高德地图---逆地理编码
一.使用场景
因公司需要,新增一个根据经纬度查询所在地址的需求
例如: 113.305377,23.140492
广东省广州市越秀区黄花岗街道广州动物园
二.前期准备
申请高德web服务的key 值,测试够用,如果上线的话,最好用企业账号申请(申请流程高德里面有提示)
三.使用案例
1.所需jar包
<!--导入httpclient jar包和fastjson包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
2.测试代码
package cn.gdmcmc.esi.gaode;
import com.alibaba.fastjson.JSON;
import com.mysql.cj.xdevapi.JsonArray;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Description:高德逆地理编码
* @Author:lighter
* @Date:2019/11/20 16:43
* @Version 1.0
*/
public class GeoCodeTest {
public static void main(String[] args) throws Exception {
//创建一个httpclient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//创建url
//output = json 返回结果数据将会以JSON结构构成
// batch 参数设置为 true 时进行批量查询操作,设置为 false 时进行单点查询,最多查询20个
String urlStr = "https://restapi.amap.com/v3/geocode/regeo? output=json&batch=true&key=053633e246650ab25ae2f58c504e964b&";
//坐标点,多个坐标点之间用 | 连接
//java 中使用String 连接url ,识别 | 错误,要更换成 %7C
String location = "location=113.313596,23.080083";
String url =urlStr+location;
//生成get 请求对象
HttpGet httpGet = new HttpGet(newUrl);
//发送请求
CloseableHttpResponse response = httpClient.execute(httpGet);
//获取响应实体对象
HttpEntity entity = response.getEntity();
//转换成utf-8 编码的字符串
String entityStr = EntityUtils.toString(entity, "utf-8");
//转换成map 的集合
Map map = JSON.parseObject(entityStr, Map.class);
//获取逆地理编码列表列表
//batch=true,此时 regeocodes 标签返回;batch=false,会返回 regeocode对象;
String regeocodes = map.get("regeocodes").toString();
//字符串转换成 List<Map<String,Object>> 类型的集合
List<Map<String,Object>> list = JSON.parseObject(regeocodes,new ArrayList<Map<String,Object>>().getClass());
//循环
for (Map<String, Object> regecodeMap : list) {
//获取结构化地址信息
String s = regecodeMap.get("formatted_address").toString();
System.out.println(s);
}
//关闭资源
httpClient.close();
response.close();
}
}
3.GeocodeUtil 工具类(批量查询)
package cn.gdmcmc.iovs.common.util;
import cn.gdmcmc.iovs.authbasecommon.common.exception.GlobalException;
import cn.gdmcmc.iovs.module.find.pojo.Transboundary;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.type.MapLikeType;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description:
* @Author:lighter
* @Date:2019/11/20 19:23
* @Version 1.0
*/
public class GeocodeUtil {
//地址固定
private static String url = "https://restapi.amap.com/v3/geocode/regeo?output=json&batch=true&key=";
//传入需要查询的集合,和所需的key ,返回转换后的集合
public List<Transboundary> getAddress(List<Transboundary> list,String geoKey)throws Exception{
//分页,每个集合10条数据
if(list.size() <= 10){
List<Map<String,String>> addressList = getAddressList(list,geoKey);
for (int i = 0; i < list.size(); i++) {
Map<String, String> map = addressList.get(i);
list.get(i).setProvince(map.get("province"));
list.get(i).setAddress(map.get("address"));
list.get(i).setCity(map.get("city"));
}
//不分页每个集合20条,查最多经纬度次数20次
}else{
//获取一个空集合,用来装包含地址信息
List<Map<String,String>> addressList = null;
int index = list.size();
//循环传过来要转换的集合
for (int i = 0; i < index; i ++) {
// i 除 20 能整除,拿集合20个对象去获取地址
if(i%20 == 0){
//当索引在最后一个20个队列中,比如总长度为45,i = 40,0-19,20-39,40-45
if(i/20 == index/20){
//截取i=40,i=44,subList()截取包前不包后
List<Transboundary> newList = list.subList(i,index);
//获取地址集合
addressList = getAddressList(newList,geoKey);
//索引不在最后一个20队列中,i=20
}else{
//截取i= 20,i= 39
List<Transboundary> newList = list.subList(i, i + 20);
addressList = getAddressList(newList,geoKey);
}
}
//获取对应地址集合的对象,比如 i = 20 ,地址集合的所获得的对象索引为0
Map<String, String> map = addressList.get(i % 20);
//一一设置
list.get(i).setProvince(map.get("province"));
list.get(i).setAddress(map.get("address"));
list.get(i).setCity(map.get("city"));
}
}
//返回准换后的集合
return list;
}
//获取经纬度查询地址集合
public List<Map<String,String>> getAddressList(List<Transboundary> list,String geoKey) throws Exception{
//先获取一个地址集合
List<Map<String,String>> returnList = new ArrayList<>();
//设置坐标对
String location = "&location=";
//对传过来的集合进行循环,连接经纬度
for (int i = 0; i < list.size(); i++) {
Transboundary transboundary = list.get(i);
//数据库,有时经纬度为0,所以只能自己替换下,免得查询出来的为null,会报异常,并且后面顺序插入也有问题
if (transboundary.getLng().compareTo(BigDecimal.ZERO)== 0 || transboundary.getLat().compareTo(BigDecimal.ZERO)==0){
//自己替代了下坐标点
location += "113.313596,23.080083%7C";
}else{
//在这里我发现,url最后一对坐标点连接 | 这个也没有问题
//所以不进行判断
location += transboundary.getLng().stripTrailingZeros().toPlainString()+ "," + transboundary.getLat().stripTrailingZeros().toPlainString()+"%7C";
}
}
//连接地址
String urlStr = url+ geoKey + location;
//获取httpclient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//创建get对象
HttpGet httpGet = new HttpGet(urlStr);
//发送请求
CloseableHttpResponse response = httpClient.execute(httpGet);
//获取响应体对象
HttpEntity entity = response.getEntity();
//转换成字符串
String entityStr = EntityUtils.toString(entity, "utf-8");
//转换成map,这里应该可以优化,异步转化成后面所需的格式
Map map = JSON.parseObject(entityStr, Map.class);
//获取逆地理编码列表
String regeocodeStr = map.get("regeocodes").toString();
//转换成集合
ArrayList<Map<String, Object>> regeocodeList = JSON.parseObject(regeocodeStr, new ArrayList<Map<String,Object>>().getClass());
//循环
for (Map<String, Object> regeocodeMap : regeocodeList) {
Map<String,String> addMap = new HashMap<>();
//有的时候获取的地址会返回一个"[]",所以自己设置地址
if (JSON.toJSONString(regeocodeMap.get("formatted_address")).equals("[]")){
addMap.put("address","广东省广州市海珠区");
addMap.put("city","广州市");
addMap.put("province","广东省");
returnList.add(addMap);
} else{
//获取地址
addMap.put("address",regeocodeMap.get("formatted_address").toString());
Map<String,Object> addressComponentMap = JSON.parseObject(regeocodeMap.get("addressComponent").toString(),new HashMap<String,Object>().getClass());
//获取省
addMap.put("province",addressComponentMap.get("province").toString());
//获取市,直辖市,城市为"[]"
if(JSON.toJSONString(addressComponentMap.get("city")).equals("[]")){
addMap.put("city","");
}else {
addMap.put("city",addressComponentMap.get("city").toString());
}
//添加到地址集合中
returnList.add(addMap);
}
}
httpClient.close();
response.close();
//返回
return returnList;
}
}
四.所遇问题
1.地址连接
| 转换成 %7C
详细请看:
https://blog.csdn.net/weixin_40165317/article/details/81112845
2.返回的地址为[]
进行判断替换
3.坐标点类型
gps/北斗为地球坐标系
高德/腾讯为火星坐标系
详细请看: