فهرست منبع

最近添加的入湖的逻辑和分词的逻辑。

DESKTOP-6LTVLN7\Liumouren 1 ماه پیش
والد
کامیت
ca7eda694c
32فایلهای تغییر یافته به همراه2036 افزوده شده و 244 حذف شده
  1. 18 10
      pom.xml
  2. 8 1
      src/main/java/com/skyversation/poiaddr/PoiAddrApplication.java
  3. 46 15
      src/main/java/com/skyversation/poiaddr/addquery/AddressQueryEngine.java
  4. 2 0
      src/main/java/com/skyversation/poiaddr/addquery/Constant.java
  5. 7 6
      src/main/java/com/skyversation/poiaddr/addquery/TransfromDataTool.java
  6. 66 0
      src/main/java/com/skyversation/poiaddr/bean/SplitAddress.java
  7. 0 1
      src/main/java/com/skyversation/poiaddr/config/AuthInterceptor.java
  8. 0 21
      src/main/java/com/skyversation/poiaddr/config/GlobalExceptionHandler.java
  9. 80 3
      src/main/java/com/skyversation/poiaddr/controller/CorporateLibraryController.java
  10. 30 0
      src/main/java/com/skyversation/poiaddr/entity/AddrBean.java
  11. 11 2
      src/main/java/com/skyversation/poiaddr/entity/YyszAddressQp.java
  12. 1 1
      src/main/java/com/skyversation/poiaddr/service/AmapAddressV3Repository.java
  13. 20 9
      src/main/java/com/skyversation/poiaddr/service/AreaService.java
  14. 8 0
      src/main/java/com/skyversation/poiaddr/service/impl/AmapAddressV3Service.java
  15. 534 123
      src/main/java/com/skyversation/poiaddr/service/impl/YyskAddressStandardizationServiceImpl.java
  16. 1 1
      src/main/java/com/skyversation/poiaddr/service/impl/YyszAddressQpService.java
  17. 3 3
      src/main/java/com/skyversation/poiaddr/util/AddressMatcher.java
  18. 292 0
      src/main/java/com/skyversation/poiaddr/util/AddressSplitUtil.java
  19. 15 14
      src/main/java/com/skyversation/poiaddr/util/AddressTools.java
  20. 1 1
      src/main/java/com/skyversation/poiaddr/util/DataExportUtil.java
  21. 36 9
      src/main/java/com/skyversation/poiaddr/util/ExcelReaderUtils.java
  22. 1 0
      src/main/java/com/skyversation/poiaddr/util/PYVerify.java
  23. 63 12
      src/main/java/com/skyversation/poiaddr/util/SerializationUtils.java
  24. 445 0
      src/main/java/com/skyversation/poiaddr/util/ShanghaiAddressSplitUtil.java
  25. 333 0
      src/main/java/com/skyversation/poiaddr/util/lmrTools/initAddrMap.java
  26. 5 2
      src/main/java/com/skyversation/poiaddr/util/net/AddressNetTools.java
  27. 2 1
      src/main/java/com/skyversation/poiaddr/util/tasks/ScheduledTasks.java
  28. 8 9
      src/main/resources/application.properties
  29. BIN
      src/main/resources/geojson/上海市_村居边界.xlsx
  30. BIN
      src/main/resources/上海市县乡记录.xlsx
  31. BIN
      src/main/resources/全国省市县记录.xlsx
  32. BIN
      流程图.png

+ 18 - 10
pom.xml

@@ -9,11 +9,11 @@
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <groupId>com.skyversation</groupId>
-    <artifactId>poiaddr</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
-    <name>poiaddr</name>
-    <description>poiaddr</description>
-    <packaging>jar</packaging>
+    <artifactId>poiApi</artifactId>
+    <version>25.5.22</version>
+    <name>poiApi</name>
+    <description>poiApi</description>
+    <packaging>war</packaging>
     <url/>
     <licenses>
         <license/>
@@ -34,11 +34,6 @@
         <maven.compiler.target>11</maven.compiler.target>
     </properties>
     <dependencies>
-        <dependency>
-            <groupId>jakarta.persistence</groupId>
-            <artifactId>jakarta.persistence-api</artifactId>
-            <version>3.1.0</version>
-        </dependency>
         <!-- Spring Data JPA 依赖,用于简化数据库操作 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -47,6 +42,12 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
+            <!--<exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>-->
         </dependency>
         <!-- MySQL 驱动依赖 -->
         <!--        <dependency>-->
@@ -99,6 +100,13 @@
             <artifactId>javax.persistence-api</artifactId>
             <version>2.2</version>
         </dependency>
+        <!-- pom.xml -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>4.0.1</version>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>com.googlecode.json-simple</groupId>
             <artifactId>json-simple</artifactId>

+ 8 - 1
src/main/java/com/skyversation/poiaddr/PoiAddrApplication.java

@@ -2,13 +2,20 @@ package com.skyversation.poiaddr;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 import org.springframework.data.web.config.EnableSpringDataWebSupport;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
 @SpringBootApplication
 @EnableSpringDataWebSupport // 以自动处理分页参数和 Page 的序列化:
 @EnableScheduling // 定时任务支持
