|
@@ -1,15 +1,12 @@
|
|
|
package com.example.poiaddr.controller;
|
|
|
|
|
|
+import com.example.poiaddr.entity.FileDataDto;
|
|
|
import com.example.poiaddr.entity.PoiAddress;
|
|
|
import com.example.poiaddr.service.PoiAddressService;
|
|
|
-import com.example.poiaddr.util.ExcelReaderUtils;
|
|
|
+import com.example.poiaddr.util.CoordTransform;
|
|
|
import com.example.poiaddr.util.RequestUtils;
|
|
|
-import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.example.poiaddr.util.fileTools.ReadFileData;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.json.simple.JSONArray;
|
|
|
-import org.json.simple.JSONObject;
|
|
|
-import org.json.simple.parser.JSONParser;
|
|
|
import org.locationtech.jts.geom.Coordinate;
|
|
|
import org.locationtech.jts.geom.GeometryFactory;
|
|
|
import org.locationtech.jts.geom.Point;
|
|
@@ -23,8 +20,6 @@ import javax.annotation.Resource;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
import java.io.*;
|
|
|
import java.util.*;
|
|
|
-import java.util.concurrent.ExecutorService;
|
|
|
-import java.util.concurrent.Executors;
|
|
|
|
|
|
@Slf4j
|
|
|
@Validated
|
|
@@ -68,165 +63,6 @@ public class PoiAddressController {
|
|
|
return RequestUtils.request(address);
|
|
|
}
|
|
|
|
|
|
- // 创建一个方法能读取xlsx文件数据并返回List<Map>集合
|
|
|
-// 创建一个setList集合判断文档中的数据不能地址重复
|
|
|
-// 然后根据这个list集合创建多线程请求数据并插入到数据库中
|
|
|
-// filePath:C:\Users\Liumouren\Desktop\临时文件\元以科技\青浦\青浦城建所\poiAddr\doc\
|
|
|
- @GetMapping(value = "/test")
|
|
|
- public Object test() {
|
|
|
-// try {
|
|
|
-//// 根据文件路径得到下面的所有文件集合
|
|
|
-// List<File> fileList = ExcelReaderUtils.listFilesInDirectory("C:\\Users\\Liumouren\\Desktop\\临时文件\\元以科技\\青浦\\青浦城建所\\poiAddr\\doc\\");
|
|
|
-//// 根据文件集合得到
|
|
|
-// List<Map<String, String>> errorData = new ArrayList<>();
|
|
|
-// Set<String> addressSet = new HashSet<>();
|
|
|
-// for (File fileItem : fileList) {
|
|
|
-// if (fileItem.getPath().contains(".xlsx") && fileItem.getPath().contains("marge_excel_uuid")) {
|
|
|
-// List<Map<String, Object>> dataList = ExcelReaderUtils.readExcel(fileItem.getPath());
|
|
|
-// for (Map<String, Object> map : dataList) {
|
|
|
-// if (map.containsKey("详细地址")) {
|
|
|
-// addressSet.add(map.get("详细地址").toString());
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-//// 得到geojson中的所有的地址名称
|
|
|
-//// Set<String> addressSet = JacksonExample.getAddressList();
|
|
|
-//// 测试请求结果
|
|
|
-// ArrayList<JSONObject> resultList = new ArrayList<>();
|
|
|
-// ArrayList<String> addressList = new ArrayList<>();
|
|
|
-// for (String addrStr : addressSet) {
|
|
|
-// String addrStr2 = StringUtils.deleteWhitespace(addrStr);
|
|
|
-// if (addrStr2.length() > 5) {
|
|
|
-// addressList.add(addrStr2);
|
|
|
-// } else {
|
|
|
-// Map<String, String> error = new HashMap<>();
|
|
|
-// error.put("错误地址:", addrStr2);
|
|
|
-// error.put("msg", "地址长度不规范");
|
|
|
-// errorData.add(error);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// int threadCount = 10; // 设置线程数量
|
|
|
-// ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
|
|
|
-// // 将集合拆分成多个子任务
|
|
|
-// int partSize = addressList.size() / threadCount;
|
|
|
-// for (int i = 0; i < threadCount; i++) {
|
|
|
-// int startIndex = i * partSize;
|
|
|
-// int endIndex = (i == threadCount - 1) ? addressList.size() : (i + 1) * partSize;
|
|
|
-// List<String> subList = addressList.subList(startIndex, endIndex);
|
|
|
-// // 提交Runnable任务到线程池
|
|
|
-// Runnable runnable = () -> {
|
|
|
-// for (String addrStr2 : subList) {
|
|
|
-// String resultStr = RequestUtils.request(addrStr2);
|
|
|
-// if (resultStr != null && resultStr.contains("result")) {
|
|
|
-// JSONParser jsonParser = new JSONParser();
|
|
|
-// try {
|
|
|
-// JSONObject resultObject = (JSONObject) jsonParser.parse(resultStr);
|
|
|
-// JSONArray result = (JSONArray) resultObject.get("result");
|
|
|
-// if (result.size() > 0) {
|
|
|
-// System.out.println(addrStr2 + "------解析成功数据:" + jsonParser.parse(resultStr));
|
|
|
-// resultList.add(resultObject);
|
|
|
-// } else {
|
|
|
-// System.err.println(addrStr2 + "------解析失败数据:" + resultStr);
|
|
|
-// Map<String, String> error = new HashMap<>();
|
|
|
-// error.put("错误地址:", addrStr2);
|
|
|
-// error.put("msg", "地名地址解析失败");
|
|
|
-// errorData.add(error);
|
|
|
-// }
|
|
|
-// } catch (Exception e) {
|
|
|
-// System.err.println(addrStr2 + "------解析失败数据:" + resultStr);
|
|
|
-// Map<String, String> error = new HashMap<>();
|
|
|
-// error.put("错误地址:", addrStr2);
|
|
|
-// error.put("msg", "地名地址解析失败");
|
|
|
-// errorData.add(error);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// };
|
|
|
-// executorService.submit(runnable);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 关闭线程池(不再接受新任务,但会等待已提交任务完成)
|
|
|
-// executorService.shutdown();
|
|
|
-// // 等待所有任务完成
|
|
|
-// try {
|
|
|
-// while (!executorService.isTerminated()) {
|
|
|
-// Thread.sleep(100);
|
|
|
-// }
|
|
|
-// System.out.println("所有任务已完成");
|
|
|
-// for (JSONObject resultItem : resultList) {
|
|
|
-// JSONArray result = (JSONArray) resultItem.get("result");
|
|
|
-// JSONObject resultData = (JSONObject) result.get(0);
|
|
|
-// JSONObject extData = (JSONObject) resultData.get("ext_data");
|
|
|
-// PoiAddress poiAddress = new PoiAddress();
|
|
|
-// poiAddress.setUuid(UUID.randomUUID().toString());
|
|
|
-// poiAddress.setAddress(extData.get("address").toString());
|
|
|
-// poiAddress.setAddressCode(extData.get("address_code").toString());
|
|
|
-// poiAddress.setLocation(resultData.get("location").toString());
|
|
|
-// poiAddress.setBuilding(extData.get("building").toString());
|
|
|
-// poiAddress.setAttachInfo(extData.get("attach_info").toString());
|
|
|
-// poiAddress.setBuildingAlias(extData.get("building_alias").toString());
|
|
|
-// poiAddress.setCoordAdcode(extData.get("coord_adcode").toString());
|
|
|
-// poiAddress.setDataOperation(extData.get("data_operation").toString());
|
|
|
-// poiAddress.setDataSource(extData.get("data_source").toString());
|
|
|
-// poiAddress.setDataOperationCheck(extData.get("data_operation_check").toString());
|
|
|
-// poiAddress.setFloor(extData.get("floor").toString());
|
|
|
-// poiAddress.setHistoryData(extData.get("history_data").toString());
|
|
|
-// poiAddress.setManualMark(extData.get("manual_mark").toString());
|
|
|
-// poiAddress.setName1(extData.get("name1").toString());
|
|
|
-// poiAddress.setNo1(extData.get("no1").toString());
|
|
|
-// poiAddress.setNo2(extData.get("no2").toString());
|
|
|
-// poiAddress.setNo3(extData.get("no3").toString());
|
|
|
-// poiAddress.setNo4(extData.get("no4").toString());
|
|
|
-// poiAddress.setOperationRemark(extData.get("operation_remark").toString());
|
|
|
-// poiAddress.setOperationRemarkCheck(extData.get("operation_remark_check").toString());
|
|
|
-// poiAddress.setParentAddressCode(extData.get("parent_address_code").toString());
|
|
|
-// poiAddress.setPointB(extData.get("point_b").toString());
|
|
|
-// poiAddress.setPointL(extData.get("point_l").toString());
|
|
|
-// poiAddress.setPointX(extData.get("point_x").toString());
|
|
|
-// poiAddress.setPointY(extData.get("point_y").toString());
|
|
|
-// poiAddress.setPoiString(extData.get("poi_string").toString());
|
|
|
-// poiAddress.setRegionJd(extData.get("region_jd").toString());
|
|
|
-// poiAddress.setRegionJw(extData.get("region_jw").toString());
|
|
|
-// poiAddress.setRegionQx(extData.get("region_jw").toString());
|
|
|
-// poiAddress.setRegionSs(extData.get("region_ss").toString());
|
|
|
-// poiAddress.setRegionXq(extData.get("region_xq").toString());
|
|
|
-// poiAddress.setRegionXqAlias(extData.get("region_xq_alias").toString());
|
|
|
-// poiAddress.setRelationExtraAlias(extData.get("relation_extra_alias").toString());
|
|
|
-// poiAddress.setRelationSnMark(extData.get("relation_sn_mark").toString());
|
|
|
-// poiAddress.setRoomNo(extData.get("room_no").toString());
|
|
|
-// poiAddress.setRoomNoAlias(extData.get("room_no_alias").toString());
|
|
|
-// poiAddress.setSemanticsSource(extData.get("semantics_source").toString());
|
|
|
-// poiAddress.setSourceAddress(extData.get("source_address").toString());
|
|
|
-// poiAddress.setSpecificationUpdateMark(extData.get("specification_update_mark").toString());
|
|
|
-// poiAddress.setSubRegionXq(extData.get("sub_region_xq").toString());
|
|
|
-// poiAddress.setUnit(extData.get("unit").toString());
|
|
|
-// poiAddress.setUnitAlias(extData.get("unit_alias").toString());
|
|
|
-// poiAddressService.save(poiAddress);
|
|
|
-// }
|
|
|
-//// 将异常的数据保存为一个json文件
|
|
|
-// if (errorData.size() > 0) {
|
|
|
-// ObjectMapper objectMapper = new ObjectMapper();
|
|
|
-// String outputFilePath = "C:\\Users\\Liumouren\\Desktop\\errorAddressData.json"; // 输出文件路径,可按需修改
|
|
|
-// FileOutputStream fos = new FileOutputStream(new File(outputFilePath));
|
|
|
-// objectMapper.writeValue(fos, errorData);
|
|
|
-// fos.close();
|
|
|
-// }
|
|
|
-// System.out.println("解析文件得到的地址个数:" + addressSet.size() + ",异常的有" + errorData.size());
|
|
|
-// return "解析文件得到的地址个数:" + addressSet.size() + ",异常的有" + errorData.size();
|
|
|
-// } catch (InterruptedException e) {
|
|
|
-// e.printStackTrace();
|
|
|
-// return e;
|
|
|
-// }
|
|
|
-// } catch (IOException e) {
|
|
|
-// e.printStackTrace();
|
|
|
-// return e;
|
|
|
-// }
|
|
|
- return "test";
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* 地名查询任务接口
|
|
|
* * 参数:
|
|
@@ -234,12 +70,12 @@ public class PoiAddressController {
|
|
|
* *** file: xlsx、csv、geojson、shape
|
|
|
* *** addrColNames: 地名地址字段名称数组,依次查询
|
|
|
* ** 非必填:
|
|
|
- * *** inCoordinate: 输入坐标系
|
|
|
+ * *** inCoordinate: 输入坐标系(默认为wgs84)
|
|
|
* *** latLonColName: 经纬度字段名称,如果长度为一,经纬度字段分隔符为必填
|
|
|
* *** latLonSplitStr: 经纬度字段分隔符
|
|
|
* *** matchingDistance: 匹配距离,如果不为空,经纬度字段名称不能为空
|
|
|
* *** outCoordinate: 输出坐标系(默认为wgs84)
|
|
|
- * *** matchingLevel: 匹配等级,详情见xmind文件
|
|
|
+ * *** matchingLevel: 匹配等级,详情见xmind文件【1、2、3、4、0】
|
|
|
* *** regionalJudgment: 区域判断,geojson、shape文件[前端可以内置一些常用的区域文件,通过下拉框的方式进行选择]
|
|
|
* *** outFileType: 输出文件类型【xlsx、csv、geojson、shape】
|
|
|
*
|
|
@@ -251,13 +87,136 @@ public class PoiAddressController {
|
|
|
@RequestParam(name = "inCoordinate", required = false) String inCoordinate,
|
|
|
@RequestParam(name = "latLonColName", required = false) String latLonColName,
|
|
|
@RequestParam(name = "latLonSplitStr", required = false) String latLonSplitStr,
|
|
|
- @RequestParam(name = "matchingDistance", required = false) String matchingDistance,
|
|
|
+ @RequestParam(name = "matchingDistance", required = false) Long matchingDistance,
|
|
|
@RequestParam(name = "outCoordinate", required = false) String outCoordinate,
|
|
|
@RequestParam(name = "matchingLevel", required = false) String matchingLevel,
|
|
|
@RequestParam(name = "regionalJudgment", required = false) MultipartFile regionalJudgment,
|
|
|
@RequestParam(name = "outFileType", required = false) String outFileType) throws IOException {
|
|
|
- if ((file != null && !file.isEmpty()) || (addrColNames != null && !addrColNames.isEmpty())) {
|
|
|
- return null;
|
|
|
+// 参数合法性判断
|
|
|
+ if ((file != null && !file.isEmpty()) && (addrColNames != null && !addrColNames.isEmpty())) {
|
|
|
+// 搜索地址key
|
|
|
+ String addr1Key = "";
|
|
|
+ String addr2Key = "";
|
|
|
+// 参考经纬度key
|
|
|
+ String latKey = "";
|
|
|
+ String lonKey = "";
|
|
|
+ String latLonKey = "";
|
|
|
+ String SplitStr = "";
|
|
|
+// 多地址的形式
|
|
|
+ if (addrColNames.contains(",")) {
|
|
|
+ String[] addrs = addrColNames.split(",");
|
|
|
+ if (addrs.length > 2) {
|
|
|
+ return "最多支持两个地址列查询,请检查addrColNames参数!";
|
|
|
+ }
|
|
|
+ addr1Key = addrs[0];
|
|
|
+ addr2Key = addrs[1];
|
|
|
+ } else {
|
|
|
+ addr1Key = addrColNames;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (matchingLevel == null || matchingLevel.isEmpty()) {
|
|
|
+ return "请传入搜索等级参数,matchingLevel参数不能为空!";
|
|
|
+ }
|
|
|
+// 匹配距离参数合法性判断
|
|
|
+ if (matchingDistance != null) {
|
|
|
+ if (latLonColName == null || latLonColName.isEmpty()) {
|
|
|
+ return "当匹配距离参数不为空时,必须传入经纬度参数!";
|
|
|
+ }
|
|
|
+ }
|
|
|
+// 经纬度合法性判断
|
|
|
+ if (latLonColName != null) {
|
|
|
+// 两个key
|
|
|
+ if (latLonColName.contains(",")) {
|
|
|
+ String[] latLons = latLonColName.split(",");
|
|
|
+ latKey = latLons[0];
|
|
|
+ lonKey = latLons[1];
|
|
|
+ } else if (latLonSplitStr != null && !latLonSplitStr.isEmpty()) {
|
|
|
+// 单个key分割,必须要分割符参数
|
|
|
+ latLonKey = latLonColName;
|
|
|
+ SplitStr = latLonSplitStr;
|
|
|
+ } else {
|
|
|
+ return "经纬度列名解析失败,请传入经度和纬度的列名以逗号分割或传入经纬度列名和分隔符参数!";
|
|
|
+ }
|
|
|
+ }
|
|
|
+// 封装解析文件的参数
|
|
|
+// TODO 文件数据解析
|
|
|
+ assert file != null;
|
|
|
+ List<FileDataDto> fileDataDtoList = ReadFileData.ReadMultipartFile(file);
|
|
|
+// TODO 补充FileDataDto中的搜索条件参数
|
|
|
+ for (FileDataDto fileDataDto : fileDataDtoList) {
|
|
|
+// 搜索等级
|
|
|
+ fileDataDto.setMatchingLevel(matchingLevel);
|
|
|
+// set地名地址搜索字段
|
|
|
+ Map<String, Object> properties = fileDataDto.getProperties();
|
|
|
+ if (addr1Key != null && !addr1Key.isEmpty()) {
|
|
|
+ String address = "上海市青浦区" + properties.getOrDefault(addr1Key, "").toString().replace("青浦区", "").replace(
|
|
|
+ "青浦", "").replace("上海市","").replace("上海","").replace("/弄","").replace("/号","").replace("弄","").replace("/幢","").replace("/室"," ").replace("(号楼) "," ");
|
|
|
+ fileDataDto.setAddr1(address);
|
|
|
+ }
|
|
|
+ if (addr2Key != null && !addr2Key.isEmpty()) {
|
|
|
+ String address = "上海市青浦区" + properties.getOrDefault(addr2Key, "").toString().replace("青浦区", "").replace(
|
|
|
+ "青浦", "").replace("上海市","").replace("上海","").replace("/弄","").replace("/号","").replace("弄","").replace("/幢","").replace("/室"," ").replace("(号楼) "," ");
|
|
|
+ fileDataDto.setAddr2(address);
|
|
|
+ }
|
|
|
+// 判断是否有参考经纬度字段
|
|
|
+ if (latKey != null && !latKey.isEmpty() && lonKey != null && !lonKey.isEmpty() && properties.get(latKey) != null && properties.get(lonKey) != null) {
|
|
|
+ String latStr = properties.get(latKey).toString();
|
|
|
+ String lonStr = properties.get(lonKey).toString();
|
|
|
+ fileDataDto.setLat(Double.valueOf(latStr));
|
|
|
+ fileDataDto.setLon(Double.valueOf(lonStr));
|
|
|
+ } else if (!latLonKey.isEmpty() && !SplitStr.isEmpty()) {
|
|
|
+ String[] latLonKeys = latLonKey.split(SplitStr);
|
|
|
+ if (properties.get(latLonKeys[0]) != null && properties.get(latLonKeys[1]) != null) {
|
|
|
+ String latStr = properties.get(latLonKeys[0]).toString();
|
|
|
+ String lonStr = properties.get(latLonKeys[1]).toString();
|
|
|
+ fileDataDto.setLat(Double.valueOf(latStr));
|
|
|
+ fileDataDto.setLon(Double.valueOf(lonStr));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+// TODO 地名查询
|
|
|
+// TODO 转换坐标(根据输入坐标系将参考坐标统一转换成wgs84)
|
|
|
+ ArrayList<String> selectOptions = new ArrayList<>();
|
|
|
+// {"WGS84(国际通用)", "GCJ02(高德、QQ地图)", "BD09(百度地图)", "上海2000坐标系"}
|
|
|
+ selectOptions.add("WGS84");
|
|
|
+ selectOptions.add("GCJ02");
|
|
|
+ selectOptions.add("BD09");
|
|
|
+ selectOptions.add("SH2000");
|
|
|
+ if(inCoordinate != null && !inCoordinate.isEmpty()){
|
|
|
+ if (!selectOptions.contains(inCoordinate)) {
|
|
|
+ return "请传入正确的坐标系名称!可选坐标系名称:WGS84,GCJ02,BD09,SH2000";
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ inCoordinate = "WGS84";
|
|
|
+ }
|
|
|
+ for(FileDataDto fileDataDto:fileDataDtoList){
|
|
|
+ if(fileDataDto.getLat() != null && fileDataDto.getLon() != null){
|
|
|
+ double[] lonLat = com.example.poiaddr.util.Coordinate.transformationCoordinateByCoordinate(fileDataDto.getLat(),fileDataDto.getLon(),inCoordinate,outCoordinate);
|
|
|
+ fileDataDto.setLat(lonLat[1]);
|
|
|
+ fileDataDto.setLon(lonLat[0]);
|
|
|
+ }
|
|
|
+ // TODO 距离计算
|
|
|
+ if(matchingDistance != null){
|
|
|
+ if(fileDataDto.getResultLat() != null && fileDataDto.getResultLon() != null && fileDataDto.getLat() != null && fileDataDto.getLon() != null){
|
|
|
+ double distance = com.example.poiaddr.util.Coordinate.calculateDistance(fileDataDto.getResultLat(),fileDataDto.getResultLon(),fileDataDto.getLat(),fileDataDto.getLon());
|
|
|
+ fileDataDto.setMatchingDistance(distance);
|
|
|
+ double matchingDistanceDb = Double.parseDouble(matchingDistance.toString());
|
|
|
+ if(distance < matchingDistanceDb){
|
|
|
+ fileDataDto.setLtMatchingDistance("是");
|
|
|
+ }else{
|
|
|
+ fileDataDto.setLtMatchingDistance("否");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // TODO 区域判断
|
|
|
+ if(regionalJudgment != null && !regionalJudgment.isEmpty()){
|
|
|
+// 解析geojson文件得到区域
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+// TODO 转换坐标
|
|
|
+// TODO 结果输出
|
|
|
+ return "文件解析完成,共" + fileDataDtoList.size() + "条数据!";
|
|
|
} else {
|
|
|
return "file或addrColName不能为空!";
|
|
|
}
|