123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
- package com.skyversation.poiaddr.addquery;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.skyversation.poiaddr.bean.AddressResult;
- import com.skyversation.poiaddr.bean.GeoJsonBean;
- import com.skyversation.poiaddr.bean.YyskDmdzAddressStandardization;
- import com.skyversation.poiaddr.entity.AddrBean;
- import com.skyversation.poiaddr.service.AreaService;
- import com.skyversation.poiaddr.util.AddrSplitLmrMap;
- import com.skyversation.poiaddr.util.ShanghaiAddressSplitUtil;
- import com.skyversation.poiaddr.util.SplitAddress;
- import com.skyversation.poiaddr.util.net.AddressNetTools;
- import com.skyversation.poiaddr.util.status.AddressLevel;
- import com.skyversation.poiaddr.util.status.AddressResultEnum;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.ResponseEntity;
- import org.springframework.util.StringUtils;
- import org.apache.commons.codec.binary.Base64;
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import java.util.*;
- public class AddressQueryEngine {
- private static AddressQueryEngine instance = new AddressQueryEngine();
- private AddressQueryEngine() {
- }
- public synchronized static AddressQueryEngine getInstance() {
- if (instance == null) {
- instance = new AddressQueryEngine();
- }
- return instance;
- }
- /***
- * 单条地名搜索通用方法,搜索顺序 1. 武大吉奥; 2. 市四中心; 3. 高德搜索; 4. 高德高级搜索;
- * @param addrs
- * @return
- */
- public AddressResult commonSearchByName(List<String> addrs) {
- if (addrs == null || addrs.size() < 1) {
- return null;
- }
- AddressResult addressResult = new AddressResult();
- for (String addr : addrs) {
- // 创建请求
- addressResult = sj_szxSearchByName(addr, 3);
- if (addressResult != null) {
- addressResult.setCode(AddressResultEnum.SZX_SUCCESS);
- addressResult.setMessage("成功");
- SplitAddress splitAddress = ShanghaiAddressSplitUtil.splitBestAddress(addr);
- return getCjWgWgwByLoc(addressResult, splitAddress);
- }
- }
- addressResult.setCode(AddressResultEnum.RESULT_NULL);
- addressResult.setMessage("失败");
- return addressResult;
- }
- /***
- * 单条地名搜索通用方法
- * @param addr
- * @return
- */
- public AddressResult commonSearchByName_nw(String addr) {
- if (!StringUtils.hasText(addr) || addr.length() <= 3) {
- return null;
- }
- AddressResult addressResult = new AddressResult();
- AddrBean lmrAddrBean = AddrSplitLmrMap.outAddrMapInAddr(addr);
- if (lmrAddrBean.getRule() == null || Integer.parseInt(lmrAddrBean.getRule()) <= 0) {
- addressResult.setMessage("非上海数据");
- AddressResult.ContentBean content = new AddressResult.ContentBean();
- content.setSearchAddress(addr);
- content.setPname(lmrAddrBean.getProvinces());
- content.setCityname(lmrAddrBean.getMarket());
- content.setAdname(lmrAddrBean.getStreetTown());
- content.setCommunity(lmrAddrBean.getResidentialCommittee());
- content.setScore("rule_0");
- addressResult.setData(new ArrayList<>());
- addressResult.getData().add(content);
- return addressResult;
- }
- SplitAddress splitAddress = ShanghaiAddressSplitUtil.splitBestAddress(addr);
- if (splitAddress.getStatus() == 3) {// 不是地址
- addressResult.setMessage("非地址数据");
- return addressResult;
- } else {
- AddressResult.ContentBean addrBean = new AddressResult.ContentBean();
- addrBean.setSearchAddress(addr);
- addrBean.setPname(splitAddress.getProvince());
- addrBean.setCityname(splitAddress.getCity());
- addrBean.setDistance(splitAddress.getDistrict());
- addrBean.setAdname(splitAddress.getStreet());
- addrBean.setCommunity(splitAddress.getCommunity());
- addrBean.setStandAddr(splitAddress.getCity() + splitAddress.getDistrict() + splitAddress.getStreet()
- + splitAddress.getCommunity() + splitAddress.getAddr());
- addressResult.setAddrBean(addrBean);
- // 优先进行数据库查询
- List<YyskDmdzAddressStandardization> dbPois = AreaService.getInstance().getAddressPoisByAddr(splitAddress);
- if (dbPois != null && dbPois.size() > 0) {
- JSONArray pois = new JSONArray();
- pois.addAll(dbPois);
- SplitAddress splitAddress1 = ShanghaiAddressSplitUtil.splitBestAddress(addr);
- addressResult = new TransfromDataTool().dbResultToResult(splitAddress1, addr, pois);
- addressResult.setAddrBean(addrBean);
- if (addressResult.getData() != null && addressResult.getData().size() > 0) {
- getCjWgWgwByLoc(addressResult, splitAddress);
- addressResult.setCode(AddressResultEnum.DB_SUCCESS);
- addressResult.setMessage("成功");
- AddressResult.ContentBean content = addressResult.getData().get(0);
- addrBean.setPname(content.getPname());
- addrBean.setCityname(content.getCityname());
- addrBean.setAdname(content.getAdname());
- addrBean.setDistance(content.getDistance());
- addrBean.setCommunity(content.getCommunity());
- addrBean.setStandAddr(content.getStandAddr());
- addressResult.setAddrBean(addrBean);
- return addressResult;
- }
- /*} else {
- if (splitAddress.getDistrict() != null && !splitAddress.getDistrict().isEmpty()) {
- //查询无结果,尝试给出推荐结果
- List<YyskDmdzAddressStandardization> recommendPois = AreaService.getInstance().getRecommendAddress(splitAddress);
- if (recommendPois != null && recommendPois.size() > 0) {
- JSONArray pois = new JSONArray();
- pois.addAll(recommendPois);
- SplitAddress splitAddress1 = ShanghaiAddressSplitUtil.splitBestAddress(addr);
- addressResult = new TransfromDataTool().dbResultToResult(splitAddress1, addr, pois);
- addressResult.setAddrBean(addrBean);
- if (addressResult != null && addressResult.getData() != null && addressResult.getData().size() > 0) {
- getCjWgWgwByLoc(addressResult);
- addressResult.setCode(AddressResultEnum.DB_RECOMMEND_SUCCESS);
- addressResult.setMessage("成功");
- AddressResult.ContentBean content = addressResult.getData().get(0);
- addrBean.setPname(content.getPname());
- addrBean.setCityname(content.getCityname());
- addrBean.setAdname(content.getAdname());
- addrBean.setDistance(content.getDistance());
- addrBean.setCommunity(content.getCommunity());
- addrBean.setStandAddr(content.getStandAddr());
- addressResult.setAddrBean(addrBean);
- return addressResult;
- }
- }
- }*/
- }
- }
- addressResult.setMessage("失败");
- return addressResult;
- }
- public static Map<String, String> initSigns() {
- Map<String, String> headerMap = new HashMap<>();
- String timestamp = System.currentTimeMillis() + "";
- String appCode = "7unv4vbwqxnq4a7m9h";
- String UUid = UUID.randomUUID().toString();
- String appSecret = "w6tawvf4k3ck4ikij9";
- headerMap.put("x-timestamp", timestamp);
- headerMap.put("x-appcode", appCode);
- headerMap.put("x-uuid", UUid);
- // 签名
- headerMap.put("x-sign", AddressQueryEngine.getSigns(timestamp, appCode, UUid, appSecret));
- return headerMap;
- }
- public static String getSigns(String timestamp, String appCode, String UUid, String appSecret) {
- // 先拼接
- String signData = timestamp + appCode + UUid;
- // 生成sign
- String sign = "";
- try {
- Mac sha256 = Mac.getInstance("HmacSHA256");
- sha256.init(new SecretKeySpec(appSecret.getBytes(), "HmacSHA256"));
- byte[] result = sha256.doFinal(signData.getBytes());
- sign = Base64.encodeBase64String(result);
- } catch (Exception e) {
- System.err.println("sign 生成异常:" + e);
- }
- return sign;
- }
- public AddressResult sj_szxSearchByName(String address, Integer level) {
- // 鉴权
- JSONObject params = new JSONObject();
- JSONArray requestJson = new JSONArray();
- JSONObject paramObject = new JSONObject();
- paramObject.put("name", "query");
- paramObject.put("position", "QUERY");
- switch (level) {
- case 3:
- paramObject.put("value", address);
- break;
- case 2:
- if (address.contains("号")) {
- paramObject.put("value", address.substring(0, address.lastIndexOf("号") + 1));
- } else {
- level--;
- return sj_szxSearchByName(address, level);
- }
- break;
- case 1:
- if (address.contains("弄")) {
- paramObject.put("value", address.substring(0, address.lastIndexOf("弄") + 1));
- } else {
- paramObject.put("value", address);
- }
- break;
- }
- if (address.startsWith("中山")) {
- if (!address.startsWith("中山街道")) {
- paramObject.put("value", "中山街道" + paramObject.get("value").toString().substring(2));
- }
- }
- if (!address.startsWith("上海")) {
- paramObject.put("value", "上海市" + paramObject.get("value"));
- }
- requestJson.add(paramObject);
- // 判断是否是关键字版搜索服务
- if (Constant.SJ_SZX_SEARCH_BY_NAME.contains("1742459783686")) {
- JSONObject paramObject2 = new JSONObject();
- paramObject2.put("name", "region");
- paramObject2.put("position", "QUERY");
- paramObject2.put("value", Constant.getAMAP_CITY_CODE());
- requestJson.add(paramObject2);
- JSONObject paramObject3 = new JSONObject();
- paramObject3.put("name", "page_size");
- paramObject3.put("position", "QUERY");
- paramObject3.put("value", "10");
- requestJson.add(paramObject3);
- }
- params.put("requestJson", requestJson);
- // 发起请求
- ResponseEntity response = AddressNetTools.getInstance().requestGetOrPost(HttpMethod.POST, Constant.SJ_SZX_SEARCH_BY_NAME, params, initSigns(), 5);
- if (response != null && response.hasBody()) {
- String body = response.getBody() + "";
- if (!StringUtils.hasText(body)) {
- if (level > 0) {
- level--;
- return sj_szxSearchByName(address, level);
- }
- return new AddressResult(AddressResultEnum.RESULT_NULL, "搜索无结果");
- }
- try {
- AddressResult addressResult = TransfromDataTool.szxResultToResult(JSONObject.parseObject(body), address);
- if (addressResult.getCode().equals(AddressResultEnum.RESULT_NULL) && level > 0) {
- level--;
- return sj_szxSearchByName(address, level);
- }
- return addressResult;
- } catch (Exception e) {
- System.err.println("请求地址:" + address + ";返回结果:" + body + ";处理异常:" + e);
- return new AddressResult(AddressResultEnum.DATA_FROMAT_FAILD, "格式化失败");
- }
- } else {
- if (level > 0) {
- level--;
- return sj_szxSearchByName(address, level);
- }
- System.out.println("地址[" + address + "]未查询到数据!");
- return null;
- }
- }
- /***
- * 根据搜索地址,赋值村居、网格、微格网信息
- * @param result
- * @return
- */
- public AddressResult getCjWgWgwByLoc(AddressResult result, SplitAddress splitAddress) {
- if (result == null || result.getData() == null || result.getData().size() < 1) {
- return result;
- } else {
- AreaService areaService = AreaService.getInstance();
- for (AddressResult.ContentBean content : result.getData()) {
- if (content.getLat() != null && content.getLon() != null) {
- // 判断是否存在村居数据
- if (content.getCommunity() == null || content.getCommunity().isEmpty()) {
- GeoJsonBean cjBean = areaService.isInResidentialCommitteePolygon(content.getLon(), content.getLat());
- if (cjBean != null && cjBean.getProperties() != null) {
- content.setPname("上海市");
- content.setCityname(cjBean.getProperties().getString("所属区"));
- content.setAdname(cjBean.getProperties().getString("所属街"));
- content.setCommunityCode(cjBean.getProperties().getString("居委会"));
- content.setCommunity(cjBean.getProperties().getString("居委_1"));
- }
- }
- // 判断是否存在街镇数据
- if (content.getAdname() == null || content.getAdname().isEmpty()) {
- GeoJsonBean townBean = areaService.isInTownPolygon(content.getLon(), content.getLat());
- if (townBean != null && townBean.getProperties() != null) {
- content.setPname("上海市");
- content.setAdnameCode(townBean.getProperties().getString("area_code"));
- content.setAdname(townBean.getProperties().getString("name"));
- }
- }
- if ((content.getAdname() == null || content.getAdname().isEmpty() || content.getCityname() == null || content.getCityname().isEmpty() || content.getCommunity() == null || content.getCommunity().isEmpty())) {
- // 判断是否存在行政区划数据
- if (content.getCityname() == null || content.getCityname().isEmpty()) {
- GeoJsonBean adBean = areaService.isInadPolygon(content.getLon(), content.getLat());
- if (adBean != null && adBean.getProperties() != null) {
- content.setPname("上海市");
- content.setCityname(adBean.getProperties().getString("name"));
- }
- }
- }
- content.setStandAddr(content.getPname() + content.getCityname() + content.getAdname() + splitAddress.getAddr());
- } else {
- System.err.println("没有经纬度参数,不能根据经纬度落点补充街镇等信息!");
- }
- }
- return result;
- }
- }
- public AddressResult.ContentBean addContentWGWGrid(AddressResult.ContentBean content) {
- AreaService areaService = AreaService.getInstance();
- if (content != null && content.getLat() != null && content.getLon() != null) {
- if (!StringUtils.hasText(content.getWgName())) {
- GeoJsonBean geoJsonBean = areaService.isInWGPolygon(content.getLon(), content.getLat());
- if (geoJsonBean != null && geoJsonBean.getProperties() != null) {
- content.setWgName(geoJsonBean.getProperties().getString("网格名称"));
- content.setWgCode(geoJsonBean.getProperties().getString("网格编码"));
- }
- }
- if (!StringUtils.hasText(content.getWgwCode())) {
- GeoJsonBean geoJsonBean = areaService.isInWGWPolygon(content.getLon(), content.getLat());
- if (geoJsonBean != null && geoJsonBean.getProperties() != null) {
- content.setWgwName(geoJsonBean.getProperties().getString("å¾®ç½\u0091_1"));
- content.setWgwCode(geoJsonBean.getProperties().getString("å¾®ç½\u0091æ ¼"));
- }
- }
- if (!StringUtils.hasText(content.getZhwgName())) {
- GeoJsonBean geoJsonBean = areaService.isInZHGWPolygon(content.getLon(), content.getLat());
- if (geoJsonBean != null && geoJsonBean.getProperties() != null) {
- content.setZhwgName(geoJsonBean.getProperties().getString("网格名称"));
- content.setZhwgCode(geoJsonBean.getProperties().getString("网格编码"));
- }
- }
- }
- return content;
- }
- //
- public static boolean isNotEmptyOrBlank(String str) {
- return str != null && !str.trim().isEmpty();
- }
- /**
- * 1. 搜索到结果就返回第一个;
- * 2. 搜索到结果去除行政区划后,存在包含关系,则使用;
- * 3. 搜索到结果,数字进行分词,数字匹配则使用;
- * 4. 搜索到结果,数字与文本均匹配,则使用;
- * 5. 结果与基准数据完全一致,则使用。
- *
- * @param result
- * @param level
- * @return
- */
- public AddressResult.ContentBean verificaData(AddressResult result, AddressLevel level, String addr) {
- switch (level) {
- case LEVEL_1: {
- if (result != null && result.getData() != null && result.getData().size() > 0) {
- return result.getData().get(0);
- } else {
- return null;
- }
- }
- // 2. 搜索到结果去除行政区划后,存在包含关系,则使用;
- case LEVEL_CONTAINS_2: {
- if (result != null && result.getData() != null && result.getData().size() > 0) {
- List<AddressResult.ContentBean> contentBean = result.getData();
- for (AddressResult.ContentBean contentBean1 : contentBean) {
- if (contentBean1.getAddress() != null) {
- String address = townReplaceAll(addressReplaceAll(contentBean1.getAddress()));
- String address2 = townReplaceAll(addressReplaceAll(addr));
- if (isNotEmptyOrBlank(address) && address.contains(address2)) {
- return contentBean1;
- }
- }
- }
- } else {
- return null;
- }
- }
- // 3. 搜索到结果,数字进行分词,数字匹配则使用;
- case LEVLE_NUMBER_3: {
- if (result != null && result.getData() != null && result.getData().size() > 0) {
- List<AddressResult.ContentBean> contentBean = result.getData();
- for (AddressResult.ContentBean contentBean1 : contentBean) {
- if (contentBean1.getAddress() != null) {
- Set<String> address = tokenizeString(contentBean1.getAddress()).get(1);
- if (address != null && address.size() > 1) {
- Set<String> address2 = tokenizeString(addr).get(1);
- int addressSize = address.size();
- for (String addr2 : address2) {
- if (address.contains(addr2)) {
- addressSize--;
- if (addressSize == 0) {
- return contentBean1;
- }
- }
- }
- }
- }
- }
- } else {
- return null;
- }
- }
- // 4. 搜索到结果,数字与文本均匹配,则使用;
- case LEVEL_NUMBER_TEXT_4: {
- if (result != null && result.getData() != null && result.getData().size() > 0) {
- List<AddressResult.ContentBean> contentBean = result.getData();
- for (AddressResult.ContentBean contentBean1 : contentBean) {
- if (contentBean1.getAddress() != null) {
- Set<String> addressString = tokenizeString(contentBean1.getAddress()).get(0);
- Set<String> addressNumber = tokenizeString(contentBean1.getAddress()).get(1);
- Set<String> address2String = tokenizeString(addr).get(0);
- Set<String> address2Number = tokenizeString(addr).get(1);
- if (addressString != null && addressString.size() > 1) {
- int addressStrSize = addressString.size();
- for (String addr2str : address2String) {
- if (addressString.contains(addr2str)) {
- addressStrSize--;
- if (addressStrSize == 0) {
- int addressNumSize = addressNumber.size();
- for (String addr2Num : address2Number) {
- if (addressNumber.contains(addr2Num)) {
- addressNumSize--;
- if (addressNumSize == 0) {
- return contentBean1;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- return null;
- }
- }
- // 结果与基准数据完全一致,则使用。
- case LEVEL_TOTAL_CONTAINS_5: {
- if (result != null && result.getData() != null && result.getData().size() > 0) {
- List<AddressResult.ContentBean> contentBean = result.getData();
- for (AddressResult.ContentBean contentBean1 : contentBean) {
- if (contentBean1.getAddress() != null) {
- String address = addressReplaceAll(contentBean1.getAddress());
- String address2 = addressReplaceAll(addr);
- if (isNotEmptyOrBlank(address) && address.equals(address2)) {
- return contentBean1;
- }
- }
- }
- } else {
- return null;
- }
- }
- default: {
- return null;
- }
- }
- }
- public static String addressReplaceAll(String address) {
- return address.replaceAll("上海市", "").replaceAll(Constant.getArea() + "区", "").replaceAll("-", "").replaceAll("_", "").replaceAll("/", "").replaceAll(" ", "").replaceAll(",", "").replaceAll("\\.", "").replaceAll(",", "").replaceAll("。", "").replaceAll("\\+", "").replaceAll("\\*", "");
- }
- public static String townReplace_ct(String address) {
- address = address.replaceAll(" ", "");
- // 替换市
- address = address.replaceAll("上海市", "");
- String[] towns = Constant.getTowns();
- for (String town : towns) {
- if (address.contains(town)) {
- address = address.substring(address.indexOf(town) + town.length());
- }
- }
- // TODO 强行去除居委
- if (address.contains("居委会")) {
- address = address.substring(address.indexOf("居委会") + 3);
- }
- if (address.contains("委员会")) {
- address = address.substring(address.indexOf("委员会") + 3);
- }
- return address;
- }
- public static String townReplaceAll(String address) {
- address = townReplace_ct(address);
- return address.replaceAll("小区", "0").replaceAll("号", "0").replaceAll("弄", "0").replaceAll("室", "0").replaceAll("户", "0").replaceAll("单元", "0").replaceAll("幢", "0");
- }
- /**
- * 数字和文字分词返回List<Set<String>>
- *
- * @param input
- * @return
- */
- public static List<Set<String>> tokenizeString(String input) {
- // 初始化两个集合,一个用于存储非数字字符串,一个用于存储数字字符串
- Set<String> nonNumberSet = new HashSet<>();
- Set<String> numberSet = new HashSet<>();
- StringBuilder currentToken = new StringBuilder();
- for (int i = 0; i < input.length(); i++) {
- char c = input.charAt(i);
- if (Character.isDigit(c)) {
- // 如果当前字符是数字
- if (currentToken.length() > 0 && !Character.isDigit(currentToken.charAt(0))) {
- // 如果之前的 token 是非数字,将其添加到非数字集合中
- nonNumberSet.add(currentToken.toString());
- currentToken.setLength(0);
- }
- currentToken.append(c);
- } else {
- // 如果当前字符不是数字
- if (currentToken.length() > 0 && Character.isDigit(currentToken.charAt(0))) {
- // 如果之前的 token 是数字,将其添加到数字集合中
- numberSet.add(currentToken.toString());
- currentToken.setLength(0);
- }
- if (!Character.isWhitespace(c)) {
- currentToken.append(c);
- }
- }
- }
- // 处理最后一个 token
- if (currentToken.length() > 0) {
- if (Character.isDigit(currentToken.charAt(0))) {
- numberSet.add(currentToken.toString());
- } else {
- nonNumberSet.add(currentToken.toString());
- }
- }
- // 将两个集合添加到列表中
- List<Set<String>> result = new ArrayList<>();
- result.add(nonNumberSet);
- result.add(numberSet);
- return result;
- }
- }
|