-public class PoiAddrApplication {
+public class PoiAddrApplication extends SpringBootServletInitializer {
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        return application.sources(PoiAddrApplication.class);
+    }
+
     public static void main(String[] args) {
         SpringApplication.run(PoiAddrApplication.class, args);
     }

+ 46 - 15
src/main/java/com/skyversation/poiaddr/addquery/AddressQueryEngine.java

@@ -48,7 +48,7 @@ public class AddressQueryEngine {
     public AddressResult commonSearchByName(List<String> addrs) {
         AddressResult addressResult = new AddressResult();
 //      数据库查询
-        for (String addr : addrs) {
+        /*for (String addr : addrs) {
             // 优先进行数据库查询
             List<AmapAddressV3> dbPois = AreaService.getInstance().getAddressPoisByAddr(addr);
             if (dbPois != null && dbPois.size() > 0) {
@@ -61,7 +61,7 @@ public class AddressQueryEngine {
                     return getCjWgWgwByLoc(addressResult);
                 }
             }
-        }
+        }*/
         /*for (String addr : addrs) {
             //  创建请求
             addressResult = sj_szxSearchByName(addr, 3);
@@ -76,22 +76,22 @@ public class AddressQueryEngine {
             //  创建请求
             addressResult = szxSearchByName(addr);
 //          TODO 高德接口无法使用,市中心的接口请求成为了最后一道防线  && ifRuleData(addressResult.getData().get(0).getScore())
-            if (addressResult != null && addressResult.getData() != null && addressResult.getData().size() > 0 && ifRuleData(addressResult.getData().get(0).getScore())) {
+            if (addressResult != null && addressResult.getData() != null && addressResult.getData().size() > 0) {
                 addressResult.setCode(AddressResultEnum.SZX_SUCCESS);
                 addressResult.setMessage("成功");
                 return getCjWgWgwByLoc(addressResult);
             }
         }
 //      TODO 如果多次尝试请求市中心地址后,还是请求失败就使用高德地名地址搜索,现在是到了上限,暂时不用
-        for (String addr : addrs) {
-            //  创建请求(要返回对应的搜索地址,返回地址,总分,市:cityname,街道:adname,村居:community)
-            addressResult = gdV3SearchByName(addr);
-            if (addressResult != null && addressResult.getData() != null && addressResult.getData().size() > 0) {
-                addressResult.setCode(AddressResultEnum.GD_SUCCESS);
-                addressResult.setMessage("成功");
-                return getCjWgWgwByLoc(addressResult);
-            }
-        }
+//        for (String addr : addrs) {
+//            //  创建请求(要返回对应的搜索地址,返回地址,总分,市:cityname,街道:adname,村居:community)
+//            addressResult = gdV3SearchByName(addr);
+//            if (addressResult != null && addressResult.getData() != null && addressResult.getData().size() > 0) {
+//                addressResult.setCode(AddressResultEnum.GD_SUCCESS);
+//                addressResult.setMessage("成功");
+//                return getCjWgWgwByLoc(addressResult);
+//            }
+//        }
         if (addressResult != null) {
             addressResult.setMessage("失败");
             addressResult.setCode(AddressResultEnum.RESULT_NULL);
@@ -176,13 +176,14 @@ public class AddressQueryEngine {
     public static Map<String, String> initSigns() {
         Map<String, String> headerMap = new HashMap<>();
         String timestamp = System.currentTimeMillis() + "";
-        String appCode = "7unv4vbwqxnq4a7m9h";
+        String appCode = "e5ptqc0y37uqqgf89s";
         String UUid = UUID.randomUUID().toString();
-        String appSecret = "w6tawvf4k3ck4ikij9";
+        String appSecret = "h0caimq0kkwnmv6y4m";
         headerMap.put("x-timestamp", timestamp);
         headerMap.put("x-appcode", appCode);
+        headerMap.put("x-appSecret", appSecret);
         headerMap.put("x-uuid", UUid);
-//                  签名
+//      签名
         headerMap.put("x-sign", AddressQueryEngine.getSigns(timestamp, appCode, UUid, appSecret));
         return headerMap;
     }
@@ -293,6 +294,36 @@ public class AddressQueryEngine {
         }
     }
 
+    public Object putDataToSJ_Big_Data(JSONObject datas) {
+        JSONObject params = new JSONObject();
+        params.put("catalogName", "松江区规范化地名地址库");
+        params.put("catalogCode", "070501723/013325");
+        params.put("timeStamp", System.currentTimeMillis());
+        JSONArray dataList = new JSONArray();
+        dataList.add(datas);
+        params.put("dataList", dataList);
+        ResponseEntity response = AddressNetTools.getInstance().requestGetOrPost(HttpMethod.POST, Constant.SJ_BIGDATA_KAFKA_URL, params, initSigns(), 0);
+        if (response != null && response.hasBody()) {
+            return response.getBody() + "";
+        }
+        return null;
+    }
+
+    public Object putDataToSJ_Big_Data2(JSONObject datas) {
+        JSONObject params = new JSONObject();
+        params.put("catalogName", "松江区2022年年报数据-外部接入");
+        params.put("catalogCode", "070501723/013417");
+        params.put("timeStamp", System.currentTimeMillis());
+        JSONArray dataList = new JSONArray();
+        dataList.add(datas);
+        params.put("dataList", dataList);
+        ResponseEntity response = AddressNetTools.getInstance().requestGetOrPost(HttpMethod.POST, Constant.SJ_BIGDATA_KAFKA_URL, params, initSigns(), 0);
+        if (response != null && response.hasBody()) {
+            return response.getBody() + "";
+        }
+        return null;
+    }
+
     /***
      * 高德普通地名搜索
      * @param address

+ 2 - 0
src/main/java/com/skyversation/poiaddr/addquery/Constant.java

@@ -30,6 +30,8 @@ public class Constant {
     //    TODO 服务器融合版地名地址接口
     public static String SJ_SZX_SEARCH_BY_NAME;
 
+    public static String SJ_BIGDATA_KAFKA_URL = "http://116.246.2.84:2222/data/kafka-api";
+
     public static void setTowns(String[] town) {
         getInstance().towns = town;
     }

+ 7 - 6
src/main/java/com/skyversation/poiaddr/addquery/TransfromDataTool.java

@@ -121,7 +121,7 @@ public class TransfromDataTool {
         }
 
         //          TODO 将请求返回的市中心结果入库到pgsql中
-        List<AmapAddressV3> amapAddressV3List = new ArrayList<>();
+        /*List<AmapAddressV3> amapAddressV3List = new ArrayList<>();
         try {
             for (int i = 0; i < array.size(); i++) {
                 JSONObject item = array.getJSONObject(i);
@@ -162,7 +162,7 @@ public class TransfromDataTool {
             }
         } catch (Exception e) {
             e.printStackTrace();
-        }
+        }*/
         JSONObject jsonObject = com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch(searchAddress, array, "address");
         if (jsonObject.containsKey("总分") && jsonObject.get("总分") != null && !jsonObject.getString("总分").isEmpty()) {
             AddressResult.ContentBean content = new AddressResult.ContentBean();
@@ -250,12 +250,13 @@ public class TransfromDataTool {
             JSONObject jsonObject = com.skyversation.poiaddr.util.AddressTools.getInstance().findBestMatch2(searchAddress, array, "address");
             if (jsonObject != null && jsonObject.containsKey("总分") && jsonObject.get("总分") != null && !jsonObject.getString("总分").isEmpty()) {
                 AddressResult.ContentBean content = new AddressResult.ContentBean();
-                if(jsonObject.getString("总分").contains("rule_")){
+                /*if(jsonObject.getString("总分").contains("rule_")){
                     content.setScore(jsonObject.getString("总分"));
                 }else{
 //                  TODO 添加规则:rule_3,代表数据库中匹配到的数据,但是不属于rule_4和rule_2的第三种规则
                     content.setScore("rule_3");
-                }
+                }*/
+                content.setScore(jsonObject.getString("总分"));
                 content.setSearchAddress(jsonObject.getString("searchAddress"));
                 content.setPname(jsonObject.getString("pname"));
                 content.setCityname(jsonObject.getString("adname"));
@@ -278,7 +279,7 @@ public class TransfromDataTool {
                 }
                 result.getData().add(content);
             }
-            if (isInserted) {
+            /*if (isInserted) {
                 //          TODO 将请求返回的高德结果入库到pgsql中
                 List<AmapAddressV3> amapAddressV3List = new ArrayList<>();
                 for (int i = 0; i < array.size(); i++) {
@@ -309,7 +310,7 @@ public class TransfromDataTool {
                 if (amapAddressV3List.size() > 0) {
                     AreaService.getInstance().saveAmapAddressV3(amapAddressV3List);
                 }
-            }
+            }*/
         } catch (Exception e) {
             e.printStackTrace();
             System.err.println("gdV3ResultToResult err:" + e);

+ 66 - 0
src/main/java/com/skyversation/poiaddr/bean/SplitAddress.java

@@ -0,0 +1,66 @@
+package com.skyversation.poiaddr.bean;
+
+import lombok.Data;
+
+/**
+ * 分割后的数据
+ * @see SplitAddress#status
+ */
+@Data
+public class SplitAddress implements Comparable<SplitAddress>{
+    private String fullAddress;
+    private String sourceAddress;
+    /**
+     * 0->正常<br/>
+     * 1->未分离区一下地址(不代表数据不可用,有可能是源地址中不存在任何行政区划)<br/>
+     * 2->外省数据<br/>
+     * 3->非地址(检查到源地址非正常地址,例如网址)<br/>
+     * 4->无法确认是否为外省
+     */
+    private int status;
+    private String addr = "";
+    private String province = "";
+    private String city = "";
+    private String district = "";
+    private String street = "";
+    private String community="";
+    private String searchAddr;
+    public boolean isSuccess(){
+        switch (status){
+            case 0: case 1: case 4:{
+                return true;
+            }
+            case 2: case 3: default:{
+                return false;
+            }
+        }
+    }
+    @Override
+    public String toString() {
+        return "AddressInfo{" +
+                "sourceAddress='" + sourceAddress + '\'' +
+                "fullAddress='" + fullAddress + '\'' +
+                ", status=" + status +
+                ", addr='" + addr + '\'' +
+                ", province='" + province + '\'' +
+                ", city='" + city + '\'' +
+                ", district='" + district + '\'' +
+                ", street='" + street + '\'' +
+                ", community='" + community + '\'' +
+                '}';
+    }
+    private int point(){
+        int output=0;
+        if (status==0||status==1)output+=1000;
+        if (status==4)output+=800;
+        if (district.isEmpty())output-=100;
+        if (street.isEmpty())output-=100;
+        if (community.isEmpty())output-=100;
+        return  output;
+
+    }
+    @Override
+    public int compareTo(SplitAddress o)throws NullPointerException {
+        return this.point()-o.point();
+    }
+}

+ 0 - 1
src/main/java/com/skyversation/poiaddr/config/AuthInterceptor.java

@@ -15,7 +15,6 @@ import java.io.PrintWriter;
 @Component
 public class AuthInterceptor implements HandlerInterceptor {
 
-
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 

+ 0 - 21
src/main/java/com/skyversation/poiaddr/config/GlobalExceptionHandler.java

@@ -1,21 +0,0 @@
-package com.skyversation.poiaddr.config;
-import org.springframework.web.bind.MissingServletRequestParameterException;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@ControllerAdvice
-public class GlobalExceptionHandler {
-
-    @ExceptionHandler(MissingServletRequestParameterException.class)
-    @ResponseBody
-    public Map<String, Object> handleMissingParams(MissingServletRequestParameterException ex) {
-        Map<String, Object> result = new HashMap<>();
-        result.put("status", 400);
-        result.put("message", "请求缺少参数:" + ex.getParameterName());
-        return result;
-    }
-}

+ 80 - 3
src/main/java/com/skyversation/poiaddr/controller/CorporateLibraryController.java

@@ -80,6 +80,7 @@ public class CorporateLibraryController {
             yyskAddressStandardizationService.searchLoadFileData(fileRootPath, startFileIndex, endFileIndex, sort);// 记录程序结束时间
             long endTime = System.currentTimeMillis();
             ScheduledTasks.taskRunStatus = false;
+            System.out.println("处理完成!用时" + (endTime - startTime) / 1000 + "秒!" + ScheduledTasks.errorCount);
             return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!" + ScheduledTasks.errorCount;
         } else {
             return "定时任务正在运行,暂不可以调用该方法!";
@@ -151,15 +152,91 @@ public class CorporateLibraryController {
      * 遍历xlsx
      * 判断level为rule_2\rule_4\>1.8的数据
      * 还要将这些数据的经纬度由sh2000转成高德坐标系
-     * 把这些数据一起保存到pg数据库中
+     * 把这些数据入湖
      *
      * @return
      */
     @PostMapping(value = "/saveFileDataToPg")
-    public Object saveFileDataToPg(@RequestParam(name = "fileRootPath") String fileRootPath, @RequestParam(name = "startFileIndex") Integer startFileIndex, @RequestParam(name = "endFileIndex") Integer endFileIndex, @RequestParam(name = "sort") Integer sort) {
+    public Object saveFileDataToPg(@RequestParam(name = "fileRootPath") String fileRootPath, @RequestParam(name = "startFileIndex") Integer startFileIndex, @RequestParam(name = "endFileIndex") Integer endFileIndex, @RequestParam(name = "sort") Integer sort, @RequestParam(name = "pageSize") Integer pageSize) {
         // 记录程序开始时间
         long startTime = System.currentTimeMillis();
-        yyskAddressStandardizationService.readFileToPg(fileRootPath, startFileIndex, endFileIndex, sort);
+        yyskAddressStandardizationService.readFileToPg(fileRootPath, startFileIndex, endFileIndex, sort, pageSize);
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!" + ScheduledTasks.OID_TAG;
+    }
+
+    /**
+     * fileRootPath:单个文件目录
+     * pageSize: 批次请求数据条数
+     *
+     * @return
+     */
+    @PostMapping(value = "/saveFileDataToPg2")
+    public Object saveFileDataToPg2(@RequestParam(name = "fileRootPath") String fileRootPath, @RequestParam(name = "pageSize") Integer pageSize) {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        yyskAddressStandardizationService.readFileToPg2(fileRootPath, pageSize);
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
+    }
+
+    /**
+     * 先获取文件内容,然后根据address当做key,standardAddress和经纬度作为value
+     * 读取结果文件,然后存成Map,接着获取经纬度
+     *
+     * @return
+     */
+    @PostMapping(value = "/saveFiles")
+    public Object saveFiles(@RequestParam(name = "fileRootPath") String fileRootPath) {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        yyskAddressStandardizationService.saveFiles(fileRootPath);
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
+    }
+
+    /**
+     * 需要迭代获取数据库中的数据
+     * 然后首先判断是否存在街镇数据,存在的话根据经纬度落点判断点位是否在这个镇里面
+     * 不存在街镇数据的话直接重新请求
+     * 最后把新的数据放到数据库里面
+     *
+     * @return
+     */
+    @PostMapping(value = "/dataCleaning")
+    public Object dataCleaning(@RequestParam(name = "page") Integer page, @RequestParam(name = "pageSize") Integer pageSize) {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        yyskAddressStandardizationService.dataCleaning(page, pageSize);
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
+    }
+
+    /**
+     * 1、分页查询所有的amapV3数据(1000条一批)
+     * 2、把amapV3转成qp表字段
+     * 3、save qp表
+     */
+    @PostMapping(value = "amapV3ToQp")
+    public Object amapV3ToQp(@RequestParam(name = "page") Integer page, @RequestParam(name = "pageSize") Integer pageSize) {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        yyskAddressStandardizationService.amapV3ToQp(page, pageSize);
+        long endTime = System.currentTimeMillis();
+        return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
+    }
+
+
+    /**
+     * 1、分页查询所有的amapV3数据(1000条一批)
+     * 2、把amapV3转成qp表字段
+     * 3、save qp表
+     */
+    @PostMapping(value = "filesToQp")
+    public Object filesToQp(@RequestParam(name = "fileRootPath") String fileRootPath, @RequestParam(name = "startFileIndex") Integer startFileIndex, @RequestParam(name = "endFileIndex") Integer endFileIndex, @RequestParam(name = "sort") Integer sort) {
+        // 记录程序开始时间
+        long startTime = System.currentTimeMillis();
+        yyskAddressStandardizationService.searchLoadFileData2(fileRootPath, startFileIndex, endFileIndex, sort);// 记录程序结束时间
         long endTime = System.currentTimeMillis();
         return "处理完成!用时" + (endTime - startTime) / 1000 + "秒!";
     }

+ 30 - 0
src/main/java/com/skyversation/poiaddr/entity/AddrBean.java

@@ -0,0 +1,30 @@
+package com.skyversation.poiaddr.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+//统一分词实体
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AddrBean {
+    //      处理前的地址
+    private String oldAddress;
+    //      省
+    private String provinces;
+    //      市
+    private String market;
+    //      区
+    private String distinguish;
+    //      镇
+    private String streetTown;
+    //      村
+    private String residentialCommittee;
+    //      路
+    private String address;
+    //      标准地址
+    private String standardAddress;
+    //      规则得分
+    private String rule;
+}

+ 11 - 2
src/main/java/com/skyversation/poiaddr/entity/YyszAddressQp.java

@@ -14,7 +14,7 @@ import java.math.BigDecimal;
 /**
  * @Description  
  * @Author  LiuMengxiang
- * @Date 2025-05-14 17:14:49 
+ * @Date 2025-05-26 11:49:24 
  */
 
 @AllArgsConstructor
@@ -24,7 +24,7 @@ import java.math.BigDecimal;
 @Table ( name ="yysz_address_qp" , schema = "")
 public class YyszAddressQp  implements Serializable {
 
-	private static final long serialVersionUID =  1012376382976936447L;
+	private static final long serialVersionUID =  4507403123713728053L;
 
 	@Id
    	@Column(name = "oid" )
@@ -218,4 +218,13 @@ public class YyszAddressQp  implements Serializable {
 
    	@Column(name = "tydz_jc" )
 	private String tydzJc;
+
+   	@Column(name = "match_level" )
+	private String matchLevel;
+
+   	@Column(name = "no1" )
+	private String no1;
+
+   	@Column(name = "no2" )
+	private String no2;
 }

+ 1 - 1
src/main/java/com/skyversation/poiaddr/service/AmapAddressV3Repository.java

@@ -12,7 +12,7 @@ import java.util.List;
 public interface AmapAddressV3Repository extends JpaRepository<AmapAddressV3, String> {
 
     // 执行自定义的SQL查询
-    @Query(value = "SELECT * FROM amap_address_v3 WHERE address ILIKE %:addr% LIMIT 20", nativeQuery = true)
+    @Query(value = "SELECT * FROM amap_address_v3 WHERE adname = '青浦区' and street_town = '香花桥街道' and address ILIKE %:addr% LIMIT 20", nativeQuery = true)
     List<AmapAddressV3> getAddressPoisByAddr(@Param("addr") String addr);
 
     @Query(value = "SELECT COUNT(*) FROM amap_address_v3", nativeQuery = true)

+ 20 - 9
src/main/java/com/skyversation/poiaddr/service/AreaService.java

@@ -18,6 +18,7 @@ import org.locationtech.jts.io.WKTReader;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.ClassPathResource;
+import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
@@ -89,7 +90,7 @@ public class AreaService {
         System.out.println("<<<<<<<<------根据配置文件为AREA赋值:" + Constant.getArea());
         System.out.println("<<<<<<<<------当前AMAP_CITY_CODE:" + Constant.getAMAP_CITY_CODE());
 //      TODO 数据库连通性测试
-        try {
+        /*try {
             long startTime = System.currentTimeMillis();
             System.out.println("<<<<<<<<------开始数据库连通性测试");
             List<AmapAddressV3> amapAddressV3List = amapAddressV3Service.getAllData();
@@ -106,10 +107,10 @@ public class AreaService {
         } catch (Exception e) {
             e.printStackTrace();
             System.err.println(">>>>>>>>------数据库连通性测试结果:" + e);
-        }
+        }*/
 
 //      TODO 网络连通性测试,可以请求一下测试的市中心地址
-        try {
+        /*try {
             System.out.println("电脑最大线程数:" + Runtime.getRuntime().availableProcessors());
             System.out.println("<<<<<<<<------开始网络连通性测试");
             long startTime = System.currentTimeMillis();
@@ -121,7 +122,15 @@ public class AreaService {
         } catch (Exception e) {
             e.printStackTrace();
             System.err.println(">>>>>>>>------网络连通性测试结果:" + e);
-        }
+        }*/
+    }
+
+    public Page<AmapAddressV3> getAmapDataByPage(Integer page, Integer pageSize){
+        return amapAddressV3Service.getDataByPages(page,pageSize);
+    }
+
+    public List<YyszAddressQp> saveYyszAddressQp(List<YyszAddressQp> amapAddressV3List){
+        return yyszAddressQpService.saveYyszAddressQp(amapAddressV3List);
     }
 
     public void initPolygons() {
@@ -171,7 +180,7 @@ public class AreaService {
     }
 
     public void saveAmapAddressV3(List<AmapAddressV3> amapAddressV3List) {
-        List<AmapAddressV3> amapAddressV3SaveList = new ArrayList<>();
+        /*List<AmapAddressV3> amapAddressV3SaveList = new ArrayList<>();
         for (AmapAddressV3 amapAddressV3 : amapAddressV3List) {
             if (!allAddressData.containsKey(amapAddressV3.getAddress())) {
                 allAddressData.put(amapAddressV3.getAddress(), amapAddressV3);
@@ -182,7 +191,9 @@ public class AreaService {
         if (amapAddressV3SaveList.size() > 0) {
             amapAddressV3Service.saveAmapAddressV3(amapAddressV3SaveList);
             amapAddressV3List.clear();
-        }
+        }*/
+        amapAddressV3Service.saveAmapAddressV3(amapAddressV3List);
+        amapAddressV3List.clear();
     }
 
     public void saveYyskAddress(List<YyskDmdzAddressStandardization> datas) {
@@ -196,7 +207,7 @@ public class AreaService {
     }
 
     public List<AmapAddressV3> getAddressPoisByAddr(String addr) {
-        List<AmapAddressV3> resultData = new ArrayList<>();
+        /*List<AmapAddressV3> resultData = new ArrayList<>();
         String[] strs = AddressMatcher.matchProvinceAndCity(addr);
         if (strs != null) {
             for (String str : strs) {
@@ -224,10 +235,10 @@ public class AreaService {
                 }
             }
         }
-        return resultData;
+        return resultData;*/
 //        TODO 使用缓存替换数据库查询
 //        System.out.println("<<<<<<<----- 开始数据库查询,数据查询地址为:" + addr);
-//        return yyszAddressQpService.getAddressPoisByAddr(addr);
+        return amapAddressV3Service.getAddressPoisByAddr(addr);
     }
 
     public GeoJsonBean isInadPolygon(double lon, double lat) {

+ 8 - 0
src/main/java/com/skyversation/poiaddr/service/impl/AmapAddressV3Service.java

@@ -3,6 +3,9 @@ package com.skyversation.poiaddr.service.impl;
 import com.skyversation.poiaddr.entity.AmapAddressV3;
 import com.skyversation.poiaddr.service.AmapAddressV3Repository;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -13,6 +16,11 @@ public class AmapAddressV3Service {
     @Autowired
     private AmapAddressV3Repository amapAddressV3Repository;
 
+    public Page<AmapAddressV3> getDataByPages(Integer page, Integer pageSize){
+        Pageable pageable = PageRequest.of(page,pageSize);
+        return amapAddressV3Repository.findAll(pageable);
+    }
+
     public List<AmapAddressV3> saveAmapAddressV3(List<AmapAddressV3> amapAddressV3List) {
         return amapAddressV3Repository.saveAll(amapAddressV3List);
     }

+ 534 - 123
src/main/java/com/skyversation/poiaddr/service/impl/YyskAddressStandardizationServiceImpl.java

@@ -1,21 +1,32 @@
 package com.skyversation.poiaddr.service.impl;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.skyversation.poiaddr.addquery.AddressQueryEngine;
 import com.skyversation.poiaddr.bean.AddressResult;
+import com.skyversation.poiaddr.bean.GeoJsonBean;
+import com.skyversation.poiaddr.bean.SplitAddress;
 import com.skyversation.poiaddr.config.DbConnection;
-import com.skyversation.poiaddr.entity.AmapAddressV3;
-import com.skyversation.poiaddr.entity.FusionKjdlTydzWf;
-import com.skyversation.poiaddr.entity.YyskAddressStandardization;
-import com.skyversation.poiaddr.entity.YyskDmdzAddressStandardization;
+import com.skyversation.poiaddr.entity.*;
 import com.skyversation.poiaddr.service.AreaService;
 import com.skyversation.poiaddr.util.*;
+import com.skyversation.poiaddr.util.lmrTools.initAddrMap;
 import com.skyversation.poiaddr.util.tasks.ScheduledTasks;
+import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Types;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
@@ -230,7 +241,329 @@ public class YyskAddressStandardizationServiceImpl {
         }
     }
 
-    public void readFileToPg(String fileRootPath, Integer startFileIndex, Integer endFileIndex, Integer sort) {
+    /**
+     * 需要迭代获取数据库中的数据
+     * 然后首先判断是否存在街镇数据,存在的话根据经纬度落点判断点位是否在这个镇里面
+     * 不存在街镇数据的话直接重新请求
+     * 最后把新的数据更新到数据库里面
+     *
+     * @param page     当前页码
+     * @param pageSize 每页数量
+     */
+    public void dataCleaning(Integer page, Integer pageSize) {
+        System.out.println("page:" + page + "pageSize:" + pageSize);
+        long startTime = System.currentTimeMillis();
+        Page<AmapAddressV3> datas = AreaService.getInstance().getAmapDataByPage(page, pageSize);
+        List<AmapAddressV3> amapAddressV3List = datas.getContent();
+//      待重跑数据列表
+        List<YyskDmdzAddressStandardization> yyskDmdzAddressStandardizationArrayList = new ArrayList<>();
+//      查询地址和amapid的绑定关系
+        Map<String, String> addr_amapId = new HashMap<>();
+//      要更新的数据列表
+        List<AmapAddressV3> updateDatas = new ArrayList<>();
+        for (AmapAddressV3 amapAddressV3 : amapAddressV3List) {
+            boolean reRun = false;
+            if (amapAddressV3.getStreetTown() == null || amapAddressV3.getStreetTown().isEmpty() || amapAddressV3.getStreetTown().contains("[]")) {
+//              街镇异常,直接重跑
+                reRun = true;
+            } else if (amapAddressV3.getStreetTown() != null && !amapAddressV3.getStreetTown().isEmpty() && !amapAddressV3.getStreetTown().contains("[]")) {
+//              传入街镇和经纬度判断是否属于这个镇(有三种情况:经纬度为空,直接重跑;经纬度为wgs84,如果在所属镇的话转换一下坐标直接update;经纬度为gd,不在所属镇,重跑)
+                if (amapAddressV3.getLat() == null || amapAddressV3.getLon() == null || amapAddressV3.getLat().isEmpty() || amapAddressV3.getLon().isEmpty()) {
+                    reRun = true;
+                } else {
+                    String town = amapAddressV3.getStreetTown();
+                    double[] wgs84lonlat = CoordTransform2.getInstance().shcj_to_wgs84(Double.parseDouble(amapAddressV3.getLon()), Double.parseDouble(amapAddressV3.getLat()));
+                    GeoJsonBean townBean = AreaService.getInstance().isInTownPolygon(wgs84lonlat[0], wgs84lonlat[1]);
+                    if (townBean == null || !townBean.getProperties().getString("name").contains(town)) {
+                        reRun = true;
+                    }
+                }
+            }
+            if (reRun) {
+                YyskDmdzAddressStandardization yyskDmdzAddressStandardization = new YyskDmdzAddressStandardization();
+                yyskDmdzAddressStandardization.setAddress(amapAddressV3.getAddress());
+                addr_amapId.put(amapAddressV3.getAddress(), amapAddressV3.getId());
+                yyskDmdzAddressStandardizationArrayList.add(yyskDmdzAddressStandardization);
+            }
+        }
+
+        List<YyskDmdzAddressStandardization> resultDataList = runExecutorService(yyskDmdzAddressStandardizationArrayList);
+
+        for (YyskDmdzAddressStandardization yyskDmdzAddressStandardization : resultDataList) {
+            if (!yyskDmdzAddressStandardization.getMatchLevel().contains("异常") && yyskDmdzAddressStandardization.getLat() != null && yyskDmdzAddressStandardization.getLon() != null) {
+                AmapAddressV3 amapAddressV3 = new AmapAddressV3();
+                amapAddressV3.setId(addr_amapId.get(yyskDmdzAddressStandardization.getAddress()));
+                amapAddressV3.setType("数据清洗");
+                amapAddressV3.setAddress(yyskDmdzAddressStandardization.getAddress());
+                double[] gdLonLat = CoordTransform2.getInstance().wgs84_to_shcj(Double.parseDouble(yyskDmdzAddressStandardization.getLon()), Double.parseDouble(yyskDmdzAddressStandardization.getLat()));
+                amapAddressV3.setLon(String.valueOf(gdLonLat[0]));
+                amapAddressV3.setLat(String.valueOf(gdLonLat[1]));
+                amapAddressV3.setLocation(yyskDmdzAddressStandardization.getLon() + "," + yyskDmdzAddressStandardization.getLat());
+                amapAddressV3.setPname(yyskDmdzAddressStandardization.getProvinces());
+                amapAddressV3.setCityname(yyskDmdzAddressStandardization.getMarket());
+                amapAddressV3.setAdname(yyskDmdzAddressStandardization.getDistinguish());
+                amapAddressV3.setStreetTown(yyskDmdzAddressStandardization.getStreetTown());
+                amapAddressV3.setResidentialCommittee(yyskDmdzAddressStandardization.getResidentialCommittee());
+                updateDatas.add(amapAddressV3);
+            }
+        }
+        System.out.println("要处理的数据条数:" + updateDatas.size());
+        if (updateDatas.size() > 0) {
+            AreaService.getInstance().saveAmapAddressV3(updateDatas);
+        }
+        long endTime = System.currentTimeMillis();
+        System.out.println("单批数据处理完成,用时:" + (endTime - startTime) / 1000 + "秒!");
+        if (datas.getTotalPages() > page) {
+            page++;
+            dataCleaning(page, pageSize);
+        }
+    }
+
+
+    /**
+     * 需要迭代获取数据库中的数据
+     * 然后首先判断是否存在街镇数据,存在的话根据经纬度落点判断点位是否在这个镇里面
+     * 不存在街镇数据的话直接重新请求
+     * 最后把新的数据更新到数据库里面
+     *
+     * @param page     当前页码
+     * @param pageSize 每页数量
+     */
+    public void amapV3ToQp(Integer page, Integer pageSize) {
+        System.out.println("page:" + page + "pageSize:" + pageSize);
+        long startTime = System.currentTimeMillis();
+        Page<AmapAddressV3> datas = AreaService.getInstance().getAmapDataByPage(page, pageSize);
+        List<AmapAddressV3> amapAddressV3List = datas.getContent();
+//      要更新的数据列表
+        List<YyszAddressQp> updateDatas = new ArrayList<>();
+        for (AmapAddressV3 amapAddressV3 : amapAddressV3List) {
+            try {
+                if (amapAddressV3.getLon() != null && amapAddressV3.getLat() != null) {
+                    YyszAddressQp yyszAddressQp = new YyszAddressQp();
+                    yyszAddressQp.setOid(ScheduledTasks.OID_TAG);
+                    ScheduledTasks.OID_TAG++;
+                    yyszAddressQp.setSourceaddress(amapAddressV3.getAddress());
+                    yyszAddressQp.setCity(amapAddressV3.getCityname());
+                    yyszAddressQp.setCounty(amapAddressV3.getAdname());
+                    yyszAddressQp.setTown(amapAddressV3.getStreetTown());
+                    yyszAddressQp.setCommunity(amapAddressV3.getResidentialCommittee());
+                    String sh2000Lon = amapAddressV3.getLon();
+                    String sh2000Lat = amapAddressV3.getLat();
+                    double[] points = CoordTransform2.getInstance().shcj_to_wgs84(
+                            Double.parseDouble(sh2000Lon), Double.parseDouble(sh2000Lat));
+//                  wgs84
+                    yyszAddressQp.setLon(BigDecimal.valueOf(points[0]));
+                    yyszAddressQp.setLat(BigDecimal.valueOf(points[1]));
+                    yyszAddressQp.setCreatetime(new Date());
+                    yyszAddressQp.setX(amapAddressV3.getLon());
+                    yyszAddressQp.setY(amapAddressV3.getLat());
+                    yyszAddressQp.setMatchLevel("amap");
+                    updateDatas.add(yyszAddressQp);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        System.out.println("要处理的数据条数:" + updateDatas.size());
+        if (updateDatas.size() > 0) {
+            AreaService.getInstance().saveYyszAddressQp(updateDatas);
+        }
+        long endTime = System.currentTimeMillis();
+        System.out.println("单批数据处理完成,用时:" + (endTime - startTime) / 1000 + "秒!");
+        updateDatas.clear();
+        if (datas.getTotalPages() > page) {
+            page++;
+            amapV3ToQp(page, pageSize);
+        }
+    }
+
+    public static void main(String[] args) {
+        try {
+            JSONObject fileDatas = parseJsonFile("C:\\Users\\Liumouren\\Desktop\\香花桥农业、资产一张图实-中间数据2.geojson");
+            JSONArray features = fileDatas.getJSONArray("features");
+            for (int i = 0; i < features.size(); i++) {
+                JSONObject item = features.getJSONObject(i);
+                JSONObject properties = item.getJSONObject("properties");
+                if (properties.getString("合同到期日期").contains("CST")) {
+                    properties.put("合同到期日期", convertToChineseDate(properties.getString("合同到期日期")));
+                }
+                if (properties.getString("合同签订日期").contains("CST")) {
+                    properties.put("合同签订日期", convertToChineseDate(properties.getString("合同签订日期")));
+                }
+            }
+            System.out.println("完成!");
+            saveJsonToFile(fileDatas, "C:\\Users\\Liumouren\\Desktop\\香花桥农业、资产一张图实-中间数据3.geojson");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    // 保存JSONObject到文件
+    public static void saveJsonToFile(JSONObject jsonObject, String filePath) throws IOException {
+        try (FileWriter file = new FileWriter(filePath)) {
+            file.write(jsonObject.toString()); // 使用缩进2空格格式化JSON
+            file.flush();
+        }
+    }
+
+    public static JSONObject parseJsonFile(String filePath) throws IOException {
+        StringBuilder contentBuilder = new StringBuilder();
+        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                contentBuilder.append(line);
+            }
+        }
+        return JSONObject.parseObject(contentBuilder.toString());
+    }
+
+    public void saveFiles(String fileRootPath) {
+        try {
+/*//          读取经纬度文件
+            List<Map<String, Object>> fileData = ExcelReaderUtils.readExcel(fileRootPath + "经纬度文件.xlsx");
+//          地址和信息的对应关系
+            Map<String, Map<String, Object>> lonLatDatas = new HashMap<>();
+            for (Map<String, Object> fileDataItem : fileData) {
+                if (fileDataItem.get("streetTown") != null && fileDataItem.get("streetTown").toString().contains("香花桥")) {
+                    lonLatDatas.put(fileDataItem.get("address").toString(), fileDataItem);
+                }
+            }
+//          读取合作社和村居文件
+            List<Map<String, Object>> fileData2 = ExcelReaderUtils.readExcel(fileRootPath + "合作社与村居对应关系.xlsx");
+            //    合作社和村居的对应关系
+            Map<String, String> hezuoshe_cunju = new HashMap<>();
+            for (Map<String, Object> fileDataItem : fileData2) {
+                hezuoshe_cunju.put(fileDataItem.get("合作社名称").toString(), fileDataItem.get("村居名称").toString());
+            }*/
+//          读取原始文件(有返回地址的替换掉,没有返回地址的保留)
+            List<Map<String, Object>> outDatas = ExcelReaderUtils.readExcel(fileRootPath + "香花桥农业、资产一张图实-中间数据3.xlsx");
+            for (Map<String, Object> item : outDatas) {
+                if (item != null) {
+                    if (item.containsKey("合同到期日期") && item.get("合同到期日期") != null && !item.get("合同到期日期").toString().isEmpty() && item.get("合同到期日期").toString().contains("CST")) {
+                        item.put("合同到期日期", convertToChineseDate(item.get("合同到期日期").toString()));
+                    }
+
+                    if (item.containsKey("合同签订日期") && item.get("合同签订日期") != null && !item.get("合同签订日期").toString().isEmpty() && item.get("合同签订日期").toString().contains("CST")) {
+                        item.put("合同签订日期", convertToChineseDate(item.get("合同签订日期").toString()));
+                    }
+                }
+            }
+
+            /*if (listData.size() > 0) {
+//              批量更新处理后的数据
+                List<YyskDmdzAddressStandardization> resultDataList = runExecutorService(listData);
+                Map<String, YyskDmdzAddressStandardization> resltItems = new HashMap<>();
+                for (YyskDmdzAddressStandardization item : resultDataList) {
+                    resltItems.put(item.getAddress(), item);
+                }
+                for (Map<String, Object> item : outDatas) {
+                    if (item != null && item.containsKey("资产地址") && item.get("资产地址") != null && !item.get("资产地址").toString().isEmpty()) {
+                        String addr = "上海市青浦区香花桥街道" + item.get("资产地址").toString();
+                        if (resltItems.containsKey(addr) && resltItems.get(addr).getStreetTown() != null && resltItems.get(addr).getStreetTown().contains("香花桥")) {
+                            String lon = resltItems.containsKey(addr) ? resltItems.get(addr).getLon() : "";
+                            String lat = resltItems.containsKey(addr) ? resltItems.get(addr).getLat() : "";
+                            String returnAddress = resltItems.containsKey(addr) ? resltItems.get(addr).getReturnAddress() : "";
+                            String residentialCommittee = resltItems.containsKey(addr) ? resltItems.get(addr).getResidentialCommittee() : "";
+                            item.put("经度", lon);
+                            item.put("纬度", lat);
+                            item.put("返回地址", returnAddress);
+                            item.put("返回村居", residentialCommittee);
+                        }
+                    }
+                }
+            }*/
+//          输出
+            ExcelReaderUtils.writeToExcel(outDatas, fileRootPath + "输出文件2.xlsx");
+            System.out.println("处理完成");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static String convertToChineseDate(String inputDate) {
+        try {
+            // 解析原始日期字符串
+            SimpleDateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
+            Date date = inputFormat.parse(inputDate);
+
+            // 转换为中文日期格式
+            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);
+            return outputFormat.format(date);
+        } catch (Exception e) {
+            System.err.println("日期解析错误: " + e.getMessage());
+            return null;
+        }
+    }
+
+    public List<YyskAddressStandardization> AmapAddressV3_to_YyskAddressStandardization(List<AmapAddressV3> datas) {
+        List<YyskAddressStandardization> yyskAddressStandardizations = new ArrayList<>();
+        for (AmapAddressV3 amapAddressV3 : datas) {
+            YyskAddressStandardization item = new YyskAddressStandardization();
+            item.setAddress(amapAddressV3.getAddress());
+            item.setDataTag(amapAddressV3.getType());
+            item.setMarket(amapAddressV3.getCityname());
+            item.setDistinguish(amapAddressV3.getAdname());
+            item.setResidentialCommittee(amapAddressV3.getResidentialCommittee());
+            item.setLon(amapAddressV3.getLon());
+            item.setLat(amapAddressV3.getLat());
+            item.setStreetTown(amapAddressV3.getStreetTown());
+            item.setProvinces(amapAddressV3.getPname());
+            yyskAddressStandardizations.add(item);
+        }
+        return yyskAddressStandardizations;
+    }
+
+    public void readFileToPg2(String fileRootPath, Integer pageSize) {
+        try {
+            List<Map<String, Object>> fileData = ExcelReaderUtils.readExcel(fileRootPath);
+            JSONObject dataList = new JSONObject();
+//          操作类型 1:新增,2:更新3:删除
+            dataList.put("optFlag", 1);
+            JSONArray datas = new JSONArray();
+            // 定义输入格式并解析字符串
+            DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+            for (int i = 0; i < fileData.size(); i++) {
+                long startTime = System.currentTimeMillis();
+                Map<String, Object> item = fileData.get(i);
+                JSONObject data = new JSONObject();
+                for (String key : item.keySet()) {
+                    if (key.equals("dsjzx_taskid")) {
+                        LocalDate date = LocalDate.parse(item.get(key).toString(), inputFormatter);
+                        // 转换为 LocalDateTime(默认时间为 00:00:00)
+                        LocalDateTime dateTime = date.atStartOfDay();
+                        // 定义输出格式并格式化日期时间
+                        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
+                        String output = dateTime.format(outputFormatter);
+                        data.put(key, output);
+                    } else {
+                        data.put(key, item.get(key));
+                    }
+                }
+                datas.add(data);
+                if (i != 0 && (i % (pageSize - 1) == 0 || i == datas.size() - 1)) {
+                    dataList.put("data", datas);
+                    try {
+                        System.out.println(AddressQueryEngine.getInstance().putDataToSJ_Big_Data2(dataList));
+                        long endTime = System.currentTimeMillis();
+                        System.out.println("处理单批次用时" + (endTime - startTime) / 1000 + "秒!");
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    datas.clear();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static String getCurrentDateTime() {
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        return now.format(formatter);
+    }
+
+    public void readFileToPg(String fileRootPath, Integer startFileIndex, Integer endFileIndex, Integer sort, Integer pageSize) {
         System.out.println("<<<<<<<<------readFileToPg{fileIndex:" + startFileIndex + "}");
         long startTime = System.currentTimeMillis();
         List<YyskAddressStandardization> listData = new ArrayList<>();
@@ -240,19 +573,19 @@ public class YyskAddressStandardizationServiceImpl {
                 YyskAddressStandardization yyskAddressStandardization = new YyskAddressStandardization();
                 String matchLevel = item.get("matchLevel").toString();
                 if (matchLevel != null && !matchLevel.isEmpty() && !"异常".equals(matchLevel) && !"rule_0".equals(matchLevel) && item.get("lat") != null && item.get("lon") != null) {
-                    if ("rule_2".equals(matchLevel) || "rule_3".equals(matchLevel) || "rule_4".equals(matchLevel) || Float.parseFloat(matchLevel) > 1.8) {
-                        yyskAddressStandardization.setAddress(item.get("address").toString());
-                        yyskAddressStandardization.setReturnAddress(item.get("returnAddress").toString());
-                        yyskAddressStandardization.setStandardAddress(item.get("standardAddress").toString());
-                        yyskAddressStandardization.setProvinces(item.get("provinces").toString());
-                        yyskAddressStandardization.setMarket(item.get("market").toString());
-                        yyskAddressStandardization.setDistinguish(item.get("distinguish").toString());
-                        yyskAddressStandardization.setStreetTown(item.get("streetTown").toString());
-                        yyskAddressStandardization.setResidentialCommittee(item.get("residentialCommittee").toString());
-                        yyskAddressStandardization.setLon(item.get("lat").toString());
-                        yyskAddressStandardization.setLat(item.get("lon").toString());
-                        listData.add(yyskAddressStandardization);
-                    }
+                    yyskAddressStandardization.setAddress(item.get("address").toString());
+                    yyskAddressStandardization.setReturnAddress(item.get("returnAddress").toString());
+                    yyskAddressStandardization.setStandardAddress(item.get("standardAddress").toString());
+                    yyskAddressStandardization.setProvinces(item.get("provinces").toString());
+                    yyskAddressStandardization.setMarket(item.get("market").toString());
+                    yyskAddressStandardization.setDistinguish(item.get("distinguish").toString());
+                    yyskAddressStandardization.setStreetTown(item.get("streetTown").toString());
+                    yyskAddressStandardization.setMatchLevel(matchLevel);
+                    yyskAddressStandardization.setResidentialCommittee(item.get("residentialCommittee").toString());
+                    yyskAddressStandardization.setLon(item.get("lat").toString());
+                    yyskAddressStandardization.setLat(item.get("lon").toString());
+                    yyskAddressStandardization.setDataTag(item.get("dataTag").toString());
+                    listData.add(yyskAddressStandardization);
                 }
             }
             fileData.clear();
@@ -260,49 +593,109 @@ public class YyskAddressStandardizationServiceImpl {
             listData = null;
         }
         if (listData != null && listData.size() > 0) {
-            List<AmapAddressV3> amapAddressV3List = new ArrayList<>();
-            for (YyskAddressStandardization yyskAddressStandardization : listData) {
-                AmapAddressV3 amapAddressV3 = new AmapAddressV3();
-                amapAddressV3.setId(UUID.randomUUID().toString());
-                amapAddressV3.setAddress(yyskAddressStandardization.getReturnAddress());
-                amapAddressV3.setLon(yyskAddressStandardization.getLon());
-                amapAddressV3.setLat(yyskAddressStandardization.getLat());
-                amapAddressV3.setPname(yyskAddressStandardization.getProvinces());
-                amapAddressV3.setCityname(yyskAddressStandardization.getMarket());
-                amapAddressV3.setAdname(yyskAddressStandardization.getDistinguish());
-                amapAddressV3.setStreetTown(yyskAddressStandardization.getStreetTown());
-                amapAddressV3.setResidentialCommittee(yyskAddressStandardization.getResidentialCommittee());
-//              上海2000转高德
-                double[] gcjLocation = Coordinate.shcj_to_gcj02(Double.parseDouble(yyskAddressStandardization.getLon()), Double.parseDouble(yyskAddressStandardization.getLat()));
-                amapAddressV3.setLocation(gcjLocation[0] + "," + gcjLocation[1]);
-                amapAddressV3.setCreateTime(new Date());
-                amapAddressV3List.add(amapAddressV3);
-
-                AmapAddressV3 amapAddressV32 = new AmapAddressV3();
-                amapAddressV32.setId(UUID.randomUUID().toString());
-                amapAddressV32.setAddress(yyskAddressStandardization.getStandardAddress());
-                amapAddressV32.setLon(amapAddressV3.getLon());
-                amapAddressV32.setLat(amapAddressV3.getLat());
-                amapAddressV32.setPname(amapAddressV3.getPname());
-                amapAddressV32.setCityname(amapAddressV3.getCityname());
-                amapAddressV32.setAdname(amapAddressV3.getAdname());
-                amapAddressV32.setStreetTown(amapAddressV3.getStreetTown());
-                amapAddressV32.setResidentialCommittee(amapAddressV3.getResidentialCommittee());
-                amapAddressV32.setLocation(amapAddressV3.getLocation());
-                amapAddressV32.setCreateTime(new Date());
-                amapAddressV3List.add(amapAddressV32);
+            JSONObject dataList = new JSONObject();
+//          操作类型 1:新增,2:更新3:删除
+            dataList.put("optFlag", 1);
+            JSONArray datas = new JSONArray();
+            for (int i = 0; i < listData.size(); i++) {
+                YyskAddressStandardization yyskAddressStandardization = listData.get(i);
+                JSONObject dataItem = new JSONObject();
+                dataItem.put("oid", ScheduledTasks.OID_TAG);
+                ScheduledTasks.OID_TAG++;
+                dataItem.put("address", yyskAddressStandardization.getAddress());
+                dataItem.put("sourceaddress", yyskAddressStandardization.getStandardAddress());
+                dataItem.put("city", yyskAddressStandardization.getMarket());
+                dataItem.put("county", yyskAddressStandardization.getDistinguish());
+                dataItem.put("town", yyskAddressStandardization.getStreetTown());
+                dataItem.put("community", yyskAddressStandardization.getResidentialCommittee());
+                dataItem.put("lon", yyskAddressStandardization.getLon());
+                dataItem.put("lat", yyskAddressStandardization.getLat());
+                dataItem.put("address_type", yyskAddressStandardization.getDataTag());
+                dataItem.put("createtime", getCurrentDateTime());
+                dataItem.put("updatetime", getCurrentDateTime());
+                dataItem.put("match_level", yyskAddressStandardization.getMatchLevel());
+                datas.add(dataItem);
+                /*if (i != 0 && (i % (pageSize - 1) == 0 || i == listData.size() - 1)) {
+                    dataList.put("data", datas);
+                    try {
+//                        System.out.println(AddressQueryEngine.getInstance().putDataToSJ_Big_Data(dataList));
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    datas.clear();
+                }*/
             }
-            //                写入到数据库中
-            AreaService.getInstance().saveAmapAddressV3(amapAddressV3List);
+            dataList.put("data", datas);
+            try {
+                System.out.println(AddressQueryEngine.getInstance().putDataToSJ_Big_Data(dataList));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            datas.clear();
             long endTime = System.currentTimeMillis();
+            dataList.clear();
             System.out.println("处理单批次用时" + (endTime - startTime) / 1000 + "秒!");
-            amapAddressV3List.clear();
         } else {
             System.out.println("该文件无有效数据!");
         }
         if (startFileIndex + sort != endFileIndex) {
             startFileIndex += sort;
-            readFileToPg(fileRootPath, startFileIndex, endFileIndex, sort);
+            readFileToPg(fileRootPath, startFileIndex, endFileIndex, sort, pageSize);
+        } else {
+            System.out.println("<<<<<<<<------任务处理完成!");
+        }
+    }
+
+
+    public void searchLoadFileData2(String fileRootPath, Integer startFileIndex, Integer endFileIndex, Integer sort) {
+        System.out.println("<<<<<<<<------readFileToPg{fileIndex:" + startFileIndex + "}");
+        long startTime = System.currentTimeMillis();
+//      要更新的数据列表
+        List<YyszAddressQp> updateDatas = new ArrayList<>();
+        try {
+            List<Map<String, Object>> fileData = ExcelReaderUtils.readExcel(fileRootPath + startFileIndex + ".xlsx");
+            for (Map<String, Object> item : fileData) {
+                String matchLevel = item.get("matchLevel").toString();
+                if (matchLevel != null && !matchLevel.isEmpty() && !"异常".equals(matchLevel) && !"rule_0".equals(matchLevel) && item.get("lat") != null && item.get("lon") != null) {
+                    try {
+                        YyszAddressQp yyszAddressQp = new YyszAddressQp();
+                        yyszAddressQp.setOid(ScheduledTasks.OID_TAG);
+                        ScheduledTasks.OID_TAG++;
+                        yyszAddressQp.setSourceaddress(item.get("standardAddress").toString());
+                        yyszAddressQp.setCity(item.get("market").toString());
+                        yyszAddressQp.setCounty(item.get("distinguish").toString());
+                        yyszAddressQp.setTown(item.get("streetTown").toString());
+                        yyszAddressQp.setCommunity(item.get("residentialCommittee").toString());
+                        String sh2000Lon = item.get("lat").toString();
+                        String sh2000Lat = item.get("lon").toString();
+                        double[] points = CoordTransform2.getInstance().shcj_to_wgs84(
+                                Double.parseDouble(sh2000Lon), Double.parseDouble(sh2000Lat));
+//                      wgs84
+                        yyszAddressQp.setLon(BigDecimal.valueOf(points[0]));
+                        yyszAddressQp.setLat(BigDecimal.valueOf(points[1]));
+                        yyszAddressQp.setCreatetime(new Date());
+                        yyszAddressQp.setX(sh2000Lon);
+                        yyszAddressQp.setY(sh2000Lat);
+                        yyszAddressQp.setMatchLevel(matchLevel);
+                        updateDatas.add(yyszAddressQp);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            fileData.clear();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (updateDatas.size() > 0) {
+            AreaService.getInstance().saveYyszAddressQp(updateDatas);
+        }
+        long endTime = System.currentTimeMillis();
+        System.out.println("单批数据处理完成,用时:" + (endTime - startTime) / 1000 + "秒!");
+        updateDatas.clear();
+        if (startFileIndex + sort != endFileIndex) {
+            startFileIndex += sort;
+            searchLoadFileData2(fileRootPath, startFileIndex, endFileIndex, sort);
         } else {
             System.out.println("<<<<<<<<------任务处理完成!");
         }
@@ -316,8 +709,8 @@ public class YyskAddressStandardizationServiceImpl {
             long startTime = System.currentTimeMillis();
             int taskId = sort * i + startFileIndex;
             // 任务执行
-            startMutilExecutor(taskId, fileRootPath + "output8\\yysk_dmdz_address_standardization_200000_" + taskId + ".xlsx",
-                    fileRootPath + "output9\\yysk_dmdz_address_standardization_200000_" + taskId + ".xlsx");
+            startMutilExecutor(taskId, fileRootPath + "output1\\yysk_dmdz_address_standardization_200000_" + taskId + ".xlsx",
+                    fileRootPath + "output2\\yysk_dmdz_address_standardization_200000_" + taskId + ".xlsx");
             long endTime = System.currentTimeMillis();
             ScheduledTasks.taskRunStatus = false;
             System.out.println("单个文件处理完成!用时" + (endTime - startTime) / 1000 + "秒!");
@@ -331,22 +724,27 @@ public class YyskAddressStandardizationServiceImpl {
         try {
             List<Map<String, Object>> fileData = ExcelReaderUtils.readExcel(filePath);
             for (Map<String, Object> item : fileData) {
-                YyskDmdzAddressStandardization yyskAddressStandardization = new YyskDmdzAddressStandardization();
-                yyskAddressStandardization.setAddress(item.getOrDefault("address", "").toString());
-                yyskAddressStandardization.setDataTag(item.getOrDefault("dataTag", "").toString());
-                yyskAddressStandardization.setMatchLevel(item.getOrDefault("matchLevel", "").toString());
-                yyskAddressStandardization.setReturnAddress(item.getOrDefault("returnAddress", "").toString());
-                yyskAddressStandardization.setStandardAddress(item.getOrDefault("standardAddress", "").toString());
-                yyskAddressStandardization.setProvinces(item.getOrDefault("provinces", "").toString());
-                yyskAddressStandardization.setMarket(item.getOrDefault("market", "").toString());
-                yyskAddressStandardization.setDistinguish(item.getOrDefault("distinguish", "").toString());
-                yyskAddressStandardization.setStreetTown(item.getOrDefault("streetTown", "").toString());
-                yyskAddressStandardization.setResidentialCommittee(item.getOrDefault("residentialCommittee", "").toString());
-                yyskAddressStandardization.setLon(item.getOrDefault("lat", "").toString());
-                yyskAddressStandardization.setLat(item.getOrDefault("lon", "").toString());
-                listData.add(yyskAddressStandardization);
+                try {
+                    YyskDmdzAddressStandardization yyskAddressStandardization = new YyskDmdzAddressStandardization();
+                    yyskAddressStandardization.setAddress(item.getOrDefault("address", "").toString());
+                    yyskAddressStandardization.setDataTag(item.getOrDefault("dataTag", "").toString());
+                    yyskAddressStandardization.setMatchLevel(item.getOrDefault("matchLevel", "").toString());
+                    yyskAddressStandardization.setReturnAddress(item.getOrDefault("returnAddress", "").toString());
+                    yyskAddressStandardization.setStandardAddress(item.getOrDefault("standardAddress", "").toString());
+                    yyskAddressStandardization.setProvinces(item.getOrDefault("provinces", "").toString());
+                    yyskAddressStandardization.setMarket(item.getOrDefault("market", "").toString());
+                    yyskAddressStandardization.setDistinguish(item.getOrDefault("distinguish", "").toString());
+                    yyskAddressStandardization.setStreetTown(item.getOrDefault("streetTown", "").toString());
+                    yyskAddressStandardization.setResidentialCommittee(item.getOrDefault("residentialCommittee", "").toString());
+                    yyskAddressStandardization.setLon(item.getOrDefault("lon", "").toString());
+                    yyskAddressStandardization.setLat(item.getOrDefault("lat", "").toString());
+                    listData.add(yyskAddressStandardization);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
             }
         } catch (Exception e) {
+            e.printStackTrace();
             listData = null;
         }
         if (listData != null && listData.size() > 0) {
@@ -363,7 +761,7 @@ public class YyskAddressStandardizationServiceImpl {
 //                System.err.println("第" + startFileIndex + "个文件入库异常:" + e);
 //            }
             long endTime = System.currentTimeMillis();
-            System.out.println("处理单批次用时" + (endTime - startTime) / 1000 + "秒!已调用市中心接口个数" + ScheduledTasks.szxRequestSize + ";已調用高德接口个数:" + ScheduledTasks.gdRequestSize);
+            System.out.println("处理单批次用时" + (endTime - startTime) / 1000 + "秒!");
         } else {
             System.out.println("<<<<<<<<------ 第" + startFileIndex + "个文件 -----任务处理完成!结果为空。。。--->>>>" + outPath);
         }
@@ -433,50 +831,62 @@ public class YyskAddressStandardizationServiceImpl {
             int finalI = i;
             futures.add(executorService.submit(() -> {
                 System.out.print(finalI + ">");
-                List<String> addrList = new ArrayList<>();
-                addrList.add(item.getAddress());
-                boolean ifSearchTag = true;
-//              首先判断是否为非上海市地址
-                String[] ams = AddressMatcher.matchProvinceAndCity(item.getAddress());
-                if (ams != null && ams[0] != null) {
-                    if (!ams[0].equals("上海市")) {
-                        item.setMatchLevel("rule_0");
-                        item.setProvinces(ams[0]);
-                        if (ScheduledTasks.errorCount.containsKey("外地数据")) {
-                            ScheduledTasks.errorCount.put("外地数据", ScheduledTasks.errorCount.get("外地数据") + 1);
-                        } else {
-                            ScheduledTasks.errorCount.put("外地数据", 1);
-                        }
-                        if (ams[1] != null) {
-                            item.setMarket(ams[1]);
-                        }
-                        ifSearchTag = false;
-                    }
-                }
-                if (item.getAddress().contains("http")) {
-                    ifSearchTag = false;
-                    item.setMatchLevel("异常");
-                    if (ScheduledTasks.errorCount.containsKey("链接数据")) {
-                        ScheduledTasks.errorCount.put("链接数据", ScheduledTasks.errorCount.get("链接数据") + 1);
-                    } else {
-                        ScheduledTasks.errorCount.put("链接数据", 1);
-                    }
-                }
-                if (item.getStandardAddress() != null && !item.getStandardAddress().isEmpty() && item.getProvinces().equals("上海市") && item.getStandardAddress().contains(item.getDistinguish())) {
-                    ifSearchTag = false;
-                    String newStandardAddress = item.getProvinces() + item.getDistinguish() + item.getStreetTown() + AddressTools.returnAddress(item.getAddress());
-                    if (!item.getStandardAddress().equals(newStandardAddress)) {
-                        if (ScheduledTasks.errorCount.containsKey("分词错误")) {
-                            ScheduledTasks.errorCount.put("分词错误", ScheduledTasks.errorCount.get("分词错误") + 1);
+                boolean reSearch = false;
+                List<String> addrs = new ArrayList<>();
+//              TODO output12规则
+                if (item.getAddress() != null && item.getReturnAddress() != null) {
+                    AddrBean addrBean1 = initAddrMap.outAddrMapInAddr(item.getAddress());
+                    AddrBean addrBean2 = initAddrMap.outAddrMapInAddr(item.getReturnAddress());
+                    boolean ifError = false;
+                    try {
+                        if (addrBean1.getRule() != null && Integer.parseInt(addrBean1.getRule()) > 0) {
+                            if (addrBean1.getMarket() != null || addrBean2.getMarket() != null) {
+                                item.setProvinces(addrBean1.getProvinces() == null ? addrBean2.getProvinces() : addrBean1.getProvinces());
+                                item.setMarket(addrBean1.getMarket() == null ? addrBean2.getMarket() : addrBean1.getMarket());
+                            }
+                            if (addrBean1.getStreetTown() != null) {
+                                item.setDistinguish(addrBean1.getDistinguish());
+                                item.setStreetTown(addrBean1.getStreetTown());
+                            } else if (addrBean2.getStreetTown() != null) {
+                                if (addrBean1.getDistinguish() != null && addrBean2.getDistinguish().contains(addrBean1.getDistinguish())) {
+                                    item.setDistinguish(addrBean2.getDistinguish());
+                                    item.setStreetTown(addrBean2.getStreetTown());
+                                } else {
+                                    ifError = true;
+                                }
+                            } else {
+                                addrs.add(item.getAddress());
+                                reSearch = true;
+                                ifError = true;
+                            }
+                            if (ifError) {
+                                item.setMatchLevel("异常");
+                                item.setStandardAddress(null);
+                            } else {
+                                item.setStandardAddress(item.getMarket() + item.getDistinguish() + item.getStreetTown() + addrBean1.getAddress());
+                                if (item.getMatchLevel().contains("异常") || item.getMatchLevel().contains("rule_0")) {
+                                    item.setMatchLevel("rule_5");
+                                }
+                            }
+                        } else if (item.getAddress() == null) {
+                            addrs.add(item.getAddress());
+                            reSearch = true;
                         } else {
-                            ScheduledTasks.errorCount.put("分词错误", 1);
+                            item.setMatchLevel("rule_0");
+//                            item.setProvinces(addrBean1.getProvinces());
+//                            item.setMarket(addrBean1.getMarket());
+//                            item.setDistinguish(addrBean1.getDistinguish());
+//                            item.setResidentialCommittee(null);
+//                            item.setStandardAddress(null);
+//                            item.setReturnAddress(null);
                         }
+                    } catch (Exception e) {
+                        e.printStackTrace();
                     }
-                    item.setStandardAddress(newStandardAddress);
                 }
-                if (ifSearchTag) {
+                if (reSearch) {
                     //  TODO 开始查询
-                    AddressResult addressResult = AddressQueryEngine.getInstance().commonSearchByName(addrList);
+                    AddressResult addressResult = AddressQueryEngine.getInstance().commonSearchByName(addrs);
                     if (addressResult == null || addressResult.getData() == null || addressResult.getData().size() < 1) {
                         item.setMatchLevel("异常");
                         item.setReturnAddress("未匹配到符合规则的结果");
@@ -490,10 +900,7 @@ public class YyskAddressStandardizationServiceImpl {
                             for (AddressResult.ContentBean contentBean : addressResult.getData()) {
                                 String resultAddrKey = contentBean.getAddress();
                                 if (resultAddrKey != null && contentBean.getLon() != null && contentBean.getLat() != null && AddressTools.isOtherDistrictThanSongJiang2(resultAddrKey)) {
-//                                  去除特殊字符
-                                    resultAddrKey = AddressTools.reOutDistinguish(contentBean.getAddress());
-//                                  根据地名地址返回到街镇一级分词,
-                                    String[] strs = AddressTools.parseAddressJZ(resultAddrKey);
+                                    AddrBean addrBean3 = initAddrMap.outAddrMapInAddr(resultAddrKey);
 //                                  遍历全国省份名称得到省名
                                     item.setProvinces(AddressTools.isOtherDistrictThanShangHai(resultAddrKey));
 //                                  写入街镇数据
@@ -501,8 +908,8 @@ public class YyskAddressStandardizationServiceImpl {
                                         item.setStreetTown(contentBean.getAdname());
                                     } else if (contentBean.getTownJson() != null && contentBean.getTownJson().getString("name") != null) {
                                         item.setStreetTown(contentBean.getTownJson().getString("name"));
-                                    } else if (strs != null && strs[2] != null) {
-                                        item.setStreetTown(strs[2]);
+                                    } else if (addrBean3.getRule() != null && addrBean3.getStreetTown() != null) {
+                                        item.setStreetTown(addrBean3.getStreetTown());
                                     } else {
                                         item.setStreetTown("");
                                     }
@@ -513,8 +920,8 @@ public class YyskAddressStandardizationServiceImpl {
                                         item.setDistinguish(contentBean.getCityname());
                                     } else if (contentBean.getAdJson() != null && contentBean.getAdJson().getString("name") != null) {
                                         item.setDistinguish(contentBean.getAdJson().getString("name"));
-                                    } else if (strs != null && strs[1] != null) {
-                                        item.setDistinguish(strs[1]);
+                                    } else if (addrBean3.getRule() != null && addrBean3.getDistinguish() != null) {
+                                        item.setDistinguish(addrBean3.getDistinguish());
                                     } else {
                                         item.setDistinguish("");
                                     }
@@ -524,6 +931,8 @@ public class YyskAddressStandardizationServiceImpl {
                                         item.setLat(latLonStr[0]);
                                         item.setLon(latLonStr[1]);
                                     }
+//                                    item.setLat(contentBean.getLat().toString());
+//                                    item.setLon(contentBean.getLon().toString());
                                     item.setReturnAddress(resultAddrKey);
                                     item.setMatchLevel(contentBean.getScore());
 //                                  判断并写入居委
@@ -534,7 +943,7 @@ public class YyskAddressStandardizationServiceImpl {
                                     } else {
                                         item.setResidentialCommittee("");
                                     }
-                                    item.setStandardAddress(item.getMarket() + item.getDistinguish() + item.getStreetTown() + AddressTools.returnAddress(contentBean.getSearchAddress()));
+                                    item.setStandardAddress(item.getMarket() + item.getDistinguish() + item.getStreetTown() + initAddrMap.outAddrMapInAddr(contentBean.getSearchAddress()).getAddress());
                                     break;
                                 } else {
                                     item.setMatchLevel("异常");
@@ -566,26 +975,28 @@ public class YyskAddressStandardizationServiceImpl {
             try {
                 future.get();
             } catch (InterruptedException | ExecutionException e) {
-//                e.printStackTrace();
+                e.printStackTrace();
 //                System.err.println("线程异常:" + e);
             }
         }
+        System.out.println("线程任务处理完成!");
         // 关闭线程池
         executorService.shutdown();
-        List<YyskDmdzAddressStandardization> dataList = new ArrayList<>();
+        return listData;
+        /*List<YyskDmdzAddressStandardization> dataList = new ArrayList<>();
         List<YyskDmdzAddressStandardization> errData = new ArrayList<>();
         for (YyskDmdzAddressStandardization item : listData) {
-            if (item.getMatchLevel() == null || item.getMatchLevel().isEmpty()) {
+            if (item.getMatchLevel() == null || item.getMatchLevel().isEmpty() || item.getMatchLevel().contains("异常")) {
                 errData.add(item);
             } else {
                 dataList.add(item);
             }
         }
         listData.clear();
-        if (errData.size() > 0) {
+        if (errData.size() > 0 && dataList.size() > 0) {
             dataList.addAll(runExecutorService(errData));
         }
-        return dataList;
+        return dataList;*/
     }
 }
 

+ 1 - 1
src/main/java/com/skyversation/poiaddr/service/impl/YyszAddressQpService.java

@@ -13,7 +13,7 @@ public class YyszAddressQpService {
     @Autowired
     private YyszAddressQpRepository yyszAddressQpRepository;
 
-    public List<YyszAddressQp> saveAmapAddressV3(List<YyszAddressQp> amapAddressV3List) {
+    public List<YyszAddressQp> saveYyszAddressQp(List<YyszAddressQp> amapAddressV3List) {
         return yyszAddressQpRepository.saveAll(amapAddressV3List);
     }
 

+ 3 - 3
src/main/java/com/skyversation/poiaddr/util/AddressMatcher.java

@@ -148,13 +148,13 @@ public class AddressMatcher {
      * @return
      */
     private static boolean isPartOfRoadName(String address, String name) {
-        boolean is = address.contains(name + "路") || address.contains(name + "大道") || address.contains(name + "街");
+        boolean is = address.contains(name + "路") || address.contains(name + "大道") || address.contains(name + "街") || address.contains(name + "社区") || address.contains("镇江");
         if (!is) {
             int index = address.indexOf(name) + name.length();
             String endStr = address.substring(index, Math.min((index + 2), address.length()));
-            if(endStr.contains("路") || endStr.contains("道") || endStr.contains("街")){
+            if (endStr.contains("路") || endStr.contains("道") || endStr.contains("街")) {
                 return true;
-            }else{
+            } else {
                 is = false;
             }
         }

+ 292 - 0
src/main/java/com/skyversation/poiaddr/util/AddressSplitUtil.java

@@ -0,0 +1,292 @@
+package com.skyversation.poiaddr.util;
+
+import java.io.InputStream;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class AddressSplitUtil {
+    /**省级行政单位简称->全称映射表
+     * 只读,请勿修改
+     * */
+    public static final Map<String,String> LEVEL_1_NAME_MAP;
+    /**市级行政单位简称->全称映射表
+     * 只读,请勿修改
+     * */
+    public static final Map<String,String> LEVEL_2_NAME_MAP;
+    /**县级行政单位简称->全称映射表
+     * 只读,请勿修改
+     * */
+    public static final Map<String,String> LEVEL_3_NAME_MAP;
+    /**省市县三级行政单位简称树
+     * 只读,请勿修改
+     * */
+    public static final Map<String,Map<String,Set<String>>> SIMPLE_NAME_TREE;
+    private static final Map<String,Set<String>> All_CITY_IN_TREE;
+
+    private static final Pattern LEVEL_1_SUFFIX_PATTERN = Pattern.compile("^(?:维吾尔|((?:(?!省|市|自治区).)*?族))?(?:省|市|自治区)");
+
+    private static final Pattern LEVEL_2_SUFFIX_PATTERN = Pattern.compile("^(?:市|自治州|地区|盟)");
+
+    private static final Pattern LEVEL_3_SUFFIX_PATTERN = Pattern.compile("^(?:县|自治县|市|区|旗|自治旗|林区|特区)");
+
+    public static final Pattern ROAD_SUFFIX_PATTERN = Pattern.compile("^(?:旅游区|[东南西北中一二三四五六七八九十公大小支新老]{0,2}(?:大街|路|大道|街|菜市场|马路|村))");
+
+    static {
+        Map<String,String> level1NameMap = new HashMap<>();
+        Map<String,String> level2NameMap = new HashMap<>();
+        Map<String,String> level3NameMap = new HashMap<>();
+        Map<String,Map<String,Set<String>>> simpleNameTree = new HashMap<>();
+        String file = "全国省市县记录.xlsx";
+        InputStream is = AddressSplitUtil.class.getResourceAsStream(file);
+        if (is==null) is= AddressSplitUtil.class.getResourceAsStream("/"+file);
+        if (is==null) throw new RuntimeException("无法找到"+file);
+        try {
+            List<Map<String, Object>> list = ExcelReaderUtils.readExcel(is);
+            for (Map<String,Object> row : list) {
+                Object level1Name = row.get("省份");
+                Object level1SimpleName = row.get("省份简称");
+                Object level2Name = row.get("地级市");
+                Object level2SimpleName = row.get("地级市简称");
+                Object level3Name = row.get("县级市");
+                Object level3SimpleName = row.get("县级市简称");
+                if (level1SimpleName != null && level1Name!=null) {
+                    level1NameMap.put(level1SimpleName.toString(), level1Name.toString());
+                }
+                if (level2SimpleName != null && level2Name!=null) {
+                    level2NameMap.put(level2SimpleName.toString(), level2Name.toString());
+                }
+                if (level3SimpleName != null && level3Name!=null) {
+                    level3NameMap.put(level3SimpleName.toString(), level3Name.toString());
+                }
+                if (level1SimpleName!=null){
+                    if (!simpleNameTree.containsKey(level1SimpleName.toString())){
+                        simpleNameTree.put(level1SimpleName.toString(),new HashMap<>());
+                    }
+                    Map<String, Set<String>> level2Map = simpleNameTree.get(level1SimpleName.toString());
+                    if (level2SimpleName!=null){
+                        if(!level2Map.containsKey(level2SimpleName.toString())){
+                            level2Map.put(level2SimpleName.toString(),new HashSet<>());
+                        }
+                        if (level3SimpleName!=null){
+                            level2Map.get(level2SimpleName.toString()).add(level3SimpleName.toString());
+                        }
+                    }
+                }
+            }
+            LEVEL_1_NAME_MAP = Collections.unmodifiableMap(level1NameMap);
+            LEVEL_2_NAME_MAP = Collections.unmodifiableMap(level2NameMap);
+            LEVEL_3_NAME_MAP = Collections.unmodifiableMap(level3NameMap);
+            Map<String,Map<String,Set<String>>> simpleNameTree_= new HashMap<>();
+            for (String key : simpleNameTree.keySet()){
+                simpleNameTree_.put(key , Collections.unmodifiableMap(simpleNameTree.get(key)));
+            }
+            SIMPLE_NAME_TREE= Collections.unmodifiableMap(simpleNameTree_);
+            All_CITY_IN_TREE= Collections.unmodifiableMap(SIMPLE_NAME_TREE.values().stream()
+                    .flatMap(map -> map.entrySet().stream())
+                    .collect(Collectors.toMap(
+                            Map.Entry::getKey,
+                            Map.Entry::getValue,
+                            (oldValue, newValue) -> newValue
+                    ))
+            );
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static class SplittingAddress {
+        int province = -1;
+        int city = -1;
+        int county = -1;
+        Map<Integer,String> provinceInChoose = new HashMap<>();
+        Map<Integer,String> cityInChoose = new HashMap<>();
+        Map<Integer,String> countyInChoose = new HashMap<>();
+        String sourceAddress ;
+        SplittingAddress(String sourceAddress){
+            this.sourceAddress=sourceAddress;
+        }
+        String[] toStringList(){
+            String[] output = new String[4];
+            output[0]=((province!=-1)?LEVEL_1_NAME_MAP.get(provinceInChoose.get(province)):"");
+            output[1]=((city!=-1)?LEVEL_2_NAME_MAP.get(cityInChoose.get(city)):"");
+            output[2]=((county!=-1)?LEVEL_3_NAME_MAP.get(countyInChoose.get(county)):"");
+            return  output;
+        }
+        String getOtherAddress(){
+            int max = Math.max(province,Math.max(county,city));
+            String maxName = "";
+            if(max==-1){
+                return sourceAddress;
+            }
+            if (province==max){
+                maxName=provinceInChoose.get(province);
+            }
+            if (city==max){
+                maxName=cityInChoose.get(city);
+            }
+            if (county==max){
+                maxName=countyInChoose.get(county);
+            }
+            String sub = sourceAddress.substring(max+maxName.length());
+            Matcher m = LEVEL_1_SUFFIX_PATTERN.matcher(sub);
+            if (m.find()){
+                sub = sub.substring(m.end());
+            }
+            m = LEVEL_2_SUFFIX_PATTERN.matcher(sub);
+            if (m.find()){
+                sub = sub.substring(m.end());
+            }
+            m = LEVEL_3_SUFFIX_PATTERN.matcher(sub);
+            if (m.find()){
+                sub = sub.substring(m.end());
+            }
+            return sub;
+        }
+        void findProvince(){
+            Map<Integer,String> results = contain(this.sourceAddress,SIMPLE_NAME_TREE.keySet());
+            for (int index : results.keySet()){
+                String name = results.get(index);
+                String sub = this.sourceAddress.substring(index+name.length());
+                //去除南京路,北京大道型选手
+                if (ROAD_SUFFIX_PATTERN.matcher(sub).find()){
+                    continue;
+                }
+                provinceInChoose.put(index,name);
+                //匹配到后缀时直接当做第一选择
+                if (LEVEL_1_SUFFIX_PATTERN.matcher(sub).find()){
+                    province = index;
+                }
+            }
+            //仅有一个选择时当成一选
+            if (provinceInChoose.size()==1){
+                province = (int)provinceInChoose.keySet().toArray()[0];
+            }
+        }
+        void findCity(){
+            Map<Integer,String> results =null;
+            //首先尝试在一选下匹配
+            if (province!=-1){
+                results  = contain(this.sourceAddress,SIMPLE_NAME_TREE.get(provinceInChoose.
+                        get(province)).keySet());
+            }
+            //一选不存在或匹配无结果,直接搜全国
+            if (results==null||results.isEmpty()){
+                results = contain(this.sourceAddress,LEVEL_2_NAME_MAP.keySet());
+            }
+
+            Iterator<Integer> iterator = results.keySet().iterator();
+            while (iterator.hasNext()) {
+                int key = iterator.next();
+                String name = results.get(key);
+                if (key > 0 && name.equals("南县") &&"滦辉甘桦灌苍阜屏定全沂莒汝衡南郁平宁思广洛商南".indexOf(sourceAddress.charAt(key - 1)) != -1) {
+                    iterator.remove();
+                }
+
+            }
+            for (int index : results.keySet()){
+                String name = results.get(index);
+                String sub = this.sourceAddress.substring(index+name.length());
+                //去除南京路,北京大道型选手
+                if (ROAD_SUFFIX_PATTERN.matcher(sub).find()){
+                    continue;
+                }
+                cityInChoose.put(index,name);
+                //匹配到后缀时直接当做第一选择
+                if (LEVEL_2_SUFFIX_PATTERN.matcher(sub).find()){
+                    city = index;
+                }
+            }
+
+            //仅有一个选择时当成一选
+            if (cityInChoose.size()==1){
+                city = (int)cityInChoose.keySet().toArray()[0];
+            }
+        }
+        void findCounty(){
+            Map<Integer,String> results = null;
+            //尝试一选
+            if (city!=-1){
+                results=contain(sourceAddress,All_CITY_IN_TREE.get(cityInChoose.get(city)));
+            }
+            //一选不存在或匹配无结果,先搜全省
+            if ((results == null || results.isEmpty()) && province != -1) {
+                results = contain(sourceAddress, SIMPLE_NAME_TREE.get(provinceInChoose.get(province)).values().stream().
+                        flatMap(Set::stream).collect(Collectors.toSet()));
+            }
+            //最后全国
+            if (results == null || results.isEmpty()) {
+                results = contain(sourceAddress, LEVEL_3_NAME_MAP.keySet());
+            }
+            for (int index : results.keySet()) {
+                String name = results.get(index);
+                String sub = this.sourceAddress.substring(index + name.length());
+                //去除南京路,北京大道型选手
+                if (ROAD_SUFFIX_PATTERN.matcher(sub).find()) {
+                    continue;
+                }
+                countyInChoose.put(index, name);
+                //匹配到后缀时直接当做第一选择
+                if (LEVEL_3_SUFFIX_PATTERN.matcher(sub).find()) {
+                    county = index;
+                }
+            }
+            //仅有一个选择时当成一选
+            if (countyInChoose.size()==1){
+                county = (int)countyInChoose.keySet().toArray()[0];
+            }
+        }
+    }
+    /**
+     * 检查字符串含有哪些字符,输出这些匹配字符的位置和字符的map
+     * @param s 被检查字符串
+     * @param nameList 检查范围
+     */
+    private static Map<Integer,String> contain(String s,Iterable<String> nameList){
+        Map<Integer,String> output = new HashMap<Integer,String>();
+        for (String name:nameList){
+            if (name.isEmpty())continue;
+            int index = -1;
+            while ((index = s.indexOf(name, index + 1)) != -1){
+                output.put(index,name);
+            }
+        }
+        return output;
+    }
+
+    /**
+     * 分离地址字符串,请优先使用shanghaiAddressSplitUtil,此类只分词到县<br/>
+     * 注意,当输入的地址错误时不会自动修正,未找到的级会被空置<br/>
+     * 例如输入"北京青浦区盈港路515号1061室" ,输出[北京市,北京市,青浦区,盈港路515号1061室]<br/>
+     * 输入"安徽怀宁县黄墩镇老埂村双闸组" ,输出[安徽省,怀宁县,黄墩镇,盈港路515号1061室]<br/>
+     * @return 结果为[省级,城级,县级,余下的部分],分离失败则返回null<br/>
+     * @see ShanghaiAddressSplitUtil
+     */
+    public static String[] splitAddress(String address){
+        SplittingAddress a = new SplittingAddress(address.replaceAll("\\s+",""));
+        a.findProvince();
+        a.findCity();
+        a.findCounty();
+        String[] output = a.toStringList();
+        output[3]=(a.getOtherAddress());
+        return output;
+
+    }
+    //测试用
+    public static void main(String[] args) {
+        System.out.println(Arrays.toString(splitAddress("安徽省安徽省颍上县垂岗乡陶嘴村东道场31号")));
+        System.out.println(Arrays.toString(splitAddress("荣乐西路1058弄32号501室")));
+        System.out.println(Arrays.toString(splitAddress("泗泾镇新家园路30弄21号402室")));
+        System.out.println(Arrays.toString(splitAddress("山东省山东省单县莱河镇宋楼行政村霍井村041号")));
+        System.out.println(Arrays.toString(splitAddress("安徽省五河县安徽省五河县朱顶乡胡庄村447号")));
+        System.out.println(Arrays.toString(splitAddress("九亭镇九亭大街506弄22号101室")));
+        System.out.println(Arrays.toString(splitAddress("陕西省宝鸡市凤翔区陕西省凤翔区尹家务乡槐中村5组024号")));
+        System.out.println(Arrays.toString(splitAddress("江苏省海门市江苏省海门市正余镇王灶河村十三组36号")));
+        System.out.println(Arrays.toString(splitAddress("泗泾镇古楼公路519弄1号1102室")));
+        System.out.println(Arrays.toString(splitAddress("奉贤县奉城镇奉粮路115号")));
+        System.out.println(Arrays.toString(splitAddress("上海市奉贤区南桥镇沪杭支路24号14幢165室")));
+        System.out.println(Arrays.toString(splitAddress("浦东新区周浦镇年家浜路10、12号1层")));
+    }
+}

+ 15 - 14
src/main/java/com/skyversation/poiaddr/util/AddressTools.java

@@ -6,8 +6,10 @@ import com.skyversation.poiaddr.addquery.AddressQueryEngine;
 import com.skyversation.poiaddr.addquery.Constant;
 import com.skyversation.poiaddr.bean.AddressResult;
 import com.skyversation.poiaddr.bean.GeoJsonBean;
+import com.skyversation.poiaddr.entity.AddrBean;
 import com.skyversation.poiaddr.entity.AmapAddressV3;
 import com.skyversation.poiaddr.service.AreaService;
+import com.skyversation.poiaddr.util.lmrTools.initAddrMap;
 import org.geotools.geojson.geom.GeometryJSON;
 import org.geotools.geometry.jts.JTSFactoryFinder;
 import org.locationtech.jts.geom.Geometry;
@@ -29,8 +31,6 @@ public class AddressTools {
     private AddressTools() {
     }
 
-    ;
-
     public static AddressTools getInstance() {
         if (instance == null) instance = new AddressTools();
         return instance;
@@ -47,15 +47,6 @@ public class AddressTools {
     private static final Map<String, Set<String>> STREET_VILLAGES_COMMUNITIES = new HashMap<>();
 
     static {
-//        // 松江区
-//        Set<String> songjiangStreets = new HashSet<>(Arrays.asList(
-//                "中山街道", "方松街道", "永丰街道", "岳阳街道",
-//                "泗泾镇", "佘山镇", "车墩镇", "新桥镇", "洞泾镇",
-//                "九亭镇", "泖港镇", "石湖荡镇", "新浜镇", "叶榭镇",
-//                "小昆山镇"
-//        ));
-//        DISTRICT_STREETS.put("松江区", songjiangStreets);
-
         // 中山街道下辖的村居
         Set<String> zhongshanCommunities = new HashSet<>(Arrays.asList(
                 "茸梅社区居委会", "方东社区居委会", "夏家浜社区居委会",
@@ -349,6 +340,7 @@ public class AddressTools {
 
     /**
      * 根据上海市标准化地址输出筛选市、区、镇后的地址
+     *
      * @param allAddress
      * @return
      */
@@ -380,6 +372,9 @@ public class AddressTools {
         if (allAddress.contains("委员会")) {
             allAddress = allAddress.substring(allAddress.indexOf("委员会") + 3);
         }
+        if (allAddress.contains("工业区")) {
+            allAddress = allAddress.substring(allAddress.indexOf("工业区") + 3);
+        }
         return allAddress;
     }
 
@@ -637,6 +632,11 @@ public class AddressTools {
             if (obj.containsKey(param) && obj.get(param) != null && !obj.getString(param).trim().isEmpty()) {
 //              得到返回的地址
                 String addr = obj.getString(param);
+                AddrBean addrBean1 = initAddrMap.outAddrMapInAddr(address);
+                AddrBean addrBean2 = initAddrMap.outAddrMapInAddr(addr);
+                if (addrBean2.getDistinguish() != null && addrBean1.getDistinguish() != null && !addrBean2.getDistinguish().contains(addrBean1.getDistinguish())) {
+                    continue;
+                }
 //              规则4判断
 //              TODO 添加校验逻辑(首先使用第4校验规则匹配,匹配不到使用第二规则,还匹配不到的话就使用打分规则)
                 Set<String> addressString = AddressQueryEngine.tokenizeString(AddressQueryEngine.townReplaceAll(addr)).get(0);
@@ -1015,8 +1015,9 @@ public class AddressTools {
      */
     public static String reOutDistinguish(String addressStr) {
         if (addressStr != null) {
-            addressStr = addressStr.replaceAll("[^\\u4e00-\\u9fa5\\da-zA-Z]", "");
+//            addressStr = addressStr.replaceAll("[^\\u4e00-\\u9fa5\\da-zA-Z]", "");
             addressStr = addressStr.replaceAll(" ", "");
+            addressStr = addressStr.replaceAll("区区", "区");
             if (!addressStr.startsWith("上海")) {
                 addressStr = "上海市" + addressStr;
             } else if (addressStr.startsWith("上海") && !addressStr.startsWith("上海市")) {
@@ -1035,10 +1036,10 @@ public class AddressTools {
             for (String distinguish : SHANGHAI_DISTRICTS) {
                 if (addressStr.startsWith("上海市" + distinguish.substring(0, distinguish.length() - 1))) {
                     distinguishName = distinguish;
-                    addressStr = "上海市" + distinguish + addressStr.substring(distinguish.length() + 2);
+                    addressStr = "上海市" + distinguish + addressStr.substring(distinguish.length() + 3);
                 } else if (addressStr.startsWith("上海市" + distinguish.substring(0, distinguish.length() - 2))) {
                     distinguishName = distinguish;
-                    addressStr = "上海市" + distinguish + addressStr.substring(distinguish.length() + 1);
+                    addressStr = "上海市" + distinguish + addressStr.substring(distinguish.length() + 2);
                 }
             }
 //          判断街镇的准确性(可能会省略【街道、镇、新镇】,也可能会替换成县)

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

@@ -27,7 +27,7 @@ import java.util.zip.ZipOutputStream;
  * 递归删除指定目录及其所有子文件和子目录。
  */
 public class DataExportUtil {
-    public static void exportDataToZip(List<Map<String, Object>> dataList, String filePath, HttpServletResponse response,String outFileType) throws IOException {
+    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()) {

+ 36 - 9
src/main/java/com/skyversation/poiaddr/util/ExcelReaderUtils.java

@@ -5,17 +5,13 @@ import com.skyversation.poiaddr.entity.YyskDmdzAddressStandardization;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
+import java.io.*;
 import java.lang.reflect.Field;
 import java.util.*;
 
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
-import java.io.FileOutputStream;
-
 /**
  * xlsx文档解析并输出内容为List<Map<String,String>>
  * 大文件分割
@@ -121,12 +117,10 @@ public class ExcelReaderUtils {
     }
 
 
-    public static List<Map<String, Object>> readExcel(String filePath) throws IOException {
+    public static List<Map<String, Object>> readExcel(InputStream is) throws Exception {
         List<Map<String, Object>> resultList = new ArrayList<>();
-        FileInputStream fis = new FileInputStream(filePath);
-        IOUtils.setByteArrayMaxOverride(400000000);
         // 创建工作簿对象,用于代表整个Excel文件
-        Workbook workbook = WorkbookFactory.create(fis);
+        Workbook workbook = WorkbookFactory.create(is);
         // 这里我们默认读取第一个工作表,如果需要读取指定名称或者索引的工作表可以进行相应修改
         Sheet sheet = workbook.getSheetAt(0);
         // 获取表头行
@@ -147,6 +141,39 @@ public class ExcelReaderUtils {
             resultList.add(rowMap);
         }
 
+        workbook.close();
+        is.close();
+        return resultList;
+    }
+
+    public static List<Map<String, Object>> readExcel(String filePath) throws IOException {
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        FileInputStream fis = new FileInputStream(filePath);
+        IOUtils.setByteArrayMaxOverride(400000000);
+        // 创建工作簿对象,用于代表整个Excel文件
+        Workbook workbook = WorkbookFactory.create(fis);
+        // 这里我们默认读取第一个工作表,如果需要读取指定名称或者索引的工作表可以进行相应修改
+        Sheet sheet = workbook.getSheetAt(0);
+        // 获取表头行
+        Row headerRow = sheet.getRow(0);
+        int headerSize = headerRow.getLastCellNum();
+
+        // 遍历数据行(从第二行开始,第一行是表头)
+        for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+            Row currentRow = sheet.getRow(rowIndex);
+            if(currentRow != null){
+                Map<String, Object> rowMap = new HashMap<>();
+                for (int cellIndex = 0; cellIndex < headerSize; cellIndex++) {
+                    Cell headerCell = headerRow.getCell(cellIndex);
+                    Cell currentCell = currentRow.getCell(cellIndex);
+                    String headerValue = getCellValue(headerCell).toString();
+                    Object currentValue = getCellValue(currentCell);
+                    rowMap.put(headerValue, currentValue);
+                }
+                resultList.add(rowMap);
+            }
+        }
+
         workbook.close();
         fis.close();
         return resultList;

+ 1 - 0
src/main/java/com/skyversation/poiaddr/util/PYVerify.java

@@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils;
 
 import javax.servlet.http.HttpServletRequest;
 
+
 public class PYVerify {
 
     private static PYVerify instance = new PYVerify();

+ 63 - 12
src/main/java/com/skyversation/poiaddr/util/SerializationUtils.java

@@ -4,10 +4,7 @@ import com.skyversation.poiaddr.addquery.AddressQueryEngine;
 import com.skyversation.poiaddr.entity.SjArrDzbzhSjWcbryDzxx;
 
 import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 public class SerializationUtils {
 
@@ -49,10 +46,64 @@ public class SerializationUtils {
     public static void main(String[] args) throws IOException {
 //        test();
 //        ruleTest("上海市松江区泗泾镇江川南路25弄19号302室", "上海市松江区洞泾镇砖桥居民委员会江川南路25弄19号302室");
-        replaceResidentialCommitteeToNull();
+//        replaceResidentialCommitteeToNull();
         /*List<SjArrDzbzhSjWcbryDzxx> listData = deserialize("output/testDataBase_all.ser");
 //      将序列化的文件转储为xlsx文件
         ExcelReaderUtils.writeClassToExcel(listData, "output/allData.xlsx");*/
+
+        List<Map<String, Object>> rootDatas = ExcelReaderUtils.readExcel("C:\\Users\\Liumouren\\Desktop\\给元以5368条.xlsx");
+        List<Map<String, Object>> meDatas = ExcelReaderUtils.readExcel("C:\\Users\\Liumouren\\Desktop\\整合数据.xlsx");
+        List<Map<String, Object>> hgDatas = ExcelReaderUtils.readExcel("C:\\Users\\Liumouren\\Desktop\\给元以5368条output-result-1.xlsx");
+        Map<String, Map<String, Object>> meDataMap = new HashMap<>();
+        for (Map<String, Object> meDataItem : meDatas) {
+            meDataMap.put(meDataItem.get("经营地址").toString(), meDataItem);
+        }
+        Map<String, Map<String, Object>> hgDataMap = new HashMap<>();
+        for (Map<String, Object> meDataItem : hgDatas) {
+            hgDataMap.put(meDataItem.get("address").toString(), meDataItem);
+        }
+        List<Map<String, Object>> outputDatas = new ArrayList<>();
+        for (Map<String, Object> item : rootDatas) {
+            String id = item.get("序号").toString();
+            if(item.get("经营地址") == null || item.get("经营地址").toString().isEmpty()){
+                Map<String, Object> outDataItem = new HashMap<>();
+                outDataItem.put("序号", id);
+                outDataItem.put("经营地址", "");
+                outDataItem.put("standardAddress", "");
+                outDataItem.put("distinguish", "");
+                outDataItem.put("streetTown", "");
+                outputDatas.add(outDataItem);
+            }else{
+                String addr = item.get("经营地址").toString();
+                if (meDataMap.containsKey(addr)) {
+                    Map<String, Object> outDataItem = new HashMap<>();
+                    outDataItem.put("序号", id);
+                    outDataItem.put("经营地址", addr);
+                    outDataItem.put("standardAddress", meDataMap.get(addr).get("standardAddress").toString());
+                    outDataItem.put("distinguish", meDataMap.get(addr).get("distinguish").toString());
+                    outDataItem.put("streetTown", meDataMap.get(addr).get("streetTown").toString());
+                    outputDatas.add(outDataItem);
+                } else if (hgDataMap.containsKey(addr)) {
+                    Map<String, Object> outDataItem = new HashMap<>();
+                    outDataItem.put("序号", id);
+                    outDataItem.put("经营地址", addr);
+                    outDataItem.put("standardAddress", "上海市" + hgDataMap.get(addr).get("所属区县").toString() + hgDataMap.get(addr).get("所属街镇").toString() + AddressTools.returnAddress(addr));
+                    outDataItem.put("distinguish", hgDataMap.get(addr).get("所属区县").toString());
+                    outDataItem.put("streetTown", hgDataMap.get(addr).get("所属街镇").toString());
+                    outputDatas.add(outDataItem);
+                    System.out.println("使用到了晗哥的数据!");
+                } else {
+                    Map<String, Object> outDataItem = new HashMap<>();
+                    outDataItem.put("序号", id);
+                    outDataItem.put("经营地址", addr);
+                    outDataItem.put("standardAddress", "");
+                    outDataItem.put("distinguish", "");
+                    outDataItem.put("streetTown", "");
+                    outputDatas.add(outDataItem);
+                }
+            }
+        }
+        ExcelReaderUtils.writeToExcel(outputDatas, "C:\\Users\\Liumouren\\Desktop\\整合数据2.xlsx");
     }
 
     public static boolean ruleTest(String address, String returnAddress) {
@@ -107,11 +158,11 @@ public class SerializationUtils {
             for (Map<String, Object> item : fileDatas) {
                 if (!"异常".equals(item.get("match_level").toString())) {
                     sum++;
-                    if("rule_2".equals(item.get("match_level").toString())){
+                    if ("rule_2".equals(item.get("match_level").toString())) {
                         rule2Sum++;
-                    }else if("rule_4".equals(item.get("match_level").toString())){
+                    } else if ("rule_4".equals(item.get("match_level").toString())) {
                         rule4Sum++;
-                    }else if (!"rule_2".equals(item.get("match_level").toString()) && !"rule_4".equals(item.get("match_level").toString())) {
+                    } else if (!"rule_2".equals(item.get("match_level").toString()) && !"rule_4".equals(item.get("match_level").toString())) {
                         //                  查询地址、主键
                         float address = Float.parseFloat(item.get("match_level").toString());
                         if (address < lecel) {
@@ -141,14 +192,14 @@ public class SerializationUtils {
     public static void replaceResidentialCommitteeToNull() {
         try {
             List<Map<String, Object>> fileDatas = ExcelReaderUtils.readExcel("output/yysk_new_wcb_address_standardization3.xlsx");
-            List<Map<String,Object>> outputDatas = new ArrayList<>();
+            List<Map<String, Object>> outputDatas = new ArrayList<>();
             for (Map<String, Object> item : fileDatas) {
-                if(!AddressTools.isOtherDistrictThanSongJiang2(item.get("address").toString())){
+                if (!AddressTools.isOtherDistrictThanSongJiang2(item.get("address").toString())) {
                     outputDatas.add(item);
-                }else if (item.get("street_town") != null && !item.get("street_town").toString().isEmpty()) {
+                } else if (item.get("street_town") != null && !item.get("street_town").toString().isEmpty()) {
                     String address = item.get("address").toString();
                     String streetTown = item.get("street_town").toString();
-                    if(address.contains("镇") && !address.contains(streetTown)){
+                    if (address.contains("镇") && !address.contains(streetTown)) {
                         outputDatas.add(item);
                     }
                 }

+ 445 - 0
src/main/java/com/skyversation/poiaddr/util/ShanghaiAddressSplitUtil.java

@@ -0,0 +1,445 @@
+package com.skyversation.poiaddr.util;
+
+import com.skyversation.poiaddr.bean.SplitAddress;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.InputStream;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Service
+public class ShanghaiAddressSplitUtil {
+    @AllArgsConstructor
+    static class threeLevelAddress{
+        String district;
+        String street;
+        String community;
+        String districtFullName;
+        String streetFullName;
+        String communityFullName;
+
+    }
+    private static Map<String,List<threeLevelAddress>> All_STREET_IN_SHANGHAI;
+    private static Map<String,List<threeLevelAddress>> All_COMMUNITY_IN_SHANGHAI;
+    private static Map<String,List<String>> DISTRICT_TO_STREET_MAP;
+    private static Map<String,List<String>> STREET_TO_COMMUNITY_MAP;
+    private static Map<String,List<String>> DISTRICT_TO_COMMUNITY_MAP;
+
+    private static final Pattern LEVEL_1_SUFFIX_PATTERN = Pattern.compile("^(?:区|新区)");
+
+    private static final Pattern LEVEL_2_SUFFIX_PATTERN = Pattern.compile("^(?:街道|路街道|镇|乡|新镇)");
+
+    private static final Pattern LEVEL_3_SUFFIX_PATTERN = Pattern.compile("^(?:居委会|管委会居委会|管委会|社区|社区居委会|居民委员会|居民区|居委|村|村委会|园区|苑|安居办|居|工作站|会)");
+
+    private static final Pattern ROAD_SUFFIX_PATTERN = AddressSplitUtil.ROAD_SUFFIX_PATTERN;
+
+    private static final Pattern UN_ADDRESS_PATTERN = Pattern.compile("http");
+    private static final Pattern OVER_SPLIT=Pattern.compile("^(?:[0123456789-\\-一二三四五六七八九十大A-za-z]{0,4}[街队组栋号站弄]|(?:车站|工业区|市场|农贸市场)(?![东南西北中一二三四五六七八九十公大小支新老]路)|[A-za-z]?[0123456789-\\-])");
+
+    private static final Pattern MULTI_ADDRESS = Pattern.compile("(?<=[0-9])[号弄]?[、—/\\\\-][0-9]+(?=[号弄])");
+    @PostConstruct
+    private void init(){
+        System.out.println("开始初始化分词器");
+        Map<String,threeLevelAddress> districtMap= new HashMap<>();
+        Map<String,List<threeLevelAddress>> streetMap= new HashMap<>();
+        Map<String,List<threeLevelAddress>> communityMap= new HashMap<>();
+        Map<String,List<String>> districtToStreetMap=new HashMap<>();
+        Map<String,List<String>> streetToCommunityMap=new HashMap<>();
+
+        String file = "上海市县乡记录.xlsx";
+        InputStream is = ShanghaiAddressSplitUtil.class.getResourceAsStream(file);
+        if (is==null) is= ShanghaiAddressSplitUtil.class.getResourceAsStream("/"+file);
+        if (is==null) throw new RuntimeException("无法找到"+file);
+        try {
+            for (Map<String, Object> row : ExcelReaderUtils.readExcel(is)) {
+                String district = Optional.ofNullable(row.get("县级市简称")).map(Object::toString).orElse("");
+                String street = Optional.ofNullable(row.get("街道简称")).map(Object::toString).orElse("");
+                String community = Optional.ofNullable(row.get("居委")).map(Object::toString).orElse("");
+                String districtFullName = Optional.ofNullable(row.get("县级市")).map(Object::toString).orElse("");
+                String streetFullName = Optional.ofNullable(row.get("街道")).map(Object::toString).orElse("");
+                String communityFullName = Optional.ofNullable(row.get("居委")).map(Object::toString).orElse("");
+                initData(district, street, community, districtFullName, streetFullName, communityFullName, districtMap, streetMap, communityMap, districtToStreetMap, streetToCommunityMap);
+            }
+            //自贸区
+            initData("浦东",  "试验区","", "浦东新区", "自由贸易试验区","",  districtMap, streetMap, communityMap, districtToStreetMap, streetToCommunityMap);
+            //松江镇特别处理
+            initData("松江",  "松江","", "松江区", "","",  districtMap, streetMap, communityMap, districtToStreetMap, streetToCommunityMap);
+            //金山工业区
+            initData("金山",  "金山工业区","", "金山区", "金山工业区","",  districtMap, streetMap, communityMap, districtToStreetMap, streetToCommunityMap);
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        All_STREET_IN_SHANGHAI = Collections.unmodifiableMap(streetMap);
+        All_COMMUNITY_IN_SHANGHAI = Collections.unmodifiableMap(communityMap);
+        DISTRICT_TO_STREET_MAP=Collections.unmodifiableMap(districtToStreetMap);
+        STREET_TO_COMMUNITY_MAP=Collections.unmodifiableMap(streetToCommunityMap);
+        DISTRICT_TO_COMMUNITY_MAP=Collections.unmodifiableMap(DISTRICT_TO_STREET_MAP.entrySet().stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().stream()
+                                .flatMap(street -> STREET_TO_COMMUNITY_MAP.getOrDefault(street, Collections.emptyList()).stream())
+                                .collect(Collectors.toList())
+                )));
+        System.out.println("分词器初始化完成");
+    }
+
+    private static void initData(String district, String street, String community, String districtFullName, String streetFullName, String communityFullName, Map<String, threeLevelAddress> districtMap, Map<String, List<threeLevelAddress>> streetMap, Map<String, List<threeLevelAddress>> communityMap, Map<String, List<String>> districtToStreetMap, Map<String, List<String>> streetToCommunityMap) {
+        threeLevelAddress add = new threeLevelAddress(district, street, community, districtFullName, streetFullName, communityFullName);
+        districtMap.put(district,add);
+        if (!streetMap.containsKey(street)) streetMap.put(street,new ArrayList<>());
+        streetMap.get(street).add(add);
+        if (!communityMap.containsKey(community)) communityMap.put(community,new ArrayList<>());
+        communityMap.get(community).add(add);
+        if (!districtToStreetMap.containsKey(district)) districtToStreetMap.put(district,new ArrayList<>());
+        districtToStreetMap.get(district).add(street);
+        if (!streetToCommunityMap.containsKey(street)) streetToCommunityMap.put(street,new ArrayList<>());
+        streetToCommunityMap.get(street).add(community);
+    }
+
+    private static class splittingAddress{
+        SplitAddress splitAddress;
+
+        int street=-1;
+        int community=-1;
+
+        Map<Integer,String> streetMap =new HashMap<>();
+        Map<Integer,String> communityMap=new HashMap<>();
+        threeLevelAddress threeLevelAddress;
+
+        String targetString;
+
+        void findStreet(){
+            Map<Integer,String> results =null;
+            int completeMatchIndex=-1;
+            //首先尝试在一选下匹配
+            if (splitAddress.getDistrict()!=null){
+                results  = contain(this.targetString,DISTRICT_TO_STREET_MAP.get(splitAddress.getDistrict()),0);
+                completeMatchIndex = washResult(this.targetString,results,LEVEL_2_SUFFIX_PATTERN,LEVEL_3_SUFFIX_PATTERN,LEVEL_1_SUFFIX_PATTERN);
+            }
+            //一选不存在或匹配无结果,直接搜全国
+            if (results==null||results.isEmpty()){
+                results = contain(this.targetString,All_STREET_IN_SHANGHAI.keySet(),0);
+                if (completeMatchIndex==-1)completeMatchIndex = washResult(this.targetString,results,LEVEL_2_SUFFIX_PATTERN,LEVEL_3_SUFFIX_PATTERN,LEVEL_1_SUFFIX_PATTERN);
+
+            }
+
+            streetMap.putAll(results);
+            street=completeMatchIndex;
+            //仅有一个选择时当成一选
+            if (streetMap.size()==1){
+                street = (int)streetMap.keySet().toArray()[0];
+            }
+
+        }
+
+        void findCommunity(){
+            Map<Integer,String> results = null;
+            int completeMatchCommunity=-1;
+            String sub=targetString;
+            //尝试一选
+            if (street!=-1){
+                sub = targetString.substring(street+streetMap.get(street).length());
+                Matcher m = LEVEL_2_SUFFIX_PATTERN.matcher(sub);
+                if (m.find()){
+                    sub=sub.substring(m.end());
+                }
+                results= contain(sub,STREET_TO_COMMUNITY_MAP.get(streetMap.get(street)),targetString.length()-sub.length());
+                completeMatchCommunity=washResult(targetString,results,LEVEL_3_SUFFIX_PATTERN,LEVEL_1_SUFFIX_PATTERN,LEVEL_2_SUFFIX_PATTERN);
+
+            }
+            //一选不存在或匹配无结果,先搜全区
+            if ((results == null || results.isEmpty()) && splitAddress.getDistrict()!=null) {
+                results = contain(sub, DISTRICT_TO_COMMUNITY_MAP.get(splitAddress.getDistrict()),targetString.length()-sub.length());
+                if (completeMatchCommunity==-1)completeMatchCommunity=washResult(targetString,results,LEVEL_3_SUFFIX_PATTERN,LEVEL_1_SUFFIX_PATTERN,LEVEL_2_SUFFIX_PATTERN);
+            }
+            //最后全市
+            if (results == null || results.isEmpty()) {
+                results = contain(sub, All_COMMUNITY_IN_SHANGHAI.keySet(),targetString.length()-sub.length());
+                if (completeMatchCommunity==-1)completeMatchCommunity=washResult(targetString,results,LEVEL_3_SUFFIX_PATTERN,LEVEL_1_SUFFIX_PATTERN,LEVEL_2_SUFFIX_PATTERN);
+            }
+            Iterator<Integer> iterator = results.keySet().iterator();
+            while (iterator.hasNext()) {
+                int key = iterator.next();
+                String name = results.get(key);
+                if (key > 0 && name.equals("江镇") && targetString.charAt(key - 1) == '松') {
+                    iterator.remove();
+                }
+            }
+            communityMap.putAll(results);
+            //仅有一个选择时当成一选
+            if (communityMap.size()==1){
+                int index = (int)communityMap.keySet().toArray()[0];
+                if (street!=index)community=index;
+            }
+
+        }
+
+        void matchThreeLevelAdd(){
+            int handingPoint=0;
+            threeLevelAddress handingTLA=new threeLevelAddress("","","","","","");
+            for (String communityName: new HashSet<>(communityMap.values())){
+                if (communityName.isEmpty())continue;
+                for(threeLevelAddress t:All_COMMUNITY_IN_SHANGHAI.get(communityName)){
+                    int point = checkTLA(t);
+                    if (point==221){
+                        threeLevelAddress=t;
+                        return;
+                    }else if (point>handingPoint){
+                        handingPoint=point;
+                        handingTLA=t;
+                    }
+                }
+            }
+            for (String streetName:new HashSet<>(streetMap.values())){
+                if (streetName.isEmpty())continue;
+                for(threeLevelAddress t:All_STREET_IN_SHANGHAI.get(streetName)){
+                    int point = checkTLA(t);
+                    if (point==2111){
+                        threeLevelAddress=t;
+                        return;
+                    }else if (point>handingPoint){
+                        handingPoint=point;
+                        handingTLA=t;
+                    }
+                }
+            }
+            threeLevelAddress = handingTLA;
+        }
+        int checkTLA(threeLevelAddress t){
+            int output=0;
+            if (t.district.equals(splitAddress.getDistrict()))output+=1;
+            if (streetMap.containsValue(t.street))output+=10;
+            if (street!=-1&&streetMap.get(street).equals(t.street))output+=1000;
+            if (communityMap.containsValue(t.community))output+=100;
+            if (community!=-1&&communityMap.get(community).equals(t.community))output+=1000;
+            if (community!=-1&&Pattern.matches(".*\\d$",communityMap.get(community)))output-=1000;
+            return output;
+        }
+        void guessFirstMatch(){
+            //先街道
+            if (!streetMap.isEmpty()&&street==-1) {
+                for (int i :streetMap.keySet()){
+                    if (streetMap.get(i).equals(threeLevelAddress.street)&&(i<street||street==-1)) {
+                        street=i;
+                    }
+                }
+            }
+            //再居委
+            if (community==-1&& !communityMap.isEmpty()){
+                for (int i :communityMap.keySet()){
+                    if (communityMap.get(i).equals(threeLevelAddress.community)&&street!=i&&(i<community||community==-1)){
+                        community=i;
+                    }
+                }
+
+            }
+
+        }
+    }
+
+    static int washResult(String sourceAddress, Map<Integer, String> result, Pattern should, Pattern... never){
+        Map<Integer,String> output=new HashMap<>();
+        int outputInt = -1;
+        for (int index : result.keySet()) {
+            String name = result.get(index);
+            String sub =sourceAddress.substring(index + name.length());
+            //匹配到后缀时直接保留
+            if (should.matcher(sub).find()) {
+                outputInt=index;
+            } else {
+                //去除南京路,北京大道型选手
+                if (ROAD_SUFFIX_PATTERN.matcher(sub).find()) {
+                    continue;
+                }
+                boolean skip =false;
+                for (Pattern p :never){
+                    if (p.matcher(sub).find())skip=true;
+                }
+                if (skip) continue;
+            }
+            output.put(index,name);
+        }
+        result.clear();
+        result.putAll(output);
+        return outputInt;
+    }
+
+    /**
+     * 检查字符串含有哪些字符,输出这些匹配字符的位置和字符的map
+     * @param s 被检查字符串
+     * @param nameList 检查范围
+     */
+    private static Map<Integer,String> contain(String s,Iterable<String> nameList,int offset){
+        Map<Integer,String> output = new HashMap<>();
+        if (nameList==null){
+            return output;
+        }
+        for (String name:nameList){
+            if (name.isEmpty())continue;
+            int index = -1;
+            while ((index = s.indexOf(name, index + 1)) != -1){
+                output.put(index+offset,name);
+            }
+        }
+        return output;
+    }
+    private static SplitAddress split(String sourceAddress){
+        //事前准备
+        String beautyAddress = sourceAddress.replaceAll("[\\s]+","");
+
+        SplitAddress splitAddress = new SplitAddress();
+        splitAddress.setFullAddress(sourceAddress);
+
+
+        splittingAddress splittingAddress = new splittingAddress();
+        splittingAddress.splitAddress=splitAddress;
+
+
+        String[] result = AddressSplitUtil.splitAddress(beautyAddress);
+
+
+        splitAddress.setProvince(result[0]);
+        splitAddress.setCity(result[1]);
+        splitAddress.setDistrict(result[2]);
+        //检查是否在外省,未找到省市或者在省市中找到上海,或者找到上海的区都算作省内
+        Map<Integer, String> districtContainResult = contain(beautyAddress, DISTRICT_TO_COMMUNITY_MAP.keySet(), 0);
+        washResult(beautyAddress, districtContainResult,LEVEL_1_SUFFIX_PATTERN);
+        if (!((result[0].isEmpty()|| result[0].equals("上海市")) && (result[1].isEmpty()  || result[1].equals("上海市")||
+                !districtContainResult.isEmpty()))) {
+            splitAddress.setStatus(2);
+            splitAddress.setAddr(result[3]);
+            return splitAddress;
+        }
+        splitAddress.setProvince("上海市");
+        splitAddress.setCity("上海市");
+        splittingAddress.targetString = beautyAddress;
+        //开始省内分词
+        splittingAddress.findStreet();
+        splittingAddress.findCommunity();
+        splittingAddress.matchThreeLevelAdd();
+        splittingAddress.guessFirstMatch();
+
+        if (splittingAddress.street!=-1||splittingAddress.community!=-1)splitAddress.setStreet(splittingAddress.threeLevelAddress.streetFullName);
+        if (splittingAddress.community!=-1)splitAddress.setCommunity(splittingAddress.threeLevelAddress.communityFullName);
+        splitAddress.setDistrict(splittingAddress.threeLevelAddress.districtFullName);
+
+        //检查是否能够分离
+        if(splittingAddress.community==-1&&splittingAddress.street==-1){
+            //检查是否是非地址
+            if (UN_ADDRESS_PATTERN.matcher(splitAddress.getFullAddress()).find()){
+                splitAddress.setStatus(3);
+                return splitAddress;
+            }
+            splitAddress.setDistrict(result[2]);
+            splitAddress.setAddr(result[3]);
+
+            splitAddress.setStatus(1);
+            if (result[0].isEmpty()&&result[1].isEmpty()&&districtContainResult.isEmpty())splitAddress.setStatus(4);
+            return splitAddress;
+        }
+        //尝试分离
+        if (splittingAddress.street> splittingAddress.community){
+            String sub = beautyAddress.substring(splittingAddress.street+splittingAddress.streetMap.get(splittingAddress.street).length());
+            Matcher m = LEVEL_2_SUFFIX_PATTERN.matcher(sub);
+            if (m.find()){
+                sub = sub.substring(m.end());
+            }
+            splitAddress.setAddr(sub);
+        }else {
+            String sub = beautyAddress.substring(
+                    splittingAddress.community+
+                            splittingAddress.communityMap.
+                                    get(splittingAddress.community).length());
+            Matcher m = LEVEL_3_SUFFIX_PATTERN.matcher(sub);
+            if (m.find()){
+                sub = sub.substring(m.end());
+            }
+            splitAddress.setAddr(sub);
+        }
+        splitAddress.setStatus(0);
+        if (result[0].isEmpty()&&result[1].isEmpty()&&districtContainResult.isEmpty())splitAddress.setStatus(4);
+        if (splitAddress.getStreet().equals("自由贸易试验区"))splitAddress.setStatus(0);
+        return splitAddress;
+    }
+
+    private static SplitAddress beautyResult(SplitAddress splitAddress){
+        //检查过度分割
+        if (splitAddress.getAddr().isEmpty() ||OVER_SPLIT.matcher(splitAddress.getAddr()).find()){
+            if (splitAddress.getCommunity().isEmpty()){
+                if (splitAddress.getStreet().isEmpty()){
+                    if (splitAddress.getDistrict().isEmpty()){
+                        splitAddress.setAddr("上海市"+splitAddress.getAddr());
+                    }else {
+                        splitAddress.setAddr(splitAddress.getDistrict()+splitAddress.getAddr());
+                    }
+                }else {
+                    splitAddress.setAddr(splitAddress.getStreet()+splitAddress.getAddr());
+                }
+            }else {
+                splitAddress.setAddr(splitAddress.getCommunity()+splitAddress.getAddr());
+            }
+        }
+        //检查多号,多弄
+        splitAddress.setAddr(splitAddress.getAddr().replaceAll(String.valueOf(MULTI_ADDRESS),""));
+
+        return splitAddress;
+    }
+    /**
+     * 工具入口,返回所有数据
+     * @param sourceAddress 任意形式的地址,请注意,上海市外的地址仅分词到县,上海市内分词到居委
+     */
+    public static List<SplitAddress> splitAddresses(String sourceAddress){
+        sourceAddress = sourceAddress.replaceAll("[^\\u4e00-\\u9fa5\\da-zA-Z]", "");
+        Matcher matcher = Pattern.compile("\\(([^()]*|\\([^()]*\\))*\\)|\\[([^\\[\\]]*|\\[[^\\[\\]]*])*]|(([^()]*|([^()]*))*)").matcher(sourceAddress);
+        List<SplitAddress> addressList =new ArrayList<>();
+        String beautyString = sourceAddress.replaceAll("\\(([^()]*|\\([^()]*\\))*\\)|\\[([^\\[\\]]*|\\[[^\\[\\]]*])*]|(([^()]*|([^()]*))*)","");
+        StringBuilder sb = new StringBuilder();
+        for (char c : beautyString.toCharArray()) {
+            // 检查是否为全角数字
+            if (c >= '0' && c <= '9') {
+                // 转换为半角数字
+                sb.append((char) (c - '0' + '0'));
+            } else if (c=='\uE5CE'){
+                // 奇妙的乱码,跳过
+            }else {
+                // 保持原字符
+                sb.append(c);
+            }
+        }
+        beautyString = sb.toString();
+        addressList.add(beautyResult(split(beautyString)));
+        while (matcher.find()){
+            String address=matcher.group();
+            if (address.length()<=2)continue;
+            addressList.addAll(splitAddresses(address.substring(1,address.length()-1)));
+        }
+        for (SplitAddress s :addressList)s.setSourceAddress(sourceAddress);
+        return addressList;
+    }
+
+    /**
+     * 工具入口,仅返回最优
+     * @param sourceAddress 任意形式的地址,请注意,上海市外的地址仅分词到县,上海市内分词到居委
+     */
+    public static SplitAddress splitBestAddress(String sourceAddress){
+        return splitAddresses(sourceAddress.toString()).stream().max(SplitAddress::compareTo).orElse(new SplitAddress());
+    }
+    public static void main(String[] args) throws Exception {
+//        List<SplitAddress> result = new ArrayList<>();
+//        for (Map<String,Object> row:ExcelReaderUtils.readExcel("C:\\Users\\dxh\\IdeaProjects\\address_poi_yysz_server\\src\\main\\resources\\yysk_dmdz_address_standardization_200000_36.xlsx")){
+//            result.add(splitAddresses(row.get("address").toString()).stream().max(SplitAddress::compareTo).orElse(new SplitAddress()));
+//            System.out.println("正在处理:"+row.get("address"));
+//        };
+//        ExcelReaderUtils.writeSplitAddressExcel(result,"C:\\\\Users\\\\dxh\\\\IdeaProjects\\\\address_poi_yysz_server\\\\src\\\\main\\\\resources\\\\result.xlsx");
+//        System.out.println("完成");
+        new ShanghaiAddressSplitUtil().init();
+        System.out.println(splitBestAddress("长宁区长宁路1595弄小河南33支弄16号"));
+        System.out.println(splitBestAddress("上海市宝山区张庙街道共和新路5199号功夫肩颈张百草"));
+
+    }
+}

+ 333 - 0
src/main/java/com/skyversation/poiaddr/util/lmrTools/initAddrMap.java

@@ -0,0 +1,333 @@
+package com.skyversation.poiaddr.util.lmrTools;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.skyversation.poiaddr.entity.AddrBean;
+import com.skyversation.poiaddr.util.ExcelReaderUtils;
+import com.skyversation.poiaddr.util.ShanghaiAddressSplitUtil;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * # 生成完整的上海市县乡记录.xlsx
+ * * 1、读取村居边界.geojson\得到对应关系【所属区:区代码:所属街:居委_1】,同时得到区和区代码的对应关系
+ * * 2、遍历xlsx文件列表,然后解析returnAddress,进行分词
+ * * 3、主要是获取街镇和居委的对应关系【判断到街镇后,得到下标,然后判断后面是否存在居委会或村委会关键字】
+ * 当前版本:V2.0.1
+ */
+@Service
+public class initAddrMap {
+    //  上海市村居边界geojson文件地址
+    private static String geojsonFilePath = "geojson/上海市_村居边界.geojson";
+    private static String All_no_SHFilePath = "全国省市县记录.xlsx";
+    private static String outPutFilePath = "geojson/上海市_村居边界.xlsx";
+
+    //  《区—街镇-居委》的对应关系
+    private static HashMap<String, HashMap<String, Set<String>>> D_S_C_tree = new HashMap<>();
+    //    非上海的《省-市-区》的对应关系
+    private static HashMap<String, HashMap<String, Set<String>>> All_NO_SH_tree = new HashMap<>();
+    //  区和区代码的对应关系
+    private static HashMap<String, String> districtCodeMap = new HashMap<>();
+
+    @PostConstruct
+    private void initFile() {
+        System.out.println("开始初始化分词器");
+        InputStream is = ShanghaiAddressSplitUtil.class.getResourceAsStream(outPutFilePath);
+        if (is == null) is = ShanghaiAddressSplitUtil.class.getResourceAsStream("/" + outPutFilePath);
+        if (is == null) throw new RuntimeException("无法找到" + outPutFilePath);
+        try {
+            for (Map<String, Object> row : ExcelReaderUtils.readExcel(is)) {
+                districtCodeMap.put(row.get("区").toString(), row.get("区代码").toString());
+                if (D_S_C_tree.containsKey(row.get("区").toString())) {
+                    Map<String, Set<String>> SCT = D_S_C_tree.get(row.get("区").toString());
+                    if (SCT.containsKey(row.get("镇").toString())) {
+                        SCT.get(row.get("镇").toString()).add(row.get("居委").toString());
+                    } else {
+                        Set<String> CL = new HashSet<>();
+                        CL.add(row.get("居委").toString());
+                        SCT.put(row.get("镇").toString(), CL);
+                    }
+                } else {
+                    HashMap<String, Set<String>> SCT = new HashMap<>();
+                    Set<String> CL = new HashSet<>();
+                    CL.add(row.get("居委").toString());
+                    SCT.put(row.get("镇").toString(), CL);
+                    D_S_C_tree.put(row.get("区").toString(), SCT);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        InputStream is2 = ShanghaiAddressSplitUtil.class.getResourceAsStream(All_no_SHFilePath);
+        if (is2 == null) is2 = ShanghaiAddressSplitUtil.class.getResourceAsStream("/" + All_no_SHFilePath);
+        if (is2 == null) throw new RuntimeException("无法找到" + All_no_SHFilePath);
+        try {
+            for (Map<String, Object> row : ExcelReaderUtils.readExcel(is2)) {
+                String ss = row.get("省份").toString();
+                String djs = row.get("地级市") != null && !row.get("地级市").toString().isEmpty() ? row.get("地级市").toString() : null;
+                String xjs = row.get("县级市") != null && !row.get("县级市").toString().isEmpty() ? row.get("县级市").toString() : null;
+                if (All_NO_SH_tree.containsKey(ss)) {
+                    Map<String, Set<String>> SCT = All_NO_SH_tree.get(ss);
+                    if (djs != null && xjs != null) {
+                        if (SCT.containsKey(djs)) {
+                            SCT.get(djs).add(xjs);
+                        } else {
+                            Set<String> CL = new HashSet<>();
+                            CL.add(xjs);
+                            SCT.put(djs, CL);
+                        }
+                    }
+                } else {
+                    HashMap<String, Set<String>> SCT = new HashMap<>();
+                    if (djs != null && xjs != null) {
+                        Set<String> CL = new HashSet<>();
+                        CL.add(xjs);
+                        SCT.put(djs, CL);
+                    }
+                    All_NO_SH_tree.put(ss, SCT);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //  更新上海市村居边界geojson文件,需要执行的操作
+    private void readGeojsonFile() {
+        BufferedReader reader = null;
+        try {
+            // 创建 ClassPathResource 对象,指定静态文件的路径
+            ClassPathResource resource = new ClassPathResource(geojsonFilePath);
+            // 获取文件的输入流
+            reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
+            String line;
+            StringBuilder sb = new StringBuilder();
+            while ((line = reader.readLine()) != null) {
+                sb.append(line).append("\r\n");
+            }
+            reader.close();
+            JSONObject json = JSONObject.parseObject(sb.toString());
+            JSONArray featrues = json.getJSONArray("features");
+            List<Map<String, Object>> outPutDatas = new ArrayList<>();
+            for (int i = 0; i < featrues.size(); i++) {
+                JSONObject properties = featrues.getJSONObject(i).getJSONObject("properties");
+                Map<String, Object> dataItem = new HashMap<>();
+                dataItem.put("区", properties.getString("所属区"));
+                dataItem.put("区代码", properties.getString("区代码"));
+                dataItem.put("镇", properties.getString("所属街"));
+                dataItem.put("居委", properties.getString("居委_1"));
+                outPutDatas.add(dataItem);
+            }
+            if (outPutDatas.size() > 0) {
+                ExcelReaderUtils.writeToExcel(outPutDatas, "C:\\Users\\Liumouren\\Desktop\\上海市_村居边界.xlsx");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.out.println("<<<<<<<<------run geo data error------>>>>>>>>>");
+        }
+    }
+
+    /**
+     * ## 分词:返回实体类【原地址:省:市:区:镇:居委:路牌地址:标准地址:区代码】
+     * * 1、初始化分词模型(读取村居边界.geojson\得到对应关系【所属区:区代码:所属街:居委_1】)(读取全国省市县记录.xlsx\得到对应关系【省:市:区县】)
+     * * 2、判断地址字符串是否存在[省、市、区、镇、街道、县]
+     * * 3、如果存在【省、市】判断是否是非上海市,是的话返回rule:0
+     * * 4、不知道是不是上海市的话,判断【区、镇】(先全词匹配,匹配不到的话模糊匹配)
+     * * 5、将匹配到的“区代码”拼接上310,否则直接是310000,作为搜索条件
+     * * 6、得到返回结果列表
+     * <p>
+     * //              省1:市2:区4:镇8:居委16
+     *
+     * @param addr
+     * @return
+     */
+    static Pattern pattern = Pattern.compile("市|区|镇|街道|县");
+    static Pattern spattern = Pattern.compile("路|街|道|村");
+
+    public static AddrBean outAddrMapInAddr(String addr) {
+        AddrBean addrMap = new AddrBean();
+        addrMap.setOldAddress(addr + "");
+        addrMap.setAddress(addr.replaceAll(" ", ""));
+        if (addr.contains("http")) {
+            //      先判断是否是链接
+            addrMap.setRule("-1");
+        } else {
+//          判断外地省名
+            boolean errorAddr = false;
+            for (String s : All_NO_SH_tree.keySet()) {
+                if (addr.startsWith(s) || (addr.startsWith(s.substring(0, 2)) && !ifTrueAddr(addr, s.substring(0, 2)))) {
+                    addrMap.setProvinces(s);
+                    addrMap.setRule("0");
+                    if (!s.contains("上海")) {
+                        errorAddr = true;
+                    }
+                }
+//              判断外地市名
+                for (String m : All_NO_SH_tree.get(s).keySet()) {
+                    if (addr.contains(m) && !addr.contains(m + "场")) {
+                        addrMap.setProvinces(s);
+                        addrMap.setMarket(m);
+                        addrMap.setRule("-2");
+                    }
+                    //              判断外地县名
+                    for (String x : All_NO_SH_tree.get(s).get(m)) {
+                        if (addr.contains(x) && !addr.contains(x + "场")) {
+                            addrMap.setDistinguish(x);
+                            addrMap.setProvinces(s);
+                            addrMap.setMarket(m);
+                            addrMap.setRule("-4");
+                            break;
+                        }
+                    }
+                }
+            }
+
+
+//          如果不是外地数据和连接数据的话
+            if (!errorAddr) {
+//              上海地址匹配
+                if (pattern.matcher(addr).find()) {
+                    if (addr.startsWith("上海")) {
+                        addrMap.setProvinces("上海市");
+                        addrMap.setMarket("上海市");
+                        addrMap.setRule("2");
+                    }
+//                  匹配区
+                    boolean ifContains = false;
+//                  区匹配标识
+                    String sh_distinguish = "";
+                    for (String d : D_S_C_tree.keySet()) {
+                        if (addr.contains(d) || addr.contains(d.substring(0, 2) + "县")) {
+                            ifContains = true;
+                            addrMap.setProvinces("上海市");
+                            addrMap.setMarket("上海市");
+                            addrMap.setDistinguish(d);
+                            sh_distinguish = d;
+                            addrMap.setRule("4");
+                            break;
+                        }
+                        if (addr.contains(d.substring(0, 2)) && ifTrueAddr(addr, d.substring(0, 2))) {
+                            addrMap.setProvinces("上海市");
+                            addrMap.setMarket("上海市");
+                            addrMap.setDistinguish(d);
+                            sh_distinguish = d;
+                            addrMap.setRule("4");
+                        }
+                    }
+//                  镇匹配
+                    for (String d : D_S_C_tree.keySet()) {
+                        for (String s : D_S_C_tree.get(d).keySet()) {
+                            if (addr.contains(s)) {
+                                addrMap.setProvinces("上海市");
+                                addrMap.setMarket("上海市");
+                                addrMap.setDistinguish(d);
+                                addrMap.setStreetTown(s);
+                                addrMap.setRule("8");
+                                break;
+                            }
+                            if (addr.contains(s.substring(0, 2)) && ifContains && !sh_distinguish.isEmpty() && sh_distinguish.contains(d)) {
+                                addrMap.setProvinces("上海市");
+                                addrMap.setMarket("上海市");
+                                addrMap.setDistinguish(d);
+                                addrMap.setStreetTown(s);
+                                addrMap.setRule("8");
+                            }
+//                              匹配居委(现在居委有很多问题,暂时不要)
+                            /*for (String c : D_S_C_tree.get(d).get(s)) {
+                                if (addr.contains(c)) {
+                                    addrMap.setProvinces("上海市");
+                                    addrMap.setMarket("上海市");
+                                    addrMap.setDistinguish(d);
+                                    addrMap.setStreetTown(s);
+                                    addrMap.setResidentialCommittee(c);
+                                    addrMap.setRule("16");
+                                }
+                            }*/
+                        }
+                    }
+                }
+            }
+//          特殊处理逻辑
+            if (addrMap.getDistinguish() != null && addrMap.getAddress() != null && addrMap.getDistinguish().contains("松江区") && addrMap.getAddress().contains("工业区")) {
+                addrMap.setStreetTown("松江技术开发区");
+                if (addrMap.getAddress().split("工业区").length > 1) {
+                    addrMap.setAddress(addrMap.getAddress().split("工业区")[1]);
+                }
+            }
+//          输出路牌
+            if (addrMap.getProvinces() != null && !addrMap.getProvinces().isEmpty() && addrMap.getAddress().contains(addrMap.getProvinces())) {
+                if (addrMap.getAddress().split(addrMap.getProvinces()).length > 1) {
+                    addrMap.setAddress(addrMap.getAddress().split(addrMap.getProvinces())[1]);
+                }
+            }
+            if (addrMap.getMarket() != null && !addrMap.getMarket().isEmpty() && addrMap.getAddress().contains(addrMap.getMarket())) {
+                if (addrMap.getAddress().split(addrMap.getMarket()).length > 1) {
+                    addrMap.setAddress(addrMap.getAddress().split(addrMap.getMarket())[1]);
+                }
+            }
+            if (addrMap.getDistinguish() != null && !addrMap.getDistinguish().isEmpty()) {
+                if (addrMap.getAddress().contains(addrMap.getDistinguish())) {
+                    if (addrMap.getAddress().split(addrMap.getDistinguish()).length > 1) {
+                        addrMap.setAddress(addrMap.getAddress().split(addrMap.getDistinguish())[1]);
+                    }
+                } else if (addrMap.getAddress().contains(addrMap.getDistinguish().substring(0, 2) + "县")) {
+                    if (addrMap.getAddress().split(addrMap.getDistinguish().substring(0, 2) + "县").length > 1) {
+                        addrMap.setAddress(addrMap.getAddress().split(addrMap.getDistinguish().substring(0, 2) + "县")[1]);
+                    }
+                }
+            }
+            if (addrMap.getStreetTown() != null && !addrMap.getStreetTown().isEmpty() && addrMap.getAddress().contains(addrMap.getStreetTown())) {
+                if (addrMap.getAddress().split(addrMap.getStreetTown()).length > 1) {
+                    addrMap.setAddress(addrMap.getAddress().split(addrMap.getStreetTown())[1]);
+                }
+            }
+            if (addrMap.getResidentialCommittee() != null && !addrMap.getResidentialCommittee().isEmpty() && addrMap.getAddress().contains(addrMap.getResidentialCommittee())) {
+                if (addrMap.getAddress().split(addrMap.getResidentialCommittee()).length > 1) {
+                    addrMap.setAddress(addrMap.getAddress().split(addrMap.getResidentialCommittee())[1]);
+                }
+            }
+            if (addrMap.getAddress().contains("村委会") || addrMap.getAddress().contains("居委会")) {
+                addrMap.setAddress(addrMap.getAddress().substring(Math.max(addrMap.getAddress().indexOf("村委会"), addrMap.getAddress().indexOf("居委会")) + 3));
+            }
+        }
+
+        return addrMap;
+    }
+
+    /**
+     * 判断是否是名称+路名街名的格式
+     *
+     * @param addr
+     * @param tagStr
+     * @return
+     */
+    public static boolean ifTrueAddr(String addr, String tagStr) {
+        String endStr = addr.substring(addr.indexOf(tagStr) + tagStr.length(), Math.min(addr.length(), addr.indexOf(tagStr) + tagStr.length() + 2));
+        if (spattern.matcher(endStr).find()) {
+            return true;
+        }
+        return false;
+    }
+
+    public static void main(String[] args) {
+        initAddrMap initAddrMap = new initAddrMap();
+//        initAddrMap.readGeojsonFile();
+        initAddrMap.initFile();
+        /*System.out.println(outAddrMapInAddr("南昌集贸市场东-22"));
+        System.out.println(outAddrMapInAddr("中国上海南京西路699号上海东方众鑫大厦1811A"));
+        System.out.println(outAddrMapInAddr("崇明县向化镇南六效水闸河东"));
+        System.out.println(outAddrMapInAddr("浙江省玉环县清港镇塘头"));
+        System.out.println(outAddrMapInAddr("嘉定区嘉定镇西城河北街34号"));
+        System.out.println(outAddrMapInAddr("崇明县大同镇浜北村16队"));*/
+        System.out.println(outAddrMapInAddr("上海市松江区松江工业区蓝欣农贸市场120号摊位"));
+        System.out.println(outAddrMapInAddr("上海市松江区中山街道松东路蓝天新村蓝欣农贸市场159号蓝天超市"));
+    }
+}

+ 5 - 2
src/main/java/com/skyversation/poiaddr/util/net/AddressNetTools.java

@@ -52,12 +52,13 @@ public class AddressNetTools {
         SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
         requestFactory.setConnectTimeout(10000);
         requestFactory.setReadTimeout(5000);
+        /*requestFactory.setConnectTimeout(150000);
+        requestFactory.setReadTimeout(120000);*/
         RestTemplate client = new RestTemplate(requestFactory);
         client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
         HttpHeaders headers = new HttpHeaders();
         //请勿轻易改变此提交方式,大部分的情况下,提交方式都是表单提交
         headers.setContentType(httpMethod == HttpMethod.POST ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_FORM_URLENCODED);
-        ScheduledTasks.szxRequestSize++;
         if (headerMap != null) {
             Set<String> sets = headerMap.keySet();
             for (String key : sets) {
@@ -65,6 +66,8 @@ public class AddressNetTools {
             }
         }
         try {
+            /*int length = params.toString().getBytes().length;
+            System.out.println("参数大小:" + length / 1048576 + "MB,不能大于10MB!");*/
             if (httpMethod == HttpMethod.POST) {
                 org.springframework.http.HttpEntity<JSONObject> requestEntity = new org.springframework.http.HttpEntity<>(params, headers);//执行HTTP请求
                 return client.exchange(url, httpMethod, requestEntity, String.class);
@@ -83,7 +86,7 @@ public class AddressNetTools {
                 ifReloadSize--;
                 return requestGetOrPost(httpMethod, url, params, headerMap, ifReloadSize);
             } else {
-                System.err.println("requestGet err:" + e);
+                e.printStackTrace();
                 return null;
                 /*if (e.toString().contains("timed out")) {
                     System.out.print("请求超时!");

+ 2 - 1
src/main/java/com/skyversation/poiaddr/util/tasks/ScheduledTasks.java

@@ -22,7 +22,8 @@ public class ScheduledTasks {
 
     public static int szxRequestSize = 0;
     public static int gdRequestSize = 0;
-    public static Long OID_TAG = 0L;
+//  2kw-3kw是xlsx数据;amap是3kw开头
+    public static Long OID_TAG = 30000000L;
 //  统计异常数量和类型
     public static Map<String,Integer> errorCount = new ConcurrentHashMap<>();
 

+ 8 - 9
src/main/resources/application.properties

@@ -1,4 +1,4 @@
-server.port=8081
+server.port=8082
 server.servlet.context-path=/poiApi/
 spring.application.name=poiAddr
 spring.servlet.multipart.max-file-size=300MB
@@ -10,24 +10,23 @@ spring.servlet.multipart.max-request-size=300MB
 #spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 # \u6570\u636E\u5E93\u914D\u7F6E\uFF08\u672C\u5730\u8C03\u8BD5\u73AF\u5883\uFF09
 spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/postgres?stringtype=unspecified&u003fuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=PRC&useSSL=false&tinyInt1isBit=false
-#spring.datasource.url=jdbc:postgresql://192.168.1.4:5432/postgres?stringtype=unspecified&u003fuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=PRC&useSSL=false&tinyInt1isBit=false
 spring.datasource.username=postgres
-#spring.datasource.password=WE176852439@lmx
-spring.datasource.password=SKYversation0816
-spring.datasource.driver-class-name=org.postgresql.Driver
-
+spring.datasource.password=WE176852439@lmx
+#spring.datasource.url=jdbc:postgresql://121.43.55.7:5433/postgres?stringtype=unspecified&u003fuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=PRC&useSSL=false&tinyInt1isBit=false
+#spring.datasource.username=postgres
+#spring.datasource.password=SKYversation@0816
+#spring.datasource.driver-class-name=org.postgresql.Driver
 # JPA\u914D\u7F6E
 spring.jpa.hibernate.ddl-auto=update
 #spring.jpa.show-sql=true
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
-
 # JPA \u914D\u7F6E
 #spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
 #spring.jpa.hibernate.ddl-auto=update
 #spring.jpa.show-sql=false
 # \u677E\u6C5F\u8857\u9547
 app.area=\u4E0A\u6D77
-app.town=\u5CB3\u9633\u8857\u9053,\u6C38\u4E30\u8857\u9053,\u65B9\u677E\u8857\u9053,\u4E2D\u5C71\u8857\u9053,\u5E7F\u5BCC\u6797\u8857\u9053,\u4E5D\u91CC\u4EAD\u8857\u9053,\u6CD7\u6CFE\u9547,\u4F58\u5C71\u9547,\u8F66\u58A9\u9547,\u65B0\u6865\u9547,\u6D1E\u6CFE\u9547,\u4E5D\u4EAD\u9547,\u6CD6\u6E2F\u9547,\u77F3\u6E56\u8361\u9547,\u65B0\u6D5C\u9547,\u53F6\u69AD\u9547,\u5C0F\u6606\u5C71\u9547,\u5929\u9A6C\u5C71\u9547
+#app.town=\u5CB3\u9633\u8857\u9053,\u6C38\u4E30\u8857\u9053,\u65B9\u677E\u8857\u9053,\u4E2D\u5C71\u8857\u9053,\u5E7F\u5BCC\u6797\u8857\u9053,\u4E5D\u91CC\u4EAD\u8857\u9053,\u6CD7\u6CFE\u9547,\u4F58\u5C71\u9547,\u8F66\u58A9\u9547,\u65B0\u6865\u9547,\u6D1E\u6CFE\u9547,\u4E5D\u4EAD\u9547,\u6CD6\u6E2F\u9547,\u77F3\u6E56\u8361\u9547,\u65B0\u6D5C\u9547,\u53F6\u69AD\u9547,\u5C0F\u6606\u5C71\u9547,\u5929\u9A6C\u5C71\u9547
 # \u878D\u5408\u7248\uFF1A1736930075105|\u5173\u952E\u5B57\uFF1A1742459783686
 app.search_server_id=1742459783686
 app.db.username=dev_sjbdc_kjyy
@@ -36,4 +35,4 @@ app.db.driver=io.transwarp.jdbc.QuarkDriver
 app.db.jdbc_url=jdbc:transwarp2://172.30.75.126:32265/kjyy_dev
 # \u9752\u6D66\u8857\u9547
 #app.area=\u9752\u6D66
-#app.town2=\u6731\u5BB6\u89D2\u9547\u3001\u8D75\u5DF7\u9547\u3001\u5F90\u6CFE\u9547\u3001\u534E\u65B0\u9547\u3001\u91CD\u56FA\u9547\u3001\u767D\u9E64\u9547\u3001\u7EC3\u5858\u9547\u3001\u91D1\u6CFD\u9547\u3001\u590F\u9633\u8857\u9053\u3001\u76C8\u6D66\u8857\u9053\u3001\u9999\u82B1\u6865\u8857\u9053
+app.town=\u6731\u5BB6\u89D2\u9547\u3001\u8D75\u5DF7\u9547\u3001\u5F90\u6CFE\u9547\u3001\u534E\u65B0\u9547\u3001\u91CD\u56FA\u9547\u3001\u767D\u9E64\u9547\u3001\u7EC3\u5858\u9547\u3001\u91D1\u6CFD\u9547\u3001\u590F\u9633\u8857\u9053\u3001\u76C8\u6D66\u8857\u9053\u3001\u9999\u82B1\u6865\u8857\u9053

BIN
src/main/resources/geojson/上海市_村居边界.xlsx


BIN
src/main/resources/上海市县乡记录.xlsx


BIN
src/main/resources/全国省市县记录.xlsx


BIN
流程图.png