diff --git a/src/main/java/com/platform/cac/CacHpApi.java b/src/main/java/com/platform/cac/CacHpApi.java index fcc3c68..9944248 100644 --- a/src/main/java/com/platform/cac/CacHpApi.java +++ b/src/main/java/com/platform/cac/CacHpApi.java @@ -1,6 +1,7 @@ package com.platform.cac; +import com.fasterxml.jackson.core.type.TypeReference; import com.platform.info.GlobalData; import com.platform.model.DirectControlUavParam; import com.platform.model.Result; @@ -45,12 +46,13 @@ public class CacHpApi { return null; } } - private static Result postRequestAndGetResult(String api, String body) { + private static Result<String> postRequestAndGetResult(String api, String body) { String path = "http://" + HOST + api; HashMap<String, String> header = new HashMap<>(3); generateAuthAndDateHeader(header, "POST", GlobalData.GCS_ID, GlobalData.GCS_TOKEN, api); try { - return HttpClientUtils.sendPost(path, body, header, Result.class); + String responseStr = HttpClientUtils.sendPost(path, body, header); + return JSONUtils.json2obj(responseStr, new TypeReference<Result<String>>() {}); } catch (ConnectException e) { log.error("[cac] http请求超时: {}", e.getMessage()); return null; @@ -85,12 +87,12 @@ public class CacHpApi { */ public static String gcsSignIn(String body) { final String gcsSignApi = HTFP_PATH + "/signIn"; - Result result = postRequestAndGetResult(gcsSignApi, body); + Result<String> result = postRequestAndGetResult(gcsSignApi, body); if (result == null || !result.isSuccess()) { log.error("[cac] 地面站上线失败: {}", result); return null; } - return result.getData().toString(); + return result.getData(); } /** @@ -108,7 +110,7 @@ public class CacHpApi { body.put("uavId", uavId); body.put("gcsId", GlobalData.GCS_ID); try { - Result result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); + Result<String> result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); if (result == null || !result.isSuccess()) { log.error("[cac] 无人机上线失败: {}", result); return false; @@ -128,7 +130,7 @@ public class CacHpApi { body.put("uavId", uavId); body.put("gcsId", GlobalData.GCS_ID); try { - Result result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); + Result<String> result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); if (result == null || !result.isSuccess()) { log.error("[cac] 无人机下线失败: {}", result); return false; @@ -154,7 +156,7 @@ public class CacHpApi { */ public static boolean commandNotify(String body) { final String gcsSignApi = HTFP_PATH + "/notifyUavCommand"; - Result result = postRequestAndGetResult(gcsSignApi, body); + Result<String> result = postRequestAndGetResult(gcsSignApi, body); if (result == null || !result.isSuccess()) { log.error("[cac] 指令执行结果通知失败: {}", result); return false; @@ -166,7 +168,7 @@ public class CacHpApi { */ public static boolean uavParamQueryResultNotify(String body) { final String gcsSignApi = HTFP_PATH + "/uavParamQueryResultNotify"; - Result result = postRequestAndGetResult(gcsSignApi, body); + Result<String> result = postRequestAndGetResult(gcsSignApi, body); if (result == null || !result.isSuccess()) { log.error("[cac] 参数查询结果通知失败: {}", result); return false; @@ -179,7 +181,7 @@ public class CacHpApi { */ public static boolean uavParamBindResultNotify(String body) { final String gcsSignApi = HTFP_PATH + "/uavParamBindResultNotify"; - Result result = postRequestAndGetResult(gcsSignApi, body); + Result<String> result = postRequestAndGetResult(gcsSignApi, body); if (result == null || !result.isSuccess()) { log.error("[cac] 装订执行结果通知失败: {}", result); return false; @@ -192,12 +194,12 @@ public class CacHpApi { public static List<DirectControlUavParam> queryAllCacDirectControlUavList(String body) { final String gcsSignApi = HTFP_PATH + "/queryAllCacDirectControlUavList"; try { - Result result = postRequestAndGetResult(gcsSignApi, body); + Result<String> result = postRequestAndGetResult(gcsSignApi, body); if (result == null || !result.isSuccess()){ log.error("查询全量无人机映射关系失败: {}", result); return null; } - return JSONUtils.json2list(result.getData().toString(), DirectControlUavParam.class); + return JSONUtils.json2list(result.getData(), DirectControlUavParam.class); } catch (Exception e) { log.error("查询全量无人机映射关系失败: {}", e.getMessage()); } @@ -209,12 +211,12 @@ public class CacHpApi { Map<String, String> body = new HashMap<>(); body.put("haborSn", haborSn); try { - Result result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); + Result<String> result = postRequestAndGetResult(gcsSignApi, JSONUtils.obj2json(body)); if (result == null || !result.isSuccess()){ log.error("查询单个无人机映射关系失败,body={}, result={}", body, result); return null; } - return JSONUtils.json2obj(result.getData().toString(), DirectControlUavParam.class); + return JSONUtils.json2obj(result.getData(), DirectControlUavParam.class); } catch (Exception e) { log.error("查询全量无人机映射关系失败: {}", e.getMessage()); } diff --git a/src/main/java/com/platform/controller/ClientController.java b/src/main/java/com/platform/controller/ClientController.java index bba6429..3a06a82 100644 --- a/src/main/java/com/platform/controller/ClientController.java +++ b/src/main/java/com/platform/controller/ClientController.java @@ -124,7 +124,9 @@ public class ClientController { } sessionCache.mappingListMap.put(source, newTarget); }); - + + // 更新配置文件 + sessionCache.saveMappingListMapToFile(); return true; } @@ -157,6 +159,9 @@ public class ClientController { } } }); + + // 更新配置文件 + sessionCache.saveMappingListMapToFile(); return true; } diff --git a/src/main/java/com/platform/util/JSONUtils.java b/src/main/java/com/platform/util/JSONUtils.java index e14f4fc..4199f79 100644 --- a/src/main/java/com/platform/util/JSONUtils.java +++ b/src/main/java/com/platform/util/JSONUtils.java @@ -22,7 +22,6 @@ public class JSONUtils { } public static ObjectMapper getInstance() { - return objectMapper; } @@ -40,56 +39,41 @@ public class JSONUtils { return objectMapper.readValue(jsonStr, clazz); } /** - * 通用静态方法:将JSON字符串转换为带泛型的类 T<C> + * 通用静态方法:将JSON字符串转换为带泛型的类, T嵌套了其他泛型 */ - public static <T, C> T json2obj(String json, Class<T> baseClass, Class<C> genericClass) throws IOException { - // 构造目标类型的 JavaType - JavaType javaType = objectMapper.getTypeFactory().constructParametricType(baseClass, genericClass); - // 使用 ObjectMapper 转换 JSON 字符串为目标类型 - return objectMapper.readValue(json, javaType); + public static <T> T json2obj(String json, TypeReference<T> typeReference) throws IOException { + return objectMapper.readValue(json, typeReference); } /** * json string convert to map */ - public static <T> Map<String, Object> json2map(String jsonStr) - throws IOException { - return objectMapper.readValue(jsonStr, Map.class); + public static Map<String, Object> json2map(String jsonStr) throws IOException { + return objectMapper.readValue(jsonStr, new TypeReference<Map<String, Object>>() {}); } /** - * json string convert to map with javaBean + * JSON string convert to map with specific javaBean */ - public static <T> Map<String, T> json2map(String jsonStr, Class<T> clazz) - throws IOException { - Map<String, Map<String, Object>> map = (Map<String, Map<String, Object>>) objectMapper.readValue(jsonStr, - new TypeReference<Map<String, T>>() { - }); - Map<String, T> result = new HashMap<String, T>(); - for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) { - result.put(entry.getKey(), map2obj(entry.getValue(), clazz)); - } - return result; + public static <T> Map<String, T> json2map(String jsonStr, Class<T> clazz) throws IOException { + JavaType type = objectMapper.getTypeFactory().constructMapType(Map.class, String.class, clazz); + return objectMapper.readValue(jsonStr, type); } /** - * json array string convert to list with javaBean + * json array string convert to list with specific javaBean */ public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) throws IOException { - List<Map<String, Object>> list = (List<Map<String, Object>>) objectMapper.readValue(jsonArrayStr, - new TypeReference<List<T>>() { - }); - List<T> result = new ArrayList<T>(); - for (Map<String, Object> map : list) { - result.add(map2obj(map, clazz)); - } - return result; + return objectMapper.readValue( + jsonArrayStr, + objectMapper.getTypeFactory().constructCollectionType(List.class, clazz) + ); } /** * map convert to javaBean */ - public static <T> T map2obj(Map map, Class<T> clazz) { + public static <T> T map2obj(Map<String, T> map, Class<T> clazz) { return objectMapper.convertValue(map, clazz); } diff --git a/src/main/java/com/platform/util/SessionCache.java b/src/main/java/com/platform/util/SessionCache.java index 1e6a55d..e782b64 100644 --- a/src/main/java/com/platform/util/SessionCache.java +++ b/src/main/java/com/platform/util/SessionCache.java @@ -1,11 +1,21 @@ package com.platform.util; import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.core.type.TypeReference; + +import io.micrometer.core.instrument.util.JsonUtils; import io.netty.channel.Channel; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; +import javax.annotation.PostConstruct; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -15,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap; @Component @Slf4j public class SessionCache { - public Map<String, Channel> tcpSession = new ConcurrentHashMap<>(16); public Map<String, String> addToSnMap = new ConcurrentHashMap<>(16); // ip地址对应的设备编号 @@ -26,6 +35,10 @@ public class SessionCache { public Map<String, List<String>> snToListMap = new ConcurrentHashMap<>(16); //一对多映射关系 public List<String> snList = new ArrayList<>(); + private static final String MAPPING_LIST_MAP_FILE = System.getProperty("user.dir") + File.separator + "mappingListMap.json"; + + + public Optional<Channel> findTargetChannel(String sourceAddr) { String sSn = addToSnMap.get(sourceAddr); String tSn = snToSnMap.get(sSn); @@ -140,5 +153,58 @@ public class SessionCache { } + // mappingListMap 保存到本地文件 + @PostConstruct + public void init() { + loadMappingListMapFromFile(); + } + + /** + * 获取 mappingListMap + */ + public Map<String, List<String>> getMappingListMap() { + return mappingListMap; + } + +/** + * 加载持久化的 mappingListMap + */ + private void loadMappingListMapFromFile() { + File file = new File(MAPPING_LIST_MAP_FILE); + if (!file.exists()) { + log.info("[config] haborSn-gcsMac映射关系文件不存在,初始化为空"); + return; + } + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + StringBuilder jsonBuilder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + jsonBuilder.append(line); + } + String json = jsonBuilder.toString(); + if (!json.isEmpty()) { + Map<String, List<String>> loadedMap = JSONUtils.json2obj(json, new TypeReference<Map<String, List<String>>>() {}); + if (loadedMap != null) { + this.mappingListMap.putAll(loadedMap); + log.info("[config] 成功加载 haborSn-gcsMac 映射关系: {}", mappingListMap); + } + } + } catch (IOException e) { + log.error("[config] 加载 haborSn-gcsMac 数据 {} 失败:" , MAPPING_LIST_MAP_FILE,e); + } + } + /** + * 保存 mappingListMap 到文件 + */ + public synchronized void saveMappingListMapToFile() { + File file = new File(MAPPING_LIST_MAP_FILE); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + String json = JSONUtils.obj2json(this.mappingListMap); + writer.write(json); + log.info("[config] 成功保存 haborSn-gcsMac 映射关系到文件 {}", MAPPING_LIST_MAP_FILE); + } catch (IOException e) { + log.error("[config] 保存 haborSn-gcsMac 数据 {} 失败:" , MAPPING_LIST_MAP_FILE,e); + } + } }