package com.ruoyi.system.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.system.domain.dto.GeocodeResult;
|
import com.ruoyi.system.service.IGeocodeService;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
import org.springframework.web.client.RestTemplate;
|
|
import java.net.URLEncoder;
|
|
/**
|
* 地理编码服务实现类
|
* 使用腾讯地图WebService API
|
*/
|
@Service
|
public class GeocodeServiceImpl implements IGeocodeService {
|
|
private static final Logger log = LoggerFactory.getLogger(GeocodeServiceImpl.class);
|
|
/**
|
* 腾讯地图API密钥,从配置文件读取
|
* 需要在application.yml中配置:tencent.map.key
|
*/
|
@Value("${tencent.map.key:}")
|
private String tencentMapKey;
|
|
/**
|
* 腾讯地图地理编码API地址
|
*/
|
private static final String GEOCODE_API_URL = "https://apis.map.qq.com/ws/geocoder/v1/";
|
|
private final RestTemplate restTemplate = new RestTemplate();
|
|
@Override
|
public GeocodeResult getCoordinatesByAddress(String address) {
|
return getCoordinatesByAddress(address, null);
|
}
|
|
@Override
|
public GeocodeResult getCoordinatesByAddress(String address, String city) {
|
if (address == null || address.trim().isEmpty()) {
|
return new GeocodeResult(false, "地址不能为空");
|
}
|
|
// 检查API密钥是否配置
|
if (tencentMapKey == null || tencentMapKey.trim().isEmpty()) {
|
log.error("腾讯地图API密钥未配置,请在application.yml中配置tencent.map.key");
|
return new GeocodeResult(false, "地图API密钥未配置");
|
}
|
|
try {
|
// 构建请求URL
|
StringBuilder urlBuilder = new StringBuilder(GEOCODE_API_URL);
|
urlBuilder.append("?address=").append(URLEncoder.encode(address, "UTF-8"));
|
urlBuilder.append("&key=").append(tencentMapKey);
|
|
// 如果指定了城市,添加region参数提高准确度
|
if (city != null && !city.trim().isEmpty()) {
|
urlBuilder.append("®ion=").append(URLEncoder.encode(city, "UTF-8"));
|
}
|
|
String url = urlBuilder.toString();
|
log.info("调用腾讯地图地理编码API: {}", url);
|
|
// 发送HTTP GET请求
|
String response = restTemplate.getForObject(url, String.class);
|
log.info("腾讯地图API响应: {}", response);
|
|
// 解析JSON响应
|
JSONObject jsonResponse = JSON.parseObject(response);
|
Integer status = jsonResponse.getInteger("status");
|
|
if (status == null || status != 0) {
|
String message = jsonResponse.getString("message");
|
log.error("地理编码失败: status={}, message={}", status, message);
|
return new GeocodeResult(false, "地理编码失败: " + message);
|
}
|
|
// 提取坐标信息
|
JSONObject result = jsonResponse.getJSONObject("result");
|
if (result == null) {
|
return new GeocodeResult(false, "未找到地理编码结果");
|
}
|
|
JSONObject location = result.getJSONObject("location");
|
if (location == null) {
|
return new GeocodeResult(false, "未找到坐标信息");
|
}
|
|
Double lat = location.getDouble("lat");
|
Double lng = location.getDouble("lng");
|
|
if (lat == null || lng == null) {
|
return new GeocodeResult(false, "坐标数据格式错误");
|
}
|
|
// 获取标准化地址
|
String standardAddress = result.getString("address");
|
|
GeocodeResult geocodeResult = new GeocodeResult(lat, lng, standardAddress);
|
log.info("地理编码成功: {}", geocodeResult);
|
|
return geocodeResult;
|
|
} catch (Exception e) {
|
log.error("地理编码服务异常", e);
|
return new GeocodeResult(false, "地理编码服务异常: " + e.getMessage());
|
}
|
}
|
}
|