Springboot 接入腾讯地图
### 腾讯密钥
> 注册腾讯位置服务 https://lbs.qq.com/ ,实名认证获取到 map key 和secret key。
配置文件增加配置
```
map:
map-key: SRGBZ-*****-GV64Z-TZJ32-CK5TT-E5BQB
secret-key: rIBxFh1O*****YJlrxU5SMhbfE2UGgC5p
```
#### 创建常用类
**经纬度类**
```
public class Location {
/**
* 纬度
*/
private Double lat;
/**
* 经度
*/
private Double lng;
public Location() {
}
public Location(Double lat, Double lng) {
this.lat = lat;
this.lng = lng;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
@Override
public String toString() {
return lat + "," + lng;
}
}
```
**距离计算类**
```
import org.jetbrains.annotations.NotNull;
import java.util.StringJoiner;
/***
*
* 地图经纬度以及距离
*/
public class LocationDistance implements Comparable {
private Location to;
private Location from;
// 起点到终点的距离,单位:米
private Integer distance;
public Location getTo() {
return to;
}
public void setTo(Location to) {
this.to = to;
}
public Location getFrom() {
return from;
}
public void setFrom(Location from) {
this.from = from;
}
public Integer getDistance() {
return distance;
}
public void setDistance(Integer distance) {
this.distance = distance;
}
public LocationDistance(Location to, Location from) {
this.to = to;
this.from = from;
}
public LocationDistance(Location to, Location from, Integer distance) {
this.to = to;
this.from = from;
this.distance = distance;
}
@Override
public int compareTo(@NotNull LocationDistance o) {
return this.distance - o.getDistance();
}
@Override
public String toString() {
return new StringJoiner(", ", LocationDistance.class.getSimpleName() + "[", "]")
.add("to=" + to)
.add("from=" + from)
.add("distance=" + distance)
.toString();
}
}
```
**地点信息类**
```
import java.util.StringJoiner;
/***
*
* 地图点详细信息
*/
public class LocationPlace {
/**
*
* poi名称
*/
private String name;
/***
*
* 国家
*/
private String nation;
/**
*
* 省
*/
private String province;
/**
*
* 市
*/
private String city;
/**
*
* 区县
*/
private String district;
/**
*
* poi地址。默认不召回,若有需求请联系我们(完成企业认证后,才能开通权限)
*/
private String address;
/**
*
* poi经纬度坐标
*/
private Location location;
public LocationPlace(Location location) {
this.location = location;
}
public LocationPlace(Double lat, Double lng) {
this.location = new Location(lat, lng);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
@Override
public String toString() {
return new StringJoiner(", ", LocationPlace.class.getSimpleName() + "[", "]")
.add("name='" + name + "'")
.add("nation='" + nation + "'")
.add("province='" + province + "'")
.add("city='" + city + "'")
.add("district='" + district + "'")
.add("address='" + address + "'")
.add("location=" + location)
.toString();
}
}
```
#### 签名校验
签名校验规则(地址:[https://lbs.qq.com/faq/serverFaq/webServiceKey](https://lbs.qq.com/faq/serverFaq/webServiceKey))

请求参数类,用于封装用户的请求
```
import org.jetbrains.annotations.NotNull;
/***
*
* 请求参数
*/
public class Param implements Comparable {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Param(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public int compareTo(@NotNull Param o) {
return this.key.compareTo(o.getKey());
}
@Override
public String toString() {
return key + "=" + value;
}
}
```
生成签名和url的工具类,用户针对传递的参数生成完成的url地址
```
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.DigestUtils;
import java.util.Collections;
import java.util.List;
public class SignTools {
/***
*
* 拼接get请求URL
*
* @param url 请求地址
* @param params 请求参数
* @return
*/
@NotNull
public static String createUrl(String url, List params) {
Collections.sort(params);
String paramStr = url + "?" + StringUtils.join(params, "&");
return paramStr;
}
/***
* 通过 sign 生成进行签名验证
*
* @param url
* @param params
* @param sk
* @return
*/
public static String createUrlBySign(String url, List params, String sk) {
// 生成签名
String sign = createSign(url, params, sk);
params.add(new Param("sig", sign));
// 生成url 生成最终请求:将计算得到的签名sig,放到请求中(参数名即为:sig):
return createUrl(url, params);
}
/****
* 生成签名字段
* 请求路径+”?”+请求参数+SK进行拼接,并计算拼接后字符串md5值(字符必须为小写),即为签名(sig):
* 要求:请求参数必须是未进行任何编码(如urlencode)的原始数据
* md5("/ws/geocoder/v1?key=5Q5BZ-5EVWJ-SN5F3-*****&location=28.7033487,115.8660847SWvT26ypwq5Nwb5RvS8cLi6NSoH8HlJX")
*
* @param url
* @param map
* @param sk
*/
private static String createSign(String url, List map, String sk) {
// 生成签名
String url1 = createUrl(url, map);
url1 = url1 + sk;
return DigestUtils.md5DigestAsHex(url1.getBytes());
}
}
```
### 案例
针对腾讯地图的逆地址解析、批量距离计算以及路径规划接口进行演示。
```
public class QQMapUtil {
public String DOMAIN = "https://apis.map.qq.com";
// 逆地址解析URL
public String GE0C0DER_URL = "/ws/geocoder/v1";
// 批量距离计算
public String Matrix_URL = "/ws/distance/v1/matrix";
// 路线规划
public String ROUTE_URL = "/ws/direction/v1/driving";
/***
* 逆地址解析,根据经纬度获取详细地址信息
*
* @param lat
* @param lng
* @return
*/
public LocationPlace getAddress(Double lat, Double lng, String mapKey, String secretKey) {
// 生成请求URL
List params = new ArrayList<>();
params.add(new Param("location", lat + "," + lng));
params.add(new Param("key", mapKey));
params.add(new Param("get_poi", "1"));
// 根据签名生成url
String url = DOMAIN + SignTools.createUrlBySign(GE0C0DER_URL, params, secretKey);
System.out.println(url);
// 发送请求
HttpResponse res = HttpRequest.get(url).execute();
LocationPlace locationPlace = new LocationPlace(lat, lng);
JSONObject respond = JSONUtil.parseObj(res.body());
// 处理响应数据
if (res.isOk() && respond.getInt("status") == 0) {
JSONObject result = respond.getJSONObject("result");
locationPlace.setName(result.getStr("address"));
locationPlace.setAddress(result.getStr("address"));
JSONObject addressComponent = result.getJSONObject("address_component");
locationPlace.setNation(addressComponent.getStr("nation"));
locationPlace.setProvince(addressComponent.getStr("province"));
locationPlace.setCity(addressComponent.getStr("city"));
locationPlace.setDistrict(addressComponent.getStr("district"));
return locationPlace;
} else {
System.out.println(respond.toString());
return null;
}
}
/***
* 计算起点最近的点
*
* @param from
* @param toList
* @return
*/
public List sortByNear(Location from, List toList, String mapKey, String secretKey) {
// 生成请求URL
List params = new ArrayList<>();
params.add(new Param("mode", "driving"));
// params.add(new Param("key", key));
params.add(new Param("key", mapKey));
params.add(new Param("from", from.toString()));
params.add(new Param("to", StringUtils.join(toList, ";")));
// 根据签名生成url
String url = DOMAIN + SignTools.createUrlBySign(Matrix_URL, params, secretKey);
HttpResponse res = HttpRequest.get(url).execute();
JSONObject respond = JSONUtil.parseObj(res.body());
List distanceList = new ArrayList<>();
if (res.isOk() && respond.getInt("status") == 0) {
JSONObject result = (JSONObject) respond.getJSONObject("result").getJSONArray("rows").get(0);
JSONArray elementsList = result.getJSONArray("elements");
System.out.println(elementsList);
for (int i = 0; i < elementsList.size(); i++) {
JSONObject elements = (JSONObject) elementsList.get(i);
System.out.println(elements);
if (!elements.containsKey("status") || elements.getInt("status") != 4) {
distanceList.add(new LocationDistance(from, toList.get(i), elements.getInt("distance")));
} else {
distanceList.add(new LocationDistance(from, toList.get(i), Integer.MAX_VALUE));
}
}
Collections.sort(distanceList);
return distanceList;
} else {
return null;
}
}
/***
* 计算起点一定返回内的司机
*
* @param from 起点经纬度
* @param toList 终点经纬度
* @param limitDistance 范围
* @return
*/
public List sortByNearLimitDistance(Location from, List toList, Integer limitDistance,
String mapKey, String secretKey) {
// 生成请求URL
List params = new ArrayList<>();
params.add(new Param("mode", "driving"));
params.add(new Param("key", mapKey));
params.add(new Param("from", from.toString()));
params.add(new Param("to", StringUtils.join(toList, ";")));
// 根据签名生成url
String url = DOMAIN + SignTools.createUrlBySign(Matrix_URL, params, secretKey);
HttpResponse res = HttpRequest.get(url).execute();
JSONObject respond = JSONUtil.parseObj(res.body());
List distanceList = new ArrayList<>();
if (res.isOk() && respond.getInt("status") == 0) {
JSONObject result = (JSONObject) respond.getJSONObject("result").getJSONArray("rows").get(0);
JSONArray elementsList = result.getJSONArray("elements");
System.out.println(elementsList);
for (int i = 0; i < elementsList.size(); i++) {
JSONObject elements = (JSONObject) elementsList.get(i);
System.out.println(elements);
if (!elements.containsKey("status") || elements.getInt("status") != 4) {
Integer distance = elements.getInt("distance");
if (distance < limitDistance) {
distanceList.add(new LocationDistance(from, toList.get(i), distance));
}
}
}
Collections.sort(distanceList);
return distanceList;
} else {
return null;
}
}
/***
* 计算里程
*
* @param from 起点
* @param to 终点
* @param wayList 途经点
* @return
*/
public LocationDistance calcMileage(Location from, Location to, List wayList, String mapKey,
String secretKey) {
// 生成请求URL
List params = new ArrayList<>();
params.add(new Param("key", mapKey));
params.add(new Param("from", from.toString()));
params.add(new Param("to", to.toString()));
params.add(new Param("waypoints", StringUtils.join(wayList, ";")));
// 根据签名生成url
String url = DOMAIN + SignTools.createUrlBySign(ROUTE_URL, params, secretKey);
HttpResponse res = HttpRequest.get(url).execute();
JSONObject respond = JSONUtil.parseObj(res.body());
if (res.isOk() && respond.getInt("status") == 0) {
JSONObject routes = (JSONObject) respond.getJSONObject("result").getJSONArray("routes").get(0);
return new LocationDistance(from, to, routes.getInt("distance"));
} else {
return null;
}
}
}
```
