From 8e770a5b9742088811a8da84141cad165b393729 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 2 Sep 2025 15:30:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor(integration):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增通用 ConfigManager 类,实现配置管理的通用功能 - 新增 DeviceConfigManager 和 ScenicConfigManager 类,分别实现设备和景区的配置管理- 更新相关控制器和服务,使用新的配置管理器类 -调整设备和景区的配置数据结构,以适应新的管理方式 --- .../controller/mobile/AppClaimController.java | 2 +- .../common/manager/ConfigManager.java | 241 ++++++++++++++++++ .../common/manager/DeviceConfigManager.java | 122 +++++++++ .../common/manager}/ScenicConfigManager.java | 19 +- .../service/impl/VoucherPrintServiceImpl.java | 2 +- .../basic/repository/DeviceRepository.java | 51 +++- .../basic/repository/ScenicRepository.java | 3 +- .../service/pc/impl/ScenicServiceImpl.java | 4 +- 8 files changed, 424 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/integration/common/manager/ConfigManager.java create mode 100644 src/main/java/com/ycwl/basic/integration/common/manager/DeviceConfigManager.java rename src/main/java/com/ycwl/basic/{util => integration/common/manager}/ScenicConfigManager.java (95%) diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppClaimController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppClaimController.java index f574a54..46947e0 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppClaimController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppClaimController.java @@ -11,7 +11,7 @@ import com.ycwl.basic.pricing.service.ICouponService; import com.ycwl.basic.pricing.service.VoucherPrintService; import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.ScenicRepository; -import com.ycwl.basic.util.ScenicConfigManager; +import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.utils.ApiResponse; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; diff --git a/src/main/java/com/ycwl/basic/integration/common/manager/ConfigManager.java b/src/main/java/com/ycwl/basic/integration/common/manager/ConfigManager.java new file mode 100644 index 0000000..9570d9d --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/common/manager/ConfigManager.java @@ -0,0 +1,241 @@ +package com.ycwl.basic.integration.common.manager; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * 通用配置管理器基类 + * 提供配置查找、类型转换等通用功能 + * + * @param 配置DTO类型 + */ +public abstract class ConfigManager { + + protected List configs; + + public ConfigManager(List configs) { + this.configs = configs != null ? configs : new ArrayList<>(); + } + + /** + * 获取配置项的键 + * 子类需要实现此方法来提取配置键 + */ + protected abstract String getConfigKey(T config); + + /** + * 获取配置项的值 + * 子类需要实现此方法来提取配置值 + */ + protected abstract Object getConfigValue(T config); + + /** + * 根据键查找配置项 + */ + protected T findConfigByKey(String key) { + if (key == null || configs == null) { + return null; + } + + return configs.stream() + .filter(config -> key.equals(getConfigKey(config))) + .findFirst() + .orElse(null); + } + + /** + * 获取字符串配置值 + */ + public String getString(String key) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + return value != null ? value.toString() : null; + } + + /** + * 获取字符串配置值,如果不存在则返回默认值 + */ + public String getString(String key, String defaultValue) { + String value = getString(key); + return value != null ? value : defaultValue; + } + + /** + * 获取整型配置值 + */ + public Integer getInteger(String key) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + if (value == null) return null; + if (value instanceof Integer) return (Integer) value; + if (value instanceof Number) return ((Number) value).intValue(); + if (value instanceof String) { + try { + return Integer.parseInt((String) value); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + /** + * 获取整型配置值,如果不存在则返回默认值 + */ + public Integer getInteger(String key, Integer defaultValue) { + Integer value = getInteger(key); + return value != null ? value : defaultValue; + } + + /** + * 获取布尔型配置值 + */ + public Boolean getBoolean(String key) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + if (value == null) return null; + if (value instanceof Boolean) return (Boolean) value; + if (value instanceof String) { + String str = ((String) value).toLowerCase().trim(); + return "true".equals(str) || "1".equals(str) || "yes".equals(str); + } + if (value instanceof Number) { + return ((Number) value).intValue() != 0; + } + return null; + } + + /** + * 获取布尔型配置值,如果不存在则返回默认值 + */ + public Boolean getBoolean(String key, Boolean defaultValue) { + Boolean value = getBoolean(key); + return value != null ? value : defaultValue; + } + + /** + * 获取浮点型配置值 + */ + public Float getFloat(String key) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + if (value == null) return null; + if (value instanceof Float) return (Float) value; + if (value instanceof Number) return ((Number) value).floatValue(); + if (value instanceof String) { + try { + return Float.parseFloat((String) value); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + /** + * 获取浮点型配置值,如果不存在则返回默认值 + */ + public Float getFloat(String key, Float defaultValue) { + Float value = getFloat(key); + return value != null ? value : defaultValue; + } + + /** + * 获取BigDecimal配置值 + */ + public BigDecimal getBigDecimal(String key) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + if (value == null) return null; + if (value instanceof BigDecimal) return (BigDecimal) value; + if (value instanceof Number) return new BigDecimal(value.toString()); + if (value instanceof String) { + try { + return new BigDecimal((String) value); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + /** + * 获取BigDecimal配置值,如果不存在则返回默认值 + */ + public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { + BigDecimal value = getBigDecimal(key); + return value != null ? value : defaultValue; + } + + /** + * 获取枚举配置值 + */ + public > E getEnum(String key, Class enumClass) { + T config = findConfigByKey(key); + if (config == null) { + return null; + } + Object value = getConfigValue(config); + return parseEnum(value, enumClass); + } + + /** + * 解析枚举值 + */ + private > E parseEnum(Object value, Class enumClass) { + if (value == null) return null; + try { + if (value instanceof String) { + return Enum.valueOf(enumClass, (String) value); + } + return Enum.valueOf(enumClass, value.toString()); + } catch (IllegalArgumentException e) { + return null; + } + } + + /** + * 获取枚举配置值,如果不存在则返回默认值 + */ + public > E getEnum(String key, Class enumClass, E defaultValue) { + E value = getEnum(key, enumClass); + return value != null ? value : defaultValue; + } + + /** + * 检查指定键的配置是否存在 + */ + public boolean hasConfig(String key) { + return findConfigByKey(key) != null; + } + + /** + * 获取所有配置项的数量 + */ + public int size() { + return configs.size(); + } + + /** + * 获取所有配置项 + */ + public List getAllConfigs() { + return new ArrayList<>(configs); + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/common/manager/DeviceConfigManager.java b/src/main/java/com/ycwl/basic/integration/common/manager/DeviceConfigManager.java new file mode 100644 index 0000000..cda3818 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/common/manager/DeviceConfigManager.java @@ -0,0 +1,122 @@ +package com.ycwl.basic.integration.common.manager; + +import com.ycwl.basic.integration.device.dto.config.DeviceConfigV2DTO; + +import java.util.List; + +/** + * 设备配置管理器 + * 基于通用ConfigManager实现设备配置的管理功能 + */ +public class DeviceConfigManager extends ConfigManager { + + public DeviceConfigManager(List configs) { + super(configs); + } + + @Override + protected String getConfigKey(DeviceConfigV2DTO config) { + return config != null ? config.getConfigKey() : null; + } + + @Override + protected Object getConfigValue(DeviceConfigV2DTO config) { + return config != null ? config.getConfigValue() : null; + } + + /** + * 获取设备配置类型 + */ + public String getConfigType(String key) { + DeviceConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getConfigType() : null; + } + + /** + * 获取设备配置描述 + */ + public String getConfigDescription(String key) { + DeviceConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getDescription() : null; + } + + /** + * 获取设备配置ID + */ + public Long getConfigId(String key) { + DeviceConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getId() : null; + } + + // 设备配置的常用快捷方法 + + /** + * 获取设备IP地址 + */ + public String getIpAddress() { + return getString("ip_address"); + } + + /** + * 获取设备分辨率 + */ + public String getResolution() { + return getString("resolution"); + } + + /** + * 获取设备帧率 + */ + public Integer getFramerate() { + return getInteger("framerate"); + } + + /** + * 获取设备协议 + */ + public String getProtocol() { + return getString("protocol"); + } + + /** + * 获取设备用户名 + */ + public String getUsername() { + return getString("username"); + } + + /** + * 获取设备密码 + */ + public String getPassword() { + return getString("password"); + } + + /** + * 获取设备亮度 + */ + public Integer getBrightness() { + return getInteger("brightness"); + } + + /** + * 获取设备对比度 + */ + public Integer getContrast() { + return getInteger("contrast"); + } + + /** + * 获取设备质量 + */ + public String getQuality() { + return getString("quality"); + } + + /** + * 检查设备是否启用录制 + */ + public Boolean isRecordingEnabled() { + return getBoolean("recording_enabled"); + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/util/ScenicConfigManager.java b/src/main/java/com/ycwl/basic/integration/common/manager/ScenicConfigManager.java similarity index 95% rename from src/main/java/com/ycwl/basic/util/ScenicConfigManager.java rename to src/main/java/com/ycwl/basic/integration/common/manager/ScenicConfigManager.java index 11892b6..7376c6b 100644 --- a/src/main/java/com/ycwl/basic/util/ScenicConfigManager.java +++ b/src/main/java/com/ycwl/basic/integration/common/manager/ScenicConfigManager.java @@ -1,4 +1,4 @@ -package com.ycwl.basic.util; +package com.ycwl.basic.integration.common.manager; import com.ycwl.basic.integration.common.util.ConfigValueUtil; import com.ycwl.basic.integration.scenic.dto.config.ScenicConfigV2DTO; @@ -9,11 +9,12 @@ import java.util.stream.Collectors; /** * 景区配置管理器 + * 基于通用ConfigManager实现景区配置的管理功能 * * 提供类型安全的配置值获取功能,支持多种数据类型的自动转换, * 当类型不兼容时返回null而不是抛出异常。 */ -public class ScenicConfigManager { +public class ScenicConfigManager extends ConfigManager { private final Map configMap; @@ -23,6 +24,7 @@ public class ScenicConfigManager { * @param configList 配置项列表 */ public ScenicConfigManager(List configList) { + super(configList); this.configMap = new HashMap<>(); if (configList != null) { for (ScenicConfigV2DTO config : configList) { @@ -39,8 +41,19 @@ public class ScenicConfigManager { * @param configMap 配置Map */ public ScenicConfigManager(Map configMap) { + super(null); // 使用Map构造时,父类configs为null this.configMap = configMap != null ? new HashMap<>(configMap) : new HashMap<>(); } + + @Override + protected String getConfigKey(ScenicConfigV2DTO config) { + return config != null ? config.getConfigKey() : null; + } + + @Override + protected Object getConfigValue(ScenicConfigV2DTO config) { + return config != null ? config.getConfigValue() : null; + } /** * 获取字符串值 @@ -325,7 +338,7 @@ public class ScenicConfigManager { * * @return 配置Map的拷贝 */ - public Map getAllConfigs() { + public Map getAllConfigsAsMap() { return new HashMap<>(configMap); } diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherPrintServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherPrintServiceImpl.java index 41b6dcf..4effcc6 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherPrintServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherPrintServiceImpl.java @@ -16,7 +16,7 @@ import com.ycwl.basic.pricing.service.VoucherPrintService; import com.ycwl.basic.printer.ticket.FeiETicketPrinter; import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.ScenicRepository; -import com.ycwl.basic.util.ScenicConfigManager; +import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.utils.WxMpUtil; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; diff --git a/src/main/java/com/ycwl/basic/repository/DeviceRepository.java b/src/main/java/com/ycwl/basic/repository/DeviceRepository.java index 46fe66f..a9d0a0e 100644 --- a/src/main/java/com/ycwl/basic/repository/DeviceRepository.java +++ b/src/main/java/com/ycwl/basic/repository/DeviceRepository.java @@ -1,5 +1,7 @@ package com.ycwl.basic.repository; +import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService; +import com.ycwl.basic.integration.device.dto.config.DeviceConfigV2DTO; import com.ycwl.basic.utils.JacksonUtil; import com.ycwl.basic.mapper.DeviceMapper; import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; @@ -7,6 +9,7 @@ import com.ycwl.basic.model.pc.device.entity.DeviceEntity; import com.ycwl.basic.utils.SnowFlakeUtil; import com.ycwl.basic.integration.device.service.DeviceIntegrationService; import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO; +import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @@ -31,6 +34,9 @@ public class DeviceRepository { public static final String DEVICE_ONLINE_CACHE_KEY = "device:online_status:%s"; public static final String DEVICE_CACHE_KEY = "device:%s"; public static final String DEVICE_CONFIG_CACHE_KEY = "device:%s:config"; + public static final String DEVICE_CONFIG_MANAGER_CACHE_KEY = "device:%s:config:manager"; + @Autowired + private DeviceConfigIntegrationService deviceConfigIntegrationService; /** * 将DeviceV2DTO转换为DeviceEntity @@ -71,18 +77,41 @@ public class DeviceRepository { } public DeviceConfigEntity getDeviceConfig(Long deviceId) { - if (redisTemplate.hasKey(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId))) { - return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId)), DeviceConfigEntity.class); + List configList = deviceConfigIntegrationService.getDeviceConfigs(deviceId); + if (configList != null && !configList.isEmpty()) { + return convertToDeviceConfigEntity(configList, deviceId); } - DeviceConfigEntity deviceConfig = deviceMapper.getConfigByDeviceId(deviceId); - if (null == deviceConfig) { - deviceConfig = new DeviceConfigEntity(); - deviceConfig.setId(SnowFlakeUtil.getLongId()); - deviceConfig.setDeviceId(deviceId); - deviceMapper.addConfig(deviceConfig); + return null; + } + + /** + * 获取设备配置管理器 + * + * @param deviceId 设备ID + * @return DeviceConfigManager实例,如果获取失败返回null + */ + public DeviceConfigManager getDeviceConfigManager(Long deviceId) { + try { + List configList = deviceConfigIntegrationService.getDeviceConfigs(deviceId); + return new DeviceConfigManager(configList); + } catch (Exception e) { + log.warn("获取设备配置管理器失败, deviceId: {}", deviceId, e); + return null; } - redisTemplate.opsForValue().set(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId), JacksonUtil.toJSONString(deviceConfig), 3, TimeUnit.DAYS); - return deviceConfig; + } + + /** + * 将DeviceConfigV2DTO列表转换为DeviceConfigEntity(为了兼容性) + */ + private DeviceConfigEntity convertToDeviceConfigEntity(List configList, Long deviceId) { + DeviceConfigEntity entity = new DeviceConfigEntity(); + entity.setId(SnowFlakeUtil.getLongId()); + entity.setDeviceId(deviceId); + + // 由于DeviceConfigEntity没有通用的configJson字段,这里只设置基本信息 + // 具体的配置项需要通过DeviceConfigManager来访问 + + return entity; } public boolean clearDeviceCache(String deviceNo) { @@ -106,9 +135,11 @@ public class DeviceRepository { DeviceEntity device = getDevice(deviceId); redisTemplate.delete(String.format(DEVICE_CACHE_KEY, device.getNo())); redisTemplate.delete(String.format(DEVICE_CONFIG_CACHE_KEY, device.getNo())); + redisTemplate.delete(String.format(DEVICE_CONFIG_MANAGER_CACHE_KEY, device.getNo())); } redisTemplate.delete(String.format(DEVICE_CACHE_KEY, deviceId)); redisTemplate.delete(String.format(DEVICE_CONFIG_CACHE_KEY, deviceId)); + redisTemplate.delete(String.format(DEVICE_CONFIG_MANAGER_CACHE_KEY, deviceId)); return true; } diff --git a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java index 4d88f41..5488f6e 100644 --- a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java +++ b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java @@ -19,13 +19,12 @@ import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.pay.enums.PayAdapterType; import com.ycwl.basic.storage.enums.StorageType; import com.ycwl.basic.utils.JacksonUtil; -import com.ycwl.basic.util.ScenicConfigManager; +import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.List; -import java.util.Map; @Component public class ScenicRepository { diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java index 232299e..ab3109a 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java @@ -3,7 +3,6 @@ package com.ycwl.basic.service.pc.impl; import com.ycwl.basic.facebody.FaceBodyFactory; import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; -import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.pay.PayFactory; import com.ycwl.basic.pay.adapter.IPayAdapter; @@ -12,10 +11,9 @@ import com.ycwl.basic.service.pc.ScenicService; import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.exceptions.StorageUnsupportedException; -import com.ycwl.basic.util.ScenicConfigManager; +import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.util.TtlCacheMap; import com.ycwl.basic.utils.ApiResponse; -import com.ycwl.basic.utils.JacksonUtil; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Autowired;