diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientConfigLoader.java b/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientConfigLoader.java index 8612eb9..bcb80cb 100644 --- a/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientConfigLoader.java +++ b/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientConfigLoader.java @@ -5,7 +5,6 @@ import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.odboy.config.model.msgtype.ClientInfo; import cn.odboy.config.netty.ConfigClient; -import cn.odboy.config.util.PropertyNameUtil; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -69,6 +68,9 @@ public class ClientConfigLoader { /** Mac路径分割符 */ private static final String DEFAULT_PATH_SEP_MAC = "/"; + /** 配置源名称 */ + public static final String PROPERTY_SOURCE_NAME = "kenaito-dynamic-config"; + /** 当前客户端配置 */ public static final ClientInfo clientInfo = new ClientInfo(); @@ -84,6 +86,9 @@ public class ClientConfigLoader { /** 转换后的配置信息:filename -> {configKey: configValue} */ public static Map> lastConfigs = new HashMap<>(); + /** 所有自定义配置项缓存 */ + public static Map cacheConfigs = new HashMap<>(); + /** 定时将配置写盘,缓存配置信息 */ private final Thread fixedTimeFlushConfigFileThread = ThreadUtil.newThread( @@ -201,13 +206,15 @@ public class ClientConfigLoader { } })); } + // 合并配置项 + cacheConfigs.clear(); Set>> filename2ConfigMap = lastConfigs.entrySet(); for (Map.Entry> filename2Config : filename2ConfigMap) { - MapPropertySource propertySource = - new MapPropertySource( - PropertyNameUtil.get(filename2Config.getKey()), filename2Config.getValue()); - environment.getPropertySources().addFirst(propertySource); + cacheConfigs.putAll(filename2Config.getValue()); } + MapPropertySource propertySource = + new MapPropertySource(PROPERTY_SOURCE_NAME, cacheConfigs); + environment.getPropertySources().addFirst(propertySource); } } }; diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientPropertyHelper.java b/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientPropertyHelper.java new file mode 100644 index 0000000..bd655a4 --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/context/ClientPropertyHelper.java @@ -0,0 +1,45 @@ +package cn.odboy.config.context; + +import cn.hutool.core.util.StrUtil; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.stereotype.Component; + +/** + * 客户端配置 辅助类 + * + * @author odboy + * @date 2024-12-07 + */ +@Component +@RequiredArgsConstructor +public class ClientPropertyHelper { + private final ConfigurableEnvironment environment; + private final ValueAnnotationProcessor valueAnnotationProcessor; + + /** + * 动态更新配置值 + * + * @param propertyName 属性路径名 + * @param value 属性值 + */ + public void updateValue(String propertyName, Object value) { + if (StrUtil.isNotBlank(propertyName)) { + // 设置属性值 + MutablePropertySources propertySources = environment.getPropertySources(); + if (propertySources.contains(ClientConfigLoader.PROPERTY_SOURCE_NAME)) { + // 更新属性值 + PropertySource propertySource = + propertySources.get(ClientConfigLoader.PROPERTY_SOURCE_NAME); + Map source = ((MapPropertySource) propertySource).getSource(); + source.put(propertyName, value); + } + // 单独更新@Value对应的值 + valueAnnotationProcessor.setValue(propertyName, value); + } + } +} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationBeanPostProcessor.java b/kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationProcessor.java similarity index 62% rename from kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationBeanPostProcessor.java rename to kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationProcessor.java index df06749..1764f16 100644 --- a/kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationBeanPostProcessor.java +++ b/kenaito-config-core/src/main/java/cn/odboy/config/context/ValueAnnotationProcessor.java @@ -11,39 +11,37 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; /** - * 加载并处理@Value对应的引用 + * 加载并处理@Value对应的引用, @ConfigurationProperties注解下的值会自动刷新所以不用管 * * @author odboy * @date 2024-12-07 */ @Component -public class ValueAnnotationBeanPostProcessor implements BeanPostProcessor { - private final Logger logger = LoggerFactory.getLogger(ValueAnnotationBeanPostProcessor.class); - private final Map nameFieldMap = new HashMap<>(); - private final Map nameBeanMap = new HashMap<>(); +public class ValueAnnotationProcessor implements BeanPostProcessor { + private final Logger logger = LoggerFactory.getLogger(ValueAnnotationProcessor.class); + private final Map valueFieldMap = new HashMap<>(); + private final Map valueBeanMap = new HashMap<>(); @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { Class clazz = bean.getClass(); while (clazz != null) { + // 处理@Value for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Value.class)) { field.setAccessible(true); // 对@Value的处理 Value annotation = field.getAnnotation(Value.class); String propertyName = annotation.value(); - String substring = + propertyName = propertyName.substring(propertyName.indexOf("${") + 2, propertyName.lastIndexOf("}")); // 处理带有默认值的配置 - propertyName = substring; - if (substring.contains(":")) { - String[] splits = substring.split(":"); - if (splits.length == 2) { - propertyName = splits[0]; - } + if (propertyName.contains(":")) { + int firstSpIndex = propertyName.indexOf(":"); + propertyName = propertyName.substring(0, firstSpIndex); } - nameFieldMap.put(propertyName, field); - nameBeanMap.put(propertyName, bean); + valueFieldMap.put(propertyName, field); + valueBeanMap.put(propertyName, bean); } } clazz = clazz.getSuperclass(); @@ -53,13 +51,13 @@ public class ValueAnnotationBeanPostProcessor implements BeanPostProcessor { public void setValue(String propertyName, Object value) { try { - Field field = nameFieldMap.getOrDefault(propertyName, null); + Field field = valueFieldMap.getOrDefault(propertyName, null); if (field != null) { field.setAccessible(true); - field.set(nameBeanMap.get(propertyName), value); + field.set(valueBeanMap.get(propertyName), value); } } catch (IllegalAccessException e) { - logger.error("配置 {} 字段值 {} 失败", propertyName, value, e); + logger.error("设置 {} 字段值 {} 失败", propertyName, value, e); } } } diff --git a/kenaito-config-demo/src/main/java/cn/odboy/rest/ConfigCenterProperties.java b/kenaito-config-demo/src/main/java/cn/odboy/rest/ConfigCenterProperties.java new file mode 100644 index 0000000..33f77d6 --- /dev/null +++ b/kenaito-config-demo/src/main/java/cn/odboy/rest/ConfigCenterProperties.java @@ -0,0 +1,24 @@ +package cn.odboy.rest; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 注册中心配置 + * + * @author odboy + * @date 2024-12-07 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "kenaito.config-center") +public class ConfigCenterProperties { + private String server; + private Integer port; + private String dataId; + private String env; + private String cacheDir; +} diff --git a/kenaito-config-demo/src/main/java/cn/odboy/rest/DemoController.java b/kenaito-config-demo/src/main/java/cn/odboy/rest/DemoController.java index 717f912..f1c904e 100644 --- a/kenaito-config-demo/src/main/java/cn/odboy/rest/DemoController.java +++ b/kenaito-config-demo/src/main/java/cn/odboy/rest/DemoController.java @@ -1,7 +1,7 @@ package cn.odboy.rest; -import cn.odboy.config.context.ValueAnnotationBeanPostProcessor; -import org.springframework.beans.factory.annotation.Autowired; +import cn.odboy.config.context.ClientPropertyHelper; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -16,19 +16,20 @@ import org.springframework.web.bind.annotation.RestController; */ @RestController @RequestMapping("/updateConfig") +@RequiredArgsConstructor public class DemoController { - @Value("${kenaito.config-center.demo:123}") - private String demoStr; + @Value("${kenaito.config-center.test}") + private String testStr; - @Autowired private ValueAnnotationBeanPostProcessor valueAnnotationBeanPostProcessor; + private final ClientPropertyHelper clientPropertyHelper; /** 配置变化了 */ @GetMapping("/test") public ResponseEntity test() { - System.err.println("demoStr=" + demoStr); - String propertyName = "kenaito.config-center.demo"; - valueAnnotationBeanPostProcessor.setValue(propertyName, "xxxxxxxxxx"); - System.err.println("demoStr=" + demoStr); + System.err.println("testStr=" + testStr); + String propertyName = "kenaito.config-center.test"; + clientPropertyHelper.updateValue(propertyName, "Hello World"); + System.err.println("testStr=" + testStr); return ResponseEntity.ok("success"); } } diff --git a/kenaito-config-demo/src/main/resources/config/application-daily.yml b/kenaito-config-demo/src/main/resources/config/application-daily.yml index b6492e4..4635e48 100644 --- a/kenaito-config-demo/src/main/resources/config/application-daily.yml +++ b/kenaito-config-demo/src/main/resources/config/application-daily.yml @@ -4,4 +4,4 @@ kenaito: port: 28011 data-id: kenaito-config-demo cache-dir: c:\\data - env: daily \ No newline at end of file + env: daily