From a5903a9831eafcd75af560223334e619ad89f510 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 16 Dec 2025 10:00:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(integration):=20=E6=94=AF=E6=8C=81TypeRefe?= =?UTF-8?q?rence=E6=B3=9B=E5=9E=8B=E7=9A=84=E9=99=8D=E7=BA=A7=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在IntegrationFallbackService中新增支持TypeReference的executeWithFallback方法 - 新增getFallbackFromCache和parseFallbackCacheValue方法处理泛型缓存 - 更新DeviceStatusIntegrationService使用TypeReference保留泛型信息 - 更新RenderWorkerConfigIntegrationService使用TypeReference并修正缓存键 - 更新ScenicConfigIntegrationService使用TypeReference保留泛型信息 - 添加必要的Jackson TypeReference导入依赖 --- .../service/IntegrationFallbackService.java | 86 ++++++++++++++++++- .../DeviceStatusIntegrationService.java | 6 +- .../RenderWorkerConfigIntegrationService.java | 11 +-- .../ScenicConfigIntegrationService.java | 6 +- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ycwl/basic/integration/common/service/IntegrationFallbackService.java b/src/main/java/com/ycwl/basic/integration/common/service/IntegrationFallbackService.java index d5b51520..dc295762 100644 --- a/src/main/java/com/ycwl/basic/integration/common/service/IntegrationFallbackService.java +++ b/src/main/java/com/ycwl/basic/integration/common/service/IntegrationFallbackService.java @@ -1,5 +1,6 @@ package com.ycwl.basic.integration.common.service; +import com.fasterxml.jackson.core.type.TypeReference; import com.ycwl.basic.integration.common.config.IntegrationProperties; import com.ycwl.basic.utils.JacksonUtil; import lombok.RequiredArgsConstructor; @@ -30,7 +31,7 @@ public class IntegrationFallbackService { /** * 执行操作,失败时降级到缓存结果 - * + * * @param serviceName 服务名称 (如: zt-device, zt-scenic) * @param cacheKey 缓存键 * @param operation 主要操作 @@ -78,6 +79,57 @@ public class IntegrationFallbackService { return fallbackResult; } } + + /** + * 执行操作,失败时降级到缓存结果(支持TypeReference泛型) + * + * @param serviceName 服务名称 (如: zt-device, zt-scenic) + * @param cacheKey 缓存键 + * @param operation 主要操作 + * @param typeReference 类型引用,用于保留泛型信息 + * @param 结果类型 + * @return 操作结果或缓存的结果 + */ + public T executeWithFallback(String serviceName, String cacheKey, Supplier operation, TypeReference typeReference) { + String fullKey = buildFullCacheKey(serviceName, cacheKey); + String cachedValue = null; + boolean isPreferredCache = false; + try { + cachedValue = redisTemplate.opsForValue().get(fullKey); + isPreferredCache = cachedValue != null && isFallbackCachePreferred(serviceName, fullKey); + } catch (Exception e) { + log.warn("[{}] 读取降级缓存失败,将继续尝试远端获取, cacheKey: {}", serviceName, cacheKey, e); + } + + if (isPreferredCache) { + T preferredCacheResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, typeReference); + if (preferredCacheResult != null) { + log.debug("[{}] 命中优先缓存(<=1分钟),直接返回, cacheKey: {}", serviceName, cacheKey); + return preferredCacheResult; + } + } + + try { + T result = operation.get(); + if (result != null) { + // 操作成功,保存结果用于将来的降级 + storeFallbackCache(serviceName, cacheKey, result); + } + return result; + } catch (Exception e) { + log.warn("[{}] 操作失败,尝试降级到缓存结果, cacheKey: {}", serviceName, cacheKey, e); + T fallbackResult = parseFallbackCacheValue(serviceName, cacheKey, cachedValue, typeReference); + if (fallbackResult == null) { + fallbackResult = getFallbackFromCache(serviceName, cacheKey, typeReference); + } + if (fallbackResult == null) { + log.error("[{}] 操作失败且无缓存数据, cacheKey: {}", serviceName, cacheKey); + throw e; + } + log.info("[{}] 成功从降级缓存获取结果, cacheKey: {}", serviceName, cacheKey); + return fallbackResult; + } + } /** * 执行操作,失败时降级到缓存结果,无返回值版本 @@ -138,6 +190,23 @@ public class IntegrationFallbackService { return null; } + /** + * 从降级缓存获取结果(支持TypeReference泛型) + */ + private T getFallbackFromCache(String serviceName, String cacheKey, TypeReference typeReference) { + try { + String fullKey = buildFullCacheKey(serviceName, cacheKey); + String cachedValue = redisTemplate.opsForValue().get(fullKey); + if (cachedValue != null) { + log.debug("[{}] 从降级缓存获取结果, key: {}", serviceName, fullKey); + return JacksonUtil.parseObject(cachedValue, typeReference); + } + } catch (Exception e) { + log.warn("[{}] 从降级缓存获取结果失败, cacheKey: {}", serviceName, cacheKey, e); + } + return null; + } + /** * 判断当前降级缓存是否应该优先使用。 * 规则:缓存写入后的 1 分钟内优先使用,超过 1 分钟则优先尝试远端;远端失败再降级到缓存。 @@ -177,6 +246,21 @@ public class IntegrationFallbackService { return null; } } + + /** + * 解析降级缓存值(支持TypeReference泛型) + */ + private T parseFallbackCacheValue(String serviceName, String cacheKey, String cachedValue, TypeReference typeReference) { + if (cachedValue == null) { + return null; + } + try { + return JacksonUtil.parseObject(cachedValue, typeReference); + } catch (Exception e) { + log.warn("[{}] 解析降级缓存失败, cacheKey: {}", serviceName, cacheKey, e); + return null; + } + } /** * 清除降级缓存 diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceStatusIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceStatusIntegrationService.java index 579c883d..48cc1aac 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DeviceStatusIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceStatusIntegrationService.java @@ -1,5 +1,6 @@ package com.ycwl.basic.integration.device.service; +import com.fasterxml.jackson.core.type.TypeReference; import com.ycwl.basic.integration.common.exception.IntegrationException; import com.ycwl.basic.integration.common.response.CommonResponse; import com.ycwl.basic.integration.common.service.IntegrationFallbackService; @@ -49,6 +50,9 @@ public class DeviceStatusIntegrationService { ); } + /** + * 获取所有在线设备(带降级,使用TypeReference保留泛型信息) + */ public List getAllOnlineDevices() { log.debug("获取所有在线设备"); return fallbackService.executeWithFallback( @@ -58,7 +62,7 @@ public class DeviceStatusIntegrationService { CommonResponse> response = deviceStatusClient.getAllOnlineDevices(); return handleResponse(response, "获取所有在线设备失败"); }, - List.class + new TypeReference>() {} ); } diff --git a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java index dea19704..4e9a55c6 100644 --- a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java @@ -1,5 +1,6 @@ package com.ycwl.basic.integration.render.service; +import com.fasterxml.jackson.core.type.TypeReference; import com.ycwl.basic.integration.common.exception.IntegrationException; import com.ycwl.basic.integration.common.response.CommonResponse; import com.ycwl.basic.integration.common.service.IntegrationFallbackService; @@ -29,7 +30,7 @@ public class RenderWorkerConfigIntegrationService { private static final String SERVICE_NAME = "zt-render-worker"; /** - * 获取工作器所有配置(带降级) + * 获取工作器所有配置(带降级,使用TypeReference保留泛型信息) */ public List getWorkerConfigs(Long workerId) { log.debug("获取渲染工作器配置列表, workerId: {}", workerId); @@ -37,12 +38,12 @@ public class RenderWorkerConfigIntegrationService { SERVICE_NAME, "worker:configs:" + workerId, () -> { - CommonResponse> response = + CommonResponse> response = renderWorkerConfigV2Client.getWorkerConfigs(workerId); List configs = handleResponse(response, "获取渲染工作器配置列表失败"); return configs != null ? configs : Collections.emptyList(); }, - List.class + new TypeReference>() {} ); } @@ -70,12 +71,12 @@ public class RenderWorkerConfigIntegrationService { log.debug("获取渲染工作器平铺配置, workerId: {}", workerId); return fallbackService.executeWithFallback( SERVICE_NAME, - "worker:config:" + workerId, + "worker:flat:config:" + workerId, () -> { List configs = getWorkerConfigsInternal(workerId); return flattenConfigs(configs); }, - Map.class + new TypeReference>() {} ); } diff --git a/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicConfigIntegrationService.java index b40b3649..9ff90e9c 100644 --- a/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicConfigIntegrationService.java @@ -1,5 +1,6 @@ package com.ycwl.basic.integration.scenic.service; +import com.fasterxml.jackson.core.type.TypeReference; import com.ycwl.basic.integration.common.exception.IntegrationException; import com.ycwl.basic.integration.common.response.CommonResponse; import com.ycwl.basic.integration.common.service.IntegrationFallbackService; @@ -22,6 +23,9 @@ public class ScenicConfigIntegrationService { private static final String SERVICE_NAME = "zt-scenic"; + /** + * 获取景区配置列表(带降级,使用TypeReference保留泛型信息) + */ public List listConfigs(Long scenicId) { log.debug("获取景区配置列表, scenicId: {}", scenicId); return fallbackService.executeWithFallback( @@ -31,7 +35,7 @@ public class ScenicConfigIntegrationService { CommonResponse> response = scenicConfigV2Client.listConfigs(scenicId); return handleResponse(response, "获取景区配置列表失败"); }, - List.class + new TypeReference>() {} ); }