소스 검색

添加接口全量查询表数据并将处理后的结果序列化到本地

DESKTOP-6LTVLN7\Liumouren 3 달 전
부모
커밋
76e5c994de

+ 21 - 0
pom.xml

@@ -82,6 +82,27 @@
             <artifactId>json-simple</artifactId>
             <version>1.1.1</version>
         </dependency>
+        <!--        xlsx读取-->
+        <dependency>
+            <groupId>org.apache.xmlbeans</groupId>
+            <artifactId>xmlbeans</artifactId>
+            <version>5.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.opencsv</groupId>
+            <artifactId>opencsv</artifactId>
+            <version>5.7.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>5.2.3</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>

+ 9 - 13
src/main/java/com/skyversation/poiaddr/addquery/AddressQueryEngine.java

@@ -46,15 +46,13 @@ public class AddressQueryEngine {
             return null;
         }
         AddressResult addressResult = new AddressResult();
-        if (addressResult.getData() == null || addressResult.getData().size() == 0) {
-            for (String addr : addrs) {
-//              创建请求
-                addressResult = sj_szxSearchByName(addr);
-                if (addressResult != null) {
-                    addressResult.setCode(AddressResultEnum.SZX_SUCCESS);
-                    addressResult.setMessage("成功");
-                    return getCjWgWgwByLoc(addressResult);
-                }
+        for (String addr : addrs) {
+            //  创建请求
+            addressResult = sj_szxSearchByName(addr);
+            if (addressResult != null) {
+                addressResult.setCode(AddressResultEnum.SZX_SUCCESS);
+                addressResult.setMessage("成功");
+                return getCjWgWgwByLoc(addressResult);
             }
         }
         addressResult.setCode(AddressResultEnum.RESULT_NULL);
@@ -108,7 +106,7 @@ public class AddressQueryEngine {
             if (!StringUtils.hasText(body))
                 return AddressTools.getInstance().faildQuery(AddressResultEnum.RESULT_NULL, "搜索无结果");
             try {
-                return TransfromDataTool.szxResultToResult(JSONObject.parseObject(body));
+                return TransfromDataTool.szxResultToResult(JSONObject.parseObject(body),address);
             } catch (Exception e) {
                 System.err.println(e);
                 return AddressTools.getInstance().faildQuery(AddressResultEnum.DATA_FROMAT_FAILD, "格式化失败");
@@ -166,10 +164,8 @@ public class AddressQueryEngine {
                     System.out.println("请求地址:" + address + ";返回结果错误:" + body);
                     return AddressTools.getInstance().faildQuery(AddressResultEnum.DATA_FROMAT_FAILD, "请求地址:" + address + ";返回结果错误:" + body);
                 } else {
-//                  匹配得到得分最高的结果
-                    JSONObject res = com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch(address, JSONArray.parseArray(body), "address");
 //                  将得分最高的结果映射到实体类
-                    return TransfromDataTool.szxResultToResult2(res);
+                    return TransfromDataTool.szxResultToResult2(com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch(address, JSONArray.parseArray(body), "address"));
                 }
             } catch (Exception e) {
                 System.err.println("请求地址:" + address + ";返回结果:" + body + ";处理异常:" + e);

+ 39 - 40
src/main/java/com/skyversation/poiaddr/addquery/TransfromDataTool.java

@@ -106,58 +106,57 @@ public class TransfromDataTool {
         return result;
     }
 
-    public static AddressResult szxResultToResult(JSONObject json) {
+    public static AddressResult szxResultToResult(JSONObject json, String searchAddress) {
         AddressResult result = new AddressResult();
         JSONArray array = json.getJSONArray("result");
         if (array == null || array.size() < 1) {
             result.setCode(AddressResultEnum.RESULT_NULL);
             return result;
         }
-        for (int i = 0; i < array.size(); i++) {
-            JSONObject jsonObject = array.getJSONObject(i);
-            AddressResult.ContentBean content = new AddressResult.ContentBean();
-            content.setType(jsonObject.getString("type_name"));
-            List<String> addressList = new ArrayList<>();
-            content.setAddress(jsonObject.getString("address"));
-            if (!jsonObject.getString("address").isEmpty()) {
-                addressList.add(jsonObject.getString("address"));
+        com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch(searchAddress, array, "address");
+        JSONObject jsonObject = com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch(searchAddress, array, "address");
+        AddressResult.ContentBean content = new AddressResult.ContentBean();
+        content.setType(jsonObject.getString("type_name"));
+        List<String> addressList = new ArrayList<>();
+        content.setAddress(jsonObject.getString("address"));
+        if (!jsonObject.getString("address").isEmpty()) {
+            addressList.add(jsonObject.getString("address"));
+        }
+        if (!jsonObject.getString("std_address").isEmpty()) {
+            addressList.add(jsonObject.getString("std_address"));
+        }
+        content.setName(jsonObject.getString("name"));
+        double[] points = new double[]{jsonObject.getJSONObject("location").getDouble("lng"),
+                jsonObject.getJSONObject("location").getDouble("lat")};
+        content.setLocation(points[0] + "," + points[1]);
+        content.setLon(points[0]);
+        content.setLat(points[1]);
+        if (jsonObject.containsKey("ext_data")) {
+            JSONObject extData = jsonObject.getJSONObject("ext_data");
+            if (extData.containsKey("address") && !extData.getString("address").isEmpty()) {
+                addressList.add(extData.getString("address"));
             }
-            if (!jsonObject.getString("std_address").isEmpty()) {
-                addressList.add(jsonObject.getString("std_address"));
+            if (extData.containsKey("source_address") && !extData.getString("source_address").isEmpty()) {
+                addressList.add(extData.getString("source_address"));
             }
-            content.setName(jsonObject.getString("name"));
-            double[] points = new double[]{jsonObject.getJSONObject("location").getDouble("lng"),
-                    jsonObject.getJSONObject("location").getDouble("lat")};
-            content.setLocation(points[0] + "," + points[1]);
-            content.setLon(points[0]);
-            content.setLat(points[1]);
-            if (jsonObject.containsKey("ext_data")) {
-                JSONObject extData = jsonObject.getJSONObject("ext_data");
-                if (extData.containsKey("address") && !extData.getString("address").isEmpty()) {
-                    addressList.add(extData.getString("address"));
-                }
-                if (extData.containsKey("source_address") && !extData.getString("source_address").isEmpty()) {
-                    addressList.add(extData.getString("source_address"));
-                }
 
-                if (extData.containsKey("region_jw") && !extData.getString("region_jw").isEmpty()) {
-                    JSONObject cjJson = new JSONObject();
-                    cjJson.put("所属街道", extData.getString("region_jd"));
-                    cjJson.put("所属居委", extData.getString("region_jw"));
-                    content.setCjJson(cjJson);
-                }
-
-            }
-            for (String item : addressList) {
-                if (item.contains("上海市") && item.contains(Constant.getArea() + "区") && item.length() > content.getAddress().length()) {
-                    content.setAddress(item);
-                }
+            if (extData.containsKey("region_jw") && !extData.getString("region_jw").isEmpty()) {
+                JSONObject cjJson = new JSONObject();
+                cjJson.put("所属街道", extData.getString("region_jd"));
+                cjJson.put("所属居委", extData.getString("region_jw"));
+                content.setCjJson(cjJson);
             }
-            if (result.getData() == null) {
-                result.setData(new ArrayList<>());
+
+        }
+        for (String item : addressList) {
+            if (item.contains("上海市") && item.contains(Constant.getArea() + "区") && item.length() > content.getAddress().length()) {
+                content.setAddress(item);
             }
-            result.getData().add(content);
         }
+        if (result.getData() == null) {
+            result.setData(new ArrayList<>());
+        }
+        result.getData().add(content);
         result.setCode(AddressResultEnum.SZX_SUCCESS);
         return result;
     }

+ 14 - 0
src/main/java/com/skyversation/poiaddr/controller/PoiAddressController.java

@@ -47,6 +47,20 @@ public class PoiAddressController {
         return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
     }
 
+    /**
+     * 全量查询表数据并将处理后的结果序列化到本地(待测试)
+     *
+     * @return
+     */
+    @PostMapping(value = "/uploadDataBaseDataToLocal", produces = MediaType.APPLICATION_JSON_VALUE)
+    public Object uploadDataBaseDataToLocal() {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        testDataService.uploadAllData(100, 1);// 记录程序结束时间
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
+    }
+
     /**
      * 直接输入sql语句执行并返回结果
      *

+ 160 - 93
src/main/java/com/skyversation/poiaddr/service/impl/SjArrDzbzhSjWcbryDzxxServiceImpl.java

@@ -5,6 +5,7 @@ import com.skyversation.poiaddr.addquery.Constant;
 import com.skyversation.poiaddr.bean.AddressResult;
 import com.skyversation.poiaddr.config.DbConnection;
 import com.skyversation.poiaddr.entity.SjArrDzbzhSjWcbryDzxx;
+import com.skyversation.poiaddr.util.SerializationUtils;
 import com.skyversation.poiaddr.util.status.AddressLevel;
 import org.springframework.stereotype.Service;
 
@@ -20,6 +21,59 @@ import java.util.concurrent.Future;
 @Service
 public class SjArrDzbzhSjWcbryDzxxServiceImpl {
 
+    public List<SjArrDzbzhSjWcbryDzxx> getAllData(Integer PageSize, Integer PageNumber) {
+        try {
+            List<SjArrDzbzhSjWcbryDzxx> requestData = new ArrayList<>();
+            StringBuilder sql = new StringBuilder();
+            sql.append("SELECT * FROM sj_zrr_dzbzh_sj_wcbry_dzxx");
+            if (PageSize != null && PageNumber != null) {
+                sql.append(" order by id limit ").append(PageSize).append(" offset ").append((PageNumber - 1) * PageSize);
+            }
+            List<Map<String, Object>> oldDbData = DbConnection.getInstance().runSqlStr(sql.toString());
+//          去重
+            Map<String, Map<String, Object>> newRequestData = new HashMap<>();
+            for (Map<String, Object> item : oldDbData) {
+                if (item.get("id") != null) {
+                    newRequestData.put(item.get("id").toString(), item);
+                }
+            }
+            List<Map<String, Object>> dbData = new ArrayList<>();
+            for (String id : newRequestData.keySet()) {
+                dbData.add(newRequestData.get(id));
+            }
+
+            for (Map<String, Object> item : dbData) {
+                SjArrDzbzhSjWcbryDzxx sjArrDzbzhSjWcbryDzxx = new SjArrDzbzhSjWcbryDzxx();
+                if (item.get("id") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setId(item.getOrDefault("id", "").toString());
+                }
+                if (item.get("jc_hjdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setJcHjdz(item.getOrDefault("jc_hjdz", "").toString());
+                }
+                if (item.get("jc_jzdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setJcJzdz(item.getOrDefault("jc_jzdz", "").toString());
+                }
+                if (item.get("sk_hjdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setSkHjdz(item.getOrDefault("sk_hjdz", "").toString());
+                }
+                if (item.get("sk_jzdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setSkJzdz(item.getOrDefault("sk_jzdz", "").toString());
+                }
+                if (item.get("sqy_hjdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setSqyHjdz(item.getOrDefault("sqy_hjdz", "").toString());
+                }
+                if (item.get("sqy_jzdz") != null) {
+                    sjArrDzbzhSjWcbryDzxx.setSqyJzdz(item.getOrDefault("sqy_jzdz", "").toString());
+                }
+                requestData.add(sjArrDzbzhSjWcbryDzxx);
+            }
+            return requestData;
+        } catch (Exception e) {
+            System.err.println("sql运行异常:" + e);
+            return null;
+        }
+    }
+
     //  分页查询地址表
     public List<SjArrDzbzhSjWcbryDzxx> getAllDataPage(int size) {
         try {
@@ -32,7 +86,6 @@ public class SjArrDzbzhSjWcbryDzxxServiceImpl {
                 if (item.get("id") != null) {
                     newRequestData.put(item.get("id").toString(), item);
                 }
-
             }
             List<Map<String, Object>> dbData = new ArrayList<>();
             for (String id : newRequestData.keySet()) {
@@ -182,6 +235,17 @@ public class SjArrDzbzhSjWcbryDzxxServiceImpl {
         return true;
     }
 
+    public void uploadAllData(int PageSize, int PageNumber) {
+        List<SjArrDzbzhSjWcbryDzxx> listData = getAllData(null, null);
+        if (listData != null && listData.size() > 0) {
+            SerializationUtils.serialize(runExecutorService(listData), "output/testDataBase_all.ser");
+//            PageSize++;
+//            uploadAllData(PageSize, PageNumber);
+//        } else {
+//            System.out.println("处理完成!");
+        }
+    }
+
     /**
      * 首先要得到一个Page<T>对象,然后判断是否还有别的数据,有的话接着请求并返回新的Page<T>对象并迭代处理数据
      * init [0:批量处理;1:初始化]
@@ -192,98 +256,8 @@ public class SjArrDzbzhSjWcbryDzxxServiceImpl {
         if (init == 0) {
             List<SjArrDzbzhSjWcbryDzxx> listData = getAllDataPage(pageSize);
             if (listData != null && listData.size() > 0) {
-                // 创建线程池
-                ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-                List<Future<?>> futures = new ArrayList<>();
-                for (SjArrDzbzhSjWcbryDzxx item : listData) {
-                    futures.add(executorService.submit(() -> {
-                        List<String> addrList = new ArrayList<>();
-                        if (item.getSkHjdz() != null && !item.getSkHjdz().isEmpty() && isOtherDistrictThanSongJiang(item.getSkHjdz())) {
-//                              实口户籍地址
-                            addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getSkHjdz()));
-                        }
-                        if (item.getSkJzdz() != null && !item.getSkJzdz().isEmpty() && isOtherDistrictThanSongJiang(item.getSkJzdz())) {
-//                              实口居住地址
-                            addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getSkJzdz()));
-                        }
-                        if (item.getJcHjdz() != null && !item.getJcHjdz().isEmpty() && isOtherDistrictThanSongJiang(item.getJcHjdz())) {
-//                              基层户籍地址
-                            addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getJcHjdz()));
-                        }
-                        if (item.getJcJzdz() != null && !item.getJcJzdz().isEmpty() && isOtherDistrictThanSongJiang(item.getJcJzdz())) {
-//                              基层居住地址
-                            addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getJcJzdz()));
-                        }
-//                          判断地址是否属于松江区
-                        if (addrList.size() > 0) {
-//                              开始查询
-                            AddressResult addressResult = AddressQueryEngine.getInstance().commonSearchByName(addrList);
-                            if (addressResult == null || addressResult.getData() == null || addressResult.getData().size() < 1) {
-                                item.setInTheArea("异常");
-                                item.setResultAddrKey("未匹配到符合规则的结果");
-                            } else {
-                                try {
-                                    for (AddressResult.ContentBean contentBean : addressResult.getData()) {
-                                        String resultAddrKey = contentBean.getAddress();
-                                        if (resultAddrKey != null && contentBean.getLon() != null && contentBean.getLat() != null && isOtherDistrictThanSongJiang(resultAddrKey)) {
-                                            String lng = contentBean.getLon() + "";
-                                            String lat = contentBean.getLat() + "";
-                                            item.setInTheArea("是");
-                                            if (contentBean.getAdname() != null && !contentBean.getAdname().isEmpty()) {
-                                                item.setTwon(contentBean.getAdname());
-                                            } else if (contentBean.getTownJson().getString("name") != null) {
-                                                item.setTwon(contentBean.getTownJson().getString("name"));
-                                            }
-                                            if (contentBean.getCityname() != null && !contentBean.getCityname().isEmpty()) {
-                                                item.setAdministrativeDivision(contentBean.getCityname());
-                                            } else if (contentBean.getAdJson().getString("name") != null) {
-                                                item.setAdministrativeDivision(contentBean.getAdJson().getString("name"));
-                                            }
-                                            item.setLat(lat);
-                                            item.setLon(lng);
-                                            item.setResultAddrKey(resultAddrKey);
-                                            item.setMarket("上海市");
-                                            item.setLevel(contentBean.getScore());
-//                                              开始规范化地址(把查询地址的市、区、街镇替换为空,然后把得到的区、街镇拼接上去)(得到区、街镇)
-                                            String oldAddress = contentBean.getSearchAddress().replaceAll("上海市", "").replaceAll("松江区", "");
-                                            String[] towns = Constant.getTowns();
-                                            for (String town : towns) {
-                                                oldAddress = oldAddress.replaceAll(town, "");
-                                            }
-                                            if (contentBean.getCjJson() != null && contentBean.getCjJson().containsKey("所属居委")) {
-                                                oldAddress = contentBean.getCjJson().getString("所属居委") + oldAddress;
-                                            }
-                                            item.setStandardizedAddress("上海市" + item.getAdministrativeDivision() + item.getTwon() + oldAddress);
-                                            break;
-                                        } else {
-                                            item.setInTheArea("异常");
-                                            item.setResultAddrKey("结果处理异常");
-                                        }
-                                    }
-                                } catch (Exception e) {
-                                    item.setInTheArea("异常");
-                                    System.err.println("查询结果处理异常:" + e);
-                                }
-                            }
-                        } else {
-//                          更新时间,添加是否松江判断字段为否
-                            item.setInTheArea("否");
-                        }
-                        item.setUpdateTime(new Date());
-                    }));
-                }
-
-                // 等待所有任务完成
-                for (Future<?> future : futures) {
-                    try {
-                        future.get();
-                    } catch (InterruptedException | ExecutionException e) {
-                        System.err.println("线程异常:" + e);
-                    }
-                }
-                // 关闭线程池
-                executorService.shutdown();
-                updateDatas(listData);
+//              批量更新处理后的数据
+                updateDatas(runExecutorService(listData));
                 long endTime = System.currentTimeMillis();
                 System.out.println("处理单批次用时" + (endTime - startTime) / 1000 + "秒!");
                 if (listData.size() > 0) {
@@ -309,4 +283,97 @@ public class SjArrDzbzhSjWcbryDzxxServiceImpl {
             }
         }
     }
+
+    public List<SjArrDzbzhSjWcbryDzxx> runExecutorService(List<SjArrDzbzhSjWcbryDzxx> listData) {
+        // 创建线程池
+        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+        List<Future<?>> futures = new ArrayList<>();
+        for (SjArrDzbzhSjWcbryDzxx item : listData) {
+            futures.add(executorService.submit(() -> {
+                List<String> addrList = new ArrayList<>();
+                if (item.getSkHjdz() != null && !item.getSkHjdz().isEmpty() && isOtherDistrictThanSongJiang(item.getSkHjdz())) {
+                    //  实口户籍地址
+                    addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getSkHjdz()));
+                }
+                if (item.getSkJzdz() != null && !item.getSkJzdz().isEmpty() && isOtherDistrictThanSongJiang(item.getSkJzdz())) {
+                    //  实口居住地址
+                    addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getSkJzdz()));
+                }
+                if (item.getJcHjdz() != null && !item.getJcHjdz().isEmpty() && isOtherDistrictThanSongJiang(item.getJcHjdz())) {
+                    //  基层户籍地址
+                    addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getJcHjdz()));
+                }
+                if (item.getJcJzdz() != null && !item.getJcJzdz().isEmpty() && isOtherDistrictThanSongJiang(item.getJcJzdz())) {
+                    //  基层居住地址
+                    addrList.add("上海市" + Constant.getArea() + "区" + AddressQueryEngine.addressReplaceAll(item.getJcJzdz()));
+                }
+                if (addrList.size() > 0) {
+                    //  TODO 开始查询
+                    AddressResult addressResult = AddressQueryEngine.getInstance().commonSearchByName(addrList);
+                    if (addressResult == null || addressResult.getData() == null || addressResult.getData().size() < 1) {
+                        item.setInTheArea("异常");
+                        item.setResultAddrKey("未匹配到符合规则的结果");
+                    } else {
+                        try {
+                            for (AddressResult.ContentBean contentBean : addressResult.getData()) {
+                                String resultAddrKey = contentBean.getAddress();
+                                if (resultAddrKey != null && contentBean.getLon() != null && contentBean.getLat() != null && isOtherDistrictThanSongJiang(resultAddrKey)) {
+                                    String lng = contentBean.getLon() + "";
+                                    String lat = contentBean.getLat() + "";
+                                    item.setInTheArea("是");
+                                    if (contentBean.getAdname() != null && !contentBean.getAdname().isEmpty()) {
+                                        item.setTwon(contentBean.getAdname());
+                                    } else if (contentBean.getTownJson().getString("name") != null) {
+                                        item.setTwon(contentBean.getTownJson().getString("name"));
+                                    }
+                                    if (contentBean.getCityname() != null && !contentBean.getCityname().isEmpty()) {
+                                        item.setAdministrativeDivision(contentBean.getCityname());
+                                    } else if (contentBean.getAdJson().getString("name") != null) {
+                                        item.setAdministrativeDivision(contentBean.getAdJson().getString("name"));
+                                    }
+                                    item.setLat(lat);
+                                    item.setLon(lng);
+                                    item.setResultAddrKey(resultAddrKey);
+                                    item.setMarket("上海市");
+                                    item.setLevel(contentBean.getScore());
+//                                              开始规范化地址(把查询地址的市、区、街镇替换为空,然后把得到的区、街镇拼接上去)(得到区、街镇)
+                                    String oldAddress = contentBean.getSearchAddress().replaceAll("上海市", "").replaceAll("松江区", "");
+                                    String[] towns = Constant.getTowns();
+                                    for (String town : towns) {
+                                        oldAddress = oldAddress.replaceAll(town, "");
+                                    }
+                                    if (contentBean.getCjJson() != null && contentBean.getCjJson().containsKey("所属居委")) {
+                                        oldAddress = contentBean.getCjJson().getString("所属居委") + oldAddress;
+                                    }
+                                    item.setStandardizedAddress("上海市" + item.getAdministrativeDivision() + item.getTwon() + oldAddress);
+                                    break;
+                                } else {
+                                    item.setInTheArea("异常");
+                                    item.setResultAddrKey("结果处理异常");
+                                }
+                            }
+                        } catch (Exception e) {
+                            item.setInTheArea("异常");
+                            System.err.println("查询结果处理异常:" + e);
+                        }
+                    }
+                } else {
+                    item.setInTheArea("否");
+                }
+                item.setUpdateTime(new Date());
+            }));
+        }
+
+        // 等待所有任务完成
+        for (Future<?> future : futures) {
+            try {
+                future.get();
+            } catch (InterruptedException | ExecutionException e) {
+                System.err.println("线程异常:" + e);
+            }
+        }
+        // 关闭线程池
+        executorService.shutdown();
+        return listData;
+    }
 }

+ 0 - 2
src/main/java/com/skyversation/poiaddr/util/AddressTools.java

@@ -484,10 +484,8 @@ public class AddressTools {
     public JSONObject findBestMatch(String address, JSONArray array, String param) {
         JSONObject bestMatch = null;
         double maxTotalScore = 0;
-
         // 处理输入地址的分词和数字前文本
         AddressInfo addressInfo = processAddress(address);
-
         for (int i = 0; i < array.size(); i++) {
             JSONObject obj = array.getJSONObject(i);
             obj.put("searchAddress", address);

+ 187 - 0
src/main/java/com/skyversation/poiaddr/util/DataExportUtil.java

@@ -0,0 +1,187 @@
+package com.skyversation.poiaddr.util;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * exportDataToZip 方法:
+ * 首先创建保存 XLSX 文件的目录。
+ * 将数据按每 10000 条进行分割。
+ * 调用 createXlsxFile 方法将每组数据生成 XLSX 文件。
+ * 调用 zipDirectory 方法将生成的 XLSX 文件目录打包成 ZIP 文件。
+ * 设置响应头,将 ZIP 文件流输出给客户端。
+ * 最后删除临时文件和目录。
+ * createXlsxFile 方法:
+ * 使用 Apache POI 库创建 XLSX 文件。
+ * 生成表头,将数据填充到表格中。
+ * 自动调整列宽。
+ * zipDirectory 方法:
+ * 使用 ZipOutputStream 将指定目录下的文件打包成 ZIP 文件。
+ * deleteDirectory 方法:
+ * 递归删除指定目录及其所有子文件和子目录。
+ */
+public class DataExportUtil {
+    public static void exportDataToZip(List<Map<String, Object>> dataList, String filePath, HttpServletResponse response,String outFileType) throws IOException {
+        // 创建保存 XLSX 文件的目录
+        File directory = new File(filePath);
+        if (!directory.exists()) {
+            directory.mkdirs();
+        }
+
+        // 分割数据,每 10000 条数据一组
+        List<List<Map<String, Object>>> dataChunks = new ArrayList<>();
+        for (int i = 0; i < dataList.size(); i += 10000) {
+            dataChunks.add(dataList.subList(i, Math.min(i + 10000, dataList.size())));
+        }
+        switch (outFileType) {
+            case "xlsx":
+                // 生成 XLSX 文件
+                for (int i = 0; i < dataChunks.size(); i++) {
+                    List<Map<String, Object>> chunk = dataChunks.get(i);
+                    String fileName = filePath + File.separator + "data_" + (i + 1) + ".xlsx";
+                    createXlsxFile(chunk, fileName);
+                }
+                break;
+            case "csv":
+                // 生成 CSV 文件
+                for (int i = 0; i < dataChunks.size(); i++) {
+                    List<Map<String, Object>> chunk = dataChunks.get(i);
+                    String fileName = filePath + File.separator + "data_" + (i + 1) + ".csv";
+                    createCsvFile(chunk, fileName);
+                }
+                break;
+            case "geojson":
+                break;
+        }
+
+        // 创建 ZIP 文件
+        String zipFilePath = filePath + File.separator + "data.zip";
+        zipDirectory(directory, zipFilePath);
+
+        // 设置响应头
+        response.setContentType("application/zip");
+        response.setHeader("Content-Disposition", "attachment; filename=data.zip");
+
+        // 输出 ZIP 文件流
+        try (ServletOutputStream outputStream = response.getOutputStream();
+             FileInputStream fileInputStream = new FileInputStream(zipFilePath)) {
+            byte[] buffer = new byte[4096];
+            int bytesRead;
+            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+            outputStream.flush();
+        }
+
+        // 删除临时文件和目录
+        deleteDirectory(directory);
+    }
+
+    private static void createXlsxFile(List<Map<String, Object>> data, String filePath) throws IOException {
+        try (Workbook workbook = new XSSFWorkbook();
+             FileOutputStream fileOut = new FileOutputStream(filePath)) {
+            Sheet sheet = workbook.createSheet("Data");
+
+            // 创建表头
+            Row headerRow = sheet.createRow(0);
+            Set<String> headers = new LinkedHashSet<>();
+            for (Map<String, Object> rowData : data) {
+                headers.addAll(rowData.keySet());
+            }
+            int columnIndex = 0;
+            for (String header : headers) {
+                Cell cell = headerRow.createCell(columnIndex++);
+                cell.setCellValue(header);
+            }
+
+            // 填充数据
+            for (int i = 0; i < data.size(); i++) {
+                Row row = sheet.createRow(i + 1);
+                columnIndex = 0;
+                for (String header : headers) {
+                    Cell cell = row.createCell(columnIndex++);
+                    Object value = data.get(i).get(header);
+                    if (value != null) {
+                        cell.setCellValue(value.toString());
+                    }
+                }
+            }
+
+            // 自动调整列宽
+            for (int i = 0; i < headers.size(); i++) {
+                sheet.autoSizeColumn(i);
+            }
+
+            workbook.write(fileOut);
+        }
+    }
+
+    private static void createCsvFile(List<Map<String, Object>> data, String filePath) throws IOException {
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
+            // 获取表头
+            Set<String> headers = new LinkedHashSet<>();
+            for (Map<String, Object> rowData : data) {
+                headers.addAll(rowData.keySet());
+            }
+
+            // 写入表头
+            writer.write(String.join(",", headers));
+            writer.newLine();
+
+            // 写入数据
+            for (Map<String, Object> rowData : data) {
+                List<String> values = new ArrayList<>();
+                for (String header : headers) {
+                    Object value = rowData.get(header);
+                    values.add(value != null ? value.toString() : "");
+                }
+                writer.write(String.join(",", values));
+                writer.newLine();
+            }
+        }
+    }
+
+    private static void zipDirectory(File directory, String zipFilePath) throws IOException {
+        try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
+            File[] files = directory.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    if (!file.isDirectory()) {
+                        try (FileInputStream fileIn = new FileInputStream(file)) {
+                            ZipEntry zipEntry = new ZipEntry(file.getName());
+                            zipOut.putNextEntry(zipEntry);
+
+                            byte[] bytes = new byte[1024];
+                            int length;
+                            while ((length = fileIn.read(bytes)) >= 0) {
+                                zipOut.write(bytes, 0, length);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean deleteDirectory(File directory) {
+        if (directory.exists()) {
+            File[] files = directory.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    if (file.isDirectory()) {
+                        deleteDirectory(file);
+                    } else {
+                        file.delete();
+                    }
+                }
+            }
+        }
+        return directory.delete();
+    }
+}

+ 40 - 0
src/main/java/com/skyversation/poiaddr/util/SerializationUtils.java

@@ -0,0 +1,40 @@
+package com.skyversation.poiaddr.util;
+
+import java.io.*;
+import java.util.List;
+
+public class SerializationUtils {
+
+    /**
+     * 将 List<T> 序列化并保存到本地文件
+     * @param list 要序列化的 List
+     * @param filePath 保存文件的路径
+     * @param <T> 泛型类型
+     */
+    public static <T extends Serializable> void serialize(List<T> list, String filePath) {
+        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {
+            oos.writeObject(list);
+            System.out.println("数据已成功序列化并保存到 " + filePath);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 从本地文件中反序列化读取 List<T>
+     * @param filePath 读取文件的路径
+     * @param <T> 泛型类型
+     * @return 反序列化后的 List
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Serializable> List<T> deserialize(String filePath) {
+        List<T> list = null;
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
+            list = (List<T>) ois.readObject();
+            System.out.println("数据已成功从 " + filePath + " 反序列化");
+        } catch (IOException | ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+}