wlzboy
2025-11-16 f67945d53b20f6a45ae50b27d74c966eb1355bb4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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("&region=").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());
        }
    }
}