From d35a1facbdbdfea370e6150a2bb4950243cb540b Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 2 Sep 2025 11:22:52 +0800 Subject: [PATCH] =?UTF-8?q?refactor(device):=20=E9=87=8D=E6=9E=84=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 DeviceConfigIntegrationService 和 DeviceIntegrationService 添加 fallback 服务 - 为设备配置和信息获取方法添加缓存逻辑 - 移除冗余的设备配置设置方法 - 优化设备信息和配置的获取流程 --- .../example/DeviceIntegrationExample.java | 10 +- .../DeviceIntegrationFallbackExample.java | 112 ++++++++++++++ .../DeviceConfigIntegrationService.java | 143 +++--------------- .../DeviceIntegrationFallbackService.java | 128 ++++++++++++++++ .../service/DeviceIntegrationService.java | 59 ++++++-- 5 files changed, 306 insertions(+), 146 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationFallbackExample.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationFallbackService.java diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java index 84d2231..388c93d 100644 --- a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java +++ b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java @@ -100,12 +100,7 @@ public class DeviceIntegrationExample { log.info("=== 设备配置管理 ==="); Long deviceId = 1L; - - // 配置摄像头基本参数 - deviceConfigService.configureCameraParams( - deviceId, "192.168.1.100", "1920x1080", 30, "RTSP", "admin", "password123"); - log.info("摄像头基本参数已配置"); - + // 获取设备所有配置 List configs = deviceConfigService.getDeviceConfigs(deviceId); log.info("设备配置数量: {}", configs.size()); @@ -116,9 +111,6 @@ public class DeviceIntegrationExample { // 使用批量配置API BatchDeviceConfigRequest builderRequest = deviceConfigService.createBatchConfigBuilder() - .addVideoConfig("1920x1080", 30, "H264") - .addNetworkConfig("192.168.1.100", 554, "RTSP") - .addAuthConfig("admin", "password123") .build(); BatchUpdateResponse result = deviceConfigService.batchUpdateDeviceConfig(deviceId, builderRequest); diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationFallbackExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationFallbackExample.java new file mode 100644 index 0000000..df2b0c0 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationFallbackExample.java @@ -0,0 +1,112 @@ +package com.ycwl.basic.integration.device.example; + +import com.ycwl.basic.integration.device.service.DeviceIntegrationService; +import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService; +import com.ycwl.basic.integration.device.service.DeviceIntegrationFallbackService; +import com.ycwl.basic.integration.device.dto.device.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 设备集成降级机制示例 + * 演示失败降级策略的使用 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class DeviceIntegrationFallbackExample { + + private final DeviceIntegrationService deviceService; + private final DeviceConfigIntegrationService configService; + private final DeviceIntegrationFallbackService fallbackService; + + /** + * 演示设备信息获取的降级机制 + */ + public void deviceInfoFallbackExample() { + log.info("=== 设备信息获取降级示例 ==="); + + Long deviceId = 1001L; + String deviceNo = "CAM001"; + + try { + // 获取设备信息 - 自动降级 + DeviceV2DTO device = deviceService.getDevice(deviceId); + log.info("获取设备成功: {}", device.getName()); + + // 根据设备号获取设备 - 自动降级 + DeviceV2DTO deviceByNo = deviceService.getDeviceByNo(deviceNo); + log.info("根据设备号获取设备成功: {}", deviceByNo.getName()); + + // 获取设备配置 - 自动降级 + DeviceV2WithConfigDTO deviceWithConfig = deviceService.getDeviceWithConfig(deviceId); + log.info("获取设备配置成功,配置数量: {}", deviceWithConfig.getConfig().size()); + + } catch (Exception e) { + log.error("所有降级策略失败", e); + } + } + + /** + * 演示设备操作的降级机制 + */ + public void deviceOperationFallbackExample() { + log.info("=== 设备操作降级示例 ==="); + + Long deviceId = 1001L; + + try { + // 设备更新操作 - 自动降级 + UpdateDeviceRequest updateRequest = new UpdateDeviceRequest(); + updateRequest.setName("更新后的摄像头"); + deviceService.updateDevice(deviceId, updateRequest); + log.info("设备更新操作完成"); + + // 设备排序更新 - 自动降级 + deviceService.updateDeviceSort(deviceId, 5); + log.info("设备排序更新完成"); + + } catch (Exception e) { + log.error("设备操作降级失败", e); + } + } + + /** + * 演示降级缓存管理 + */ + public void fallbackCacheManagementExample() { + log.info("=== 降级缓存管理示例 ==="); + + String deviceCacheKey = "device:1001"; + String configCacheKey = "device:flat:config:1001"; + + // 检查降级缓存状态 + boolean hasDeviceCache = fallbackService.hasFallbackCache(deviceCacheKey); + boolean hasConfigCache = fallbackService.hasFallbackCache(configCacheKey); + + log.info("设备降级缓存存在: {}", hasDeviceCache); + log.info("配置降级缓存存在: {}", hasConfigCache); + + // 清理特定的降级缓存 + if (hasDeviceCache) { + fallbackService.clearFallbackCache(deviceCacheKey); + log.info("已清理设备降级缓存"); + } + } + + /** + * 运行所有降级示例 + */ + public void runAllFallbackExamples() { + log.info("开始运行设备集成降级示例..."); + + deviceInfoFallbackExample(); + deviceOperationFallbackExample(); + fallbackCacheManagementExample(); + + log.info("设备集成降级示例运行完成"); + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java index 4be322d..2b7b7cb 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java @@ -18,6 +18,7 @@ import java.util.Map; public class DeviceConfigIntegrationService { private final DeviceConfigV2Client deviceConfigV2Client; + private final DeviceIntegrationFallbackService fallbackService; public List getDeviceConfigs(Long deviceId) { log.info("获取设备配置列表, deviceId: {}", deviceId); @@ -39,14 +40,26 @@ public class DeviceConfigIntegrationService { public Map getDeviceFlatConfig(Long deviceId) { log.info("获取设备扁平化配置, deviceId: {}", deviceId); - CommonResponse> response = deviceConfigV2Client.getDeviceFlatConfig(deviceId); - return handleResponse(response, "获取设备扁平化配置失败"); + return fallbackService.executeWithFallback( + "device:flat:config:" + deviceId, + () -> { + CommonResponse> response = deviceConfigV2Client.getDeviceFlatConfig(deviceId); + return handleResponse(response, "获取设备扁平化配置失败"); + }, + Map.class + ); } public Map getDeviceFlatConfigByNo(String deviceNo) { log.info("根据设备编号获取扁平化配置, deviceNo: {}", deviceNo); - CommonResponse> response = deviceConfigV2Client.getDeviceFlatConfigByNo(deviceNo); - return handleResponse(response, "根据设备编号获取扁平化配置失败"); + return fallbackService.executeWithFallback( + "device:flat:config:no:" + deviceNo, + () -> { + CommonResponse> response = deviceConfigV2Client.getDeviceFlatConfigByNo(deviceNo); + return handleResponse(response, "根据设备编号获取扁平化配置失败"); + }, + Map.class + ); } public DeviceConfigV2DTO createDeviceConfig(Long deviceId, CreateDeviceConfigRequest request) { @@ -76,73 +89,6 @@ public class DeviceConfigIntegrationService { return handleResponse(response, "批量更新设备配置失败"); } - public void batchFlatUpdateDeviceConfig(Long deviceId, Map configs) { - log.info("扁平化批量更新设备配置, deviceId: {}, configs count: {}", deviceId, configs.size()); - CommonResponse response = deviceConfigV2Client.batchFlatUpdateDeviceConfig(deviceId, configs); - handleResponse(response, "扁平化批量更新设备配置失败"); - } - - /** - * 设置设备IP地址 - */ - public void setDeviceIpAddress(Long deviceId, String ipAddress) { - Map config = new HashMap<>(); - config.put("ip_address", ipAddress); - batchFlatUpdateDeviceConfig(deviceId, config); - } - - /** - * 设置设备分辨率 - */ - public void setDeviceResolution(Long deviceId, String resolution) { - Map config = new HashMap<>(); - config.put("resolution", resolution); - batchFlatUpdateDeviceConfig(deviceId, config); - } - - /** - * 设置设备帧率 - */ - public void setDeviceFramerate(Long deviceId, Integer framerate) { - Map config = new HashMap<>(); - config.put("framerate", framerate.toString()); - batchFlatUpdateDeviceConfig(deviceId, config); - } - - /** - * 设置设备协议 - */ - public void setDeviceProtocol(Long deviceId, String protocol) { - Map config = new HashMap<>(); - config.put("protocol", protocol); - batchFlatUpdateDeviceConfig(deviceId, config); - } - - /** - * 设置设备认证信息 - */ - public void setDeviceAuth(Long deviceId, String username, String password) { - Map config = new HashMap<>(); - config.put("username", username); - config.put("password", password); - batchFlatUpdateDeviceConfig(deviceId, config); - } - - /** - * 配置摄像头参数 - */ - public void configureCameraParams(Long deviceId, String ipAddress, String resolution, - Integer framerate, String protocol, String username, String password) { - Map configs = new HashMap<>(); - configs.put("ip_address", ipAddress); - configs.put("resolution", resolution); - configs.put("framerate", framerate.toString()); - configs.put("protocol", protocol); - if (username != null) configs.put("username", username); - if (password != null) configs.put("password", password); - batchFlatUpdateDeviceConfig(deviceId, configs); - } - /** * 获取设备特定配置值 */ @@ -151,20 +97,6 @@ public class DeviceConfigIntegrationService { return config != null ? config.getConfigValue() : null; } - /** - * 获取设备IP地址 - */ - public String getDeviceIpAddress(Long deviceId) { - return getDeviceConfigValue(deviceId, "ip_address"); - } - - /** - * 获取设备分辨率 - */ - public String getDeviceResolution(Long deviceId) { - return getDeviceConfigValue(deviceId, "resolution"); - } - /** * 创建批量配置请求构建器 */ @@ -206,46 +138,7 @@ public class DeviceConfigIntegrationService { request.getConfigs().add(item); return this; } - - /** - * 添加常用视频配置 - */ - public BatchDeviceConfigRequestBuilder addVideoConfig(String resolution, Integer framerate, String codec) { - addConfig("resolution", resolution); - addConfig("framerate", framerate.toString()); - if (codec != null) { - addConfig("codec", codec); - } - return this; - } - - /** - * 添加网络配置 - */ - public BatchDeviceConfigRequestBuilder addNetworkConfig(String ipAddress, Integer port, String protocol) { - addConfig("ip_address", ipAddress); - if (port != null) { - addConfig("port", port.toString()); - } - if (protocol != null) { - addConfig("protocol", protocol); - } - return this; - } - - /** - * 添加认证配置 - */ - public BatchDeviceConfigRequestBuilder addAuthConfig(String username, String password) { - if (username != null) { - addConfig("username", username); - } - if (password != null) { - addConfig("password", password); - } - return this; - } - + /** * 构建请求对象 */ diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationFallbackService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationFallbackService.java new file mode 100644 index 0000000..59ee0be --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationFallbackService.java @@ -0,0 +1,128 @@ +package com.ycwl.basic.integration.device.service; + +import com.ycwl.basic.integration.device.dto.device.*; +import com.ycwl.basic.utils.JacksonUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * 设备集成服务失败降级处理 + * 提供失败时的降级策略,不使用常规缓存 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class DeviceIntegrationFallbackService { + + private final RedisTemplate redisTemplate; + + // 降级缓存键前缀 + private static final String FALLBACK_CACHE_PREFIX = "device:fallback:"; + private static final long FALLBACK_CACHE_TTL = 7; // 7天 + + /** + * 执行操作,失败时降级到缓存结果 + * + * @param cacheKey 缓存键 + * @param operation 主要操作 + * @param resultClass 结果类型 + * @param 结果类型 + * @return 操作结果或缓存的结果 + */ + public T executeWithFallback(String cacheKey, Supplier operation, Class resultClass) { + try { + T result = operation.get(); + if (result != null) { + // 操作成功,保存结果用于将来的降级 + storeFallbackCache(cacheKey, result); + } + return result; + } catch (Exception e) { + log.warn("操作失败,尝试降级到缓存结果, cacheKey: {}", cacheKey, e); + return getFallbackFromCache(cacheKey, resultClass); + } + } + + /** + * 执行操作,失败时降级到缓存结果,无返回值版本 + * + * @param cacheKey 缓存键 + * @param operation 主要操作 + */ + public void executeWithFallback(String cacheKey, Runnable operation) { + try { + operation.run(); + // 操作成功,记录成功状态 + storeFallbackCache(cacheKey + ":success", "true"); + } catch (Exception e) { + log.warn("操作失败,检查是否有历史成功记录, cacheKey: {}", cacheKey, e); + String successRecord = getFallbackFromCache(cacheKey + ":success", String.class); + if (successRecord == null) { + log.error("操作失败且无历史成功记录, cacheKey: {}", cacheKey); + throw e; + } + log.info("操作失败但有历史成功记录,忽略此次失败, cacheKey: {}", cacheKey); + } + } + + /** + * 存储降级缓存 + */ + private void storeFallbackCache(String cacheKey, Object value) { + try { + String key = FALLBACK_CACHE_PREFIX + cacheKey; + String jsonValue = JacksonUtil.toJSONString(value); + redisTemplate.opsForValue().set(key, jsonValue, FALLBACK_CACHE_TTL, TimeUnit.DAYS); + log.debug("存储降级缓存成功, key: {}", key); + } catch (Exception e) { + log.warn("存储降级缓存失败, cacheKey: {}", cacheKey, e); + } + } + + /** + * 从降级缓存获取结果 + */ + private T getFallbackFromCache(String cacheKey, Class resultClass) { + try { + String key = FALLBACK_CACHE_PREFIX + cacheKey; + String cachedValue = redisTemplate.opsForValue().get(key); + if (cachedValue != null) { + log.info("从降级缓存获取结果, key: {}", key); + if (resultClass == String.class) { + return resultClass.cast(cachedValue); + } + return JacksonUtil.parseObject(cachedValue, resultClass); + } + } catch (Exception e) { + log.warn("从降级缓存获取结果失败, cacheKey: {}", cacheKey, e); + } + return null; + } + + /** + * 清除降级缓存 + * + * @param cacheKey 缓存键 + */ + public void clearFallbackCache(String cacheKey) { + String key = FALLBACK_CACHE_PREFIX + cacheKey; + redisTemplate.delete(key); + log.debug("清除降级缓存, key: {}", key); + } + + /** + * 检查是否有降级缓存 + * + * @param cacheKey 缓存键 + * @return 是否存在降级缓存 + */ + public boolean hasFallbackCache(String cacheKey) { + String key = FALLBACK_CACHE_PREFIX + cacheKey; + return Boolean.TRUE.equals(redisTemplate.hasKey(key)); + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java index bef9d9f..4e8dcda 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java @@ -14,29 +14,54 @@ import org.springframework.stereotype.Service; public class DeviceIntegrationService { private final DeviceV2Client deviceV2Client; + private final DeviceIntegrationFallbackService fallbackService; public DeviceV2DTO getDevice(Long deviceId) { log.info("获取设备信息, deviceId: {}", deviceId); - CommonResponse response = deviceV2Client.getDevice(deviceId); - return handleResponse(response, "获取设备信息失败"); + return fallbackService.executeWithFallback( + "device:" + deviceId, + () -> { + CommonResponse response = deviceV2Client.getDevice(deviceId); + return handleResponse(response, "获取设备信息失败"); + }, + DeviceV2DTO.class + ); } public DeviceV2DTO getDeviceByNo(String deviceNo) { log.info("根据设备编号获取设备信息, deviceNo: {}", deviceNo); - CommonResponse response = deviceV2Client.getDeviceByNo(deviceNo); - return handleResponse(response, "根据设备编号获取设备信息失败"); + return fallbackService.executeWithFallback( + "device:no:" + deviceNo, + () -> { + CommonResponse response = deviceV2Client.getDeviceByNo(deviceNo); + return handleResponse(response, "根据设备编号获取设备信息失败"); + }, + DeviceV2DTO.class + ); } public DeviceV2WithConfigDTO getDeviceWithConfig(Long deviceId) { log.info("获取设备配置信息, deviceId: {}", deviceId); - CommonResponse response = deviceV2Client.getDeviceWithConfig(deviceId); - return handleResponse(response, "获取设备配置信息失败"); + return fallbackService.executeWithFallback( + "device:config:" + deviceId, + () -> { + CommonResponse response = deviceV2Client.getDeviceWithConfig(deviceId); + return handleResponse(response, "获取设备配置信息失败"); + }, + DeviceV2WithConfigDTO.class + ); } public DeviceV2WithConfigDTO getDeviceWithConfigByNo(String deviceNo) { log.info("根据设备编号获取设备配置信息, deviceNo: {}", deviceNo); - CommonResponse response = deviceV2Client.getDeviceByNoWithConfig(deviceNo); - return handleResponse(response, "根据设备编号获取设备配置信息失败"); + return fallbackService.executeWithFallback( + "device:config:no:" + deviceNo, + () -> { + CommonResponse response = deviceV2Client.getDeviceByNoWithConfig(deviceNo); + return handleResponse(response, "根据设备编号获取设备配置信息失败"); + }, + DeviceV2WithConfigDTO.class + ); } public DeviceV2DTO createDevice(CreateDeviceRequest request) { @@ -47,14 +72,24 @@ public class DeviceIntegrationService { public void updateDevice(Long deviceId, UpdateDeviceRequest request) { log.info("更新设备信息, deviceId: {}", deviceId); - CommonResponse response = deviceV2Client.updateDevice(deviceId, request); - handleResponse(response, "更新设备信息失败"); + fallbackService.executeWithFallback( + "device:update:" + deviceId, + () -> { + CommonResponse response = deviceV2Client.updateDevice(deviceId, request); + handleResponse(response, "更新设备信息失败"); + } + ); } public void deleteDevice(Long deviceId) { log.info("删除设备, deviceId: {}", deviceId); - CommonResponse response = deviceV2Client.deleteDevice(deviceId); - handleResponse(response, "删除设备失败"); + fallbackService.executeWithFallback( + "device:delete:" + deviceId, + () -> { + CommonResponse response = deviceV2Client.deleteDevice(deviceId); + handleResponse(response, "删除设备失败"); + } + ); } public DeviceV2ListResponse listDevices(Integer page, Integer pageSize, String name, String no,