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()); } } }