puzhibing
5 天以前 8def7d50fdac0d2d464edce1d94f5bb29c519302
DriverFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDFalconUtil.java
@@ -14,21 +14,26 @@
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
/**
 * 高德猎鹰服务
 * key次数用完时自动切换可用key(切换后自动重建serverId)
 */
@Component
public class GDFalconUtil implements ApplicationRunner {
    private String key = "c473445a931ee8c42eef8b63fc3602c5";
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private GDKeyManager gdKeyManager;
    private static String serverId = null;
    /**
     * 当前serverId对应的key(key切换后需重建serverId)
     */
    private static volatile String currentKey = null;
    public String getServerId() {
@@ -46,20 +51,137 @@
    }
    /**
     * 初始化创建服务
     */
    public void init(){
        if(serverId == null){
            JSONArray jsonArray = this.selectServer();
            if(null == jsonArray){
                serverId = this.createServer("server");
            }else{
                serverId = jsonArray.getJSONObject(0).getString("sid");
            if (gdKeyManager == null || restTemplate == null) {
                // 非容器实例(如 GunsApplication.main 中 new 出来的对象),由容器内bean完成初始化
                return;
            }
            ensureServerId();
        }
    }
    /**
     * 参数构造器:key与sid切换后需按最新值重新构造
     */
    private interface ParamsBuilder {
        MultiValueMap<String, Object> build(String key, String sid);
    }
    /**
     * 确保serverId与当前使用的key对应:
     * key切换后自动查询/重建serverId;key用完自动切换可用key重试
     */
    private synchronized String ensureServerId(){
        int maxAttempts = 5;
        String lastKey = gdKeyManager.getKey();
        for (int i = 0; i < maxAttempts; i++) {
            String gdKey = gdKeyManager.getKey();
            lastKey = gdKey;
            if (serverId != null && gdKey.equals(currentKey)) {
                return gdKey;
            }
            // 1. 查询该key下的服务列表
            JSONArray jsonArray = null;
            try {
                String url = "https://tsapi.amap.com/v1/track/service/list?key=" + gdKey;
                String forObject = restTemplate.getForObject(url, String.class);
                JSONObject jsonObject = JSON.parseObject(forObject);
                if (GDKeyManager.isFalconExhausted(jsonObject)) {
                    gdKeyManager.reportExhausted(gdKey);
                    serverId = null;
                    continue;
                }
                if (jsonObject.getIntValue("errcode") == 10000) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    if (null != data) {
                        jsonArray = data.getJSONArray("results");
                    }
                }
            } catch (Exception e) {
                loggerWarn("查询猎鹰服务列表异常", e);
            }
            if (jsonArray != null && jsonArray.size() > 0) {
                serverId = jsonArray.getJSONObject(0).getString("sid");
                currentKey = gdKey;
                return gdKey;
            }
            // 2. 无服务:创建新服务
            String sid = createServerInternal("server", gdKey);
            if (sid != null) {
                serverId = sid;
                currentKey = gdKey;
                return gdKey;
            }
            // 3. 创建失败(可能key用完):切换key重试
            gdKeyManager.reportExhausted(gdKey);
            serverId = null;
        }
        return lastKey;
    }
    private void loggerWarn(String msg, Exception e) {
        System.err.println("[GDFalconUtil] " + msg + ":" + e.getMessage());
    }
    /**
     * 执行猎鹰POST表单请求:key次数用完时自动切换key并重建serverId重试
     */
    private String doFalconPost(String url, ParamsBuilder builder) {
        String lastResp = null;
        int maxAttempts = 5;
        for (int i = 0; i < maxAttempts; i++) {
            String gdKey = ensureServerId();
            String sid = serverId;
            MultiValueMap<String, Object> params = builder.build(gdKey, sid);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
            String resp = restTemplate.postForObject(url, requestEntity, String.class);
            lastResp = resp;
            JSONObject jsonObject;
            try {
                jsonObject = JSON.parseObject(resp);
            } catch (Exception e) {
                return resp;
            }
            if (GDKeyManager.isFalconExhausted(jsonObject)) {
                gdKeyManager.reportExhausted(gdKey);
                serverId = null;
                continue;
            }
            return resp;
        }
        return lastResp;
    }
    /**
     * 执行猎鹰GET请求:key次数用完时自动切换可用key重试
     */
    private String doFalconGet(String baseUrl) {
        String lastResp = null;
        int maxAttempts = 5;
        for (int i = 0; i < maxAttempts; i++) {
            String gdKey = gdKeyManager.getKey();
            String url = baseUrl + (baseUrl.contains("?") ? "&" : "?") + "key=" + gdKey;
            String resp = restTemplate.getForObject(url, String.class);
            lastResp = resp;
            JSONObject jsonObject;
            try {
                jsonObject = JSON.parseObject(resp);
            } catch (Exception e) {
                return resp;
            }
            if (GDKeyManager.isFalconExhausted(jsonObject)) {
                gdKeyManager.reportExhausted(gdKey);
                continue;
            }
            return resp;
        }
        return lastResp;
    }
@@ -68,6 +190,13 @@
     * @return
     */
    public String createServer(String name){
        return createServerInternal(name, gdKeyManager.getKey());
    }
    /**
     * 创建新的服务(内部直连,供ensureServerId使用)
     */
    private String createServerInternal(String name, String key){
        String url = "https://tsapi.amap.com/v1/track/service/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
@@ -91,24 +220,6 @@
    /**
     * 查询服务
     * @return
     */
    private JSONArray selectServer(){
        String url = "https://tsapi.amap.com/v1/track/service/list?key=" + key;
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
            if(null != data){
                return data.getJSONArray("results");
            }
        }
        return null;
    }
    /**
     * 创建终端数据
     * @param name
     * @return
@@ -118,18 +229,13 @@
        if(tid != null){
            return tid;
        }
        String url = "https://tsapi.amap.com/v1/track/terminal/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("name", name);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        String s = doFalconPost("https://tsapi.amap.com/v1/track/terminal/add", (key, sid) -> {
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            params.add("sid", sid);
            params.add("name", name);
            return params;
        });
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
@@ -146,8 +252,7 @@
     * @return
     */
    public String selectTerminal(String name){
        String url = "https://tsapi.amap.com/v1/track/terminal/list?key=" + key + "&name=" + name;
        String forObject = restTemplate.getForObject(url, String.class);
        String forObject = doFalconGet("https://tsapi.amap.com/v1/track/terminal/list?name=" + name);
        JSONObject jsonObject = JSON.parseObject(forObject);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
@@ -172,18 +277,13 @@
     * @return
     */
    public String createTrack(String tid){
        String url = "https://tsapi.amap.com/v1/track/trace/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("tid", tid);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        String s = doFalconPost("https://tsapi.amap.com/v1/track/trace/add", (key, sid) -> {
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            params.add("sid", sid);
            params.add("tid", tid);
            return params;
        });
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") == 10000){
            return jsonObject.getString("data");
@@ -199,28 +299,18 @@
     * @param trid      轨迹id
     */
    public void deleteTrack(String tid, String trid){
        String url = "https://tsapi.amap.com/v1/track/trace/delete";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("tid", tid);
        params.add("trid", trid);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        String s = doFalconPost("https://tsapi.amap.com/v1/track/trace/delete", (key, sid) -> {
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            params.add("sid", sid);
            params.add("tid", tid);
            params.add("trid", trid);
            return params;
        });
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") != 10000){
            System.err.println(jsonObject.getString("errmsg"));
        }
    }
//
//    public Map<String, Object> queryTrsearch(){
//
//    }
}