From b1ed7fcd8b117081c84566b900da8d182cd60a20 Mon Sep 17 00:00:00 2001 From: lilai Date: Thu, 18 Aug 2022 20:00:27 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90feature=E3=80=91=E4=BC=98=E5=8C=96prop?= =?UTF-8?q?erties=E5=92=8Cyaml=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=A0=BC=E5=BC=8F=E6=94=AF=E6=8C=81=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1)通过在属性appName上添加@ConfigFieldKey("app-name")注解,可以在properties或yaml用中划线替换驼峰形式的键值(兼容驼峰形式)。 (2)xxx.xxx.appName将会直接以xxx.xxx.appName和解析为xxx.xxx.app.Name再通过KeyFormatter读取环境变量 (3)xxx.xxx.app-name将会被解析为xxx.xxx.app.Name再通过KeyFormatter读取环境变量 --- .../config/strategy/LoadYamlStrategy.java | 14 +- .../core/config/utils/ConfigValueUtil.java | 121 +++++++++++++++++- .../example/demo/config/DemoConfig.java | 4 + 3 files changed, 133 insertions(+), 6 deletions(-) diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/strategy/LoadYamlStrategy.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/strategy/LoadYamlStrategy.java index f41df38f2e..bc382f2965 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/strategy/LoadYamlStrategy.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/strategy/LoadYamlStrategy.java @@ -126,9 +126,13 @@ private Map fixEntry(Map typeMap, Class cls) { Map fixedTypeMap = fixEntry(typeMap, cls.getSuperclass()); for (Field field : cls.getDeclaredFields()) { final ConfigFieldKey configFieldKey = field.getAnnotation(ConfigFieldKey.class); - final String fieldKey = configFieldKey == null ? field.getName() : configFieldKey.value(); - final Object subTypeVal = - configFieldKey == null ? fixedTypeMap.get(fieldKey) : fixedTypeMap.remove(fieldKey); + final String fieldKey = field.getName(); + final Object subTypeVal; + if (configFieldKey != null && fixedTypeMap.get(configFieldKey.value()) != null) { + subTypeVal = fixedTypeMap.remove(configFieldKey.value()); + } else { + subTypeVal = fixedTypeMap.get(fieldKey); + } if (subTypeVal == null) { continue; } @@ -136,11 +140,11 @@ private Map fixEntry(Map typeMap, Class cls) { if (subTypeVal instanceof Map) { fixedVal = fixEntry((Map) subTypeVal, field.getType()); if (configFieldKey != null) { - fixedTypeMap.put(field.getName(), fixedVal); + fixedTypeMap.put(fieldKey, fixedVal); } } else { fixedVal = fixValStr(formatConfigKey(fieldKey, cls), fixedTypeMap, subTypeVal); - fixedTypeMap.put(field.getName(), fixedVal); + fixedTypeMap.put(fieldKey, fixedVal); } } return fixedTypeMap; diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/utils/ConfigValueUtil.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/utils/ConfigValueUtil.java index 0ee9801dc6..9b3de87ba3 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/utils/ConfigValueUtil.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/config/utils/ConfigValueUtil.java @@ -30,9 +30,12 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 对配置中参数值进行处理的工具 @@ -62,6 +65,11 @@ public class ConfigValueUtil { */ private static final int MAP_KV_LEN = 2; + /** + * 驼峰匹配pattern + */ + private static final Pattern PATTERN = Pattern.compile("[A-Z]"); + /** * 配置键格式化器, 针对不同环境变量格式读取 *

若读取环境变量 service.meta.applicationName, 则会尝试从下面的变量进行读取, 否则取默认值

@@ -87,6 +95,20 @@ public class ConfigValueUtil { key -> key.toLowerCase(Locale.ROOT).replace('.', '-'), }; + /** + * 配置参考值获取表达式 + *

优先级: 启动配置 > 环境变量 > 启动参数 > 配置文件

+ */ + private static final List, String>> + VALUE_REFER_FUNCTION = Arrays.asList( + (key, argsMap) -> { + final Object config = argsMap.get(key); + return config == null ? null : config.toString(); + }, + (key, argsMap) -> System.getenv(key), + (key, argsMap) -> System.getProperty(key) + ); + /** * 值获取表达式 *

优先级: 启动配置 > 环境变量 > 启动参数 > 配置文件

@@ -296,7 +318,7 @@ public static String fixValue(String configKey, String configVal, Map 环境变量 > 系统变量 > 配置 + *

修正不同配置格式获取值, 含'-','_','.',大写以及小写

+ * + * @param key 键 + * @param configVal 配置值 + * @return 最终配置参考值 + */ + private static String getValByFixedKey(String key, String configVal, Map argsMap) { + // 1. xxx.xxx.appName直接获取 2. xxx.xxx.app-name处理为xxx.xxx.app.name再获取 + String keyReplaceMiddleLine = transFromMiddleLine(key); + Optional fixedValue = getValueByOrder(argsMap, keyReplaceMiddleLine); + if (fixedValue.isPresent()) { + return fixedValue.get(); + } + + // 3. xxx.xxx.appName分割为xxx.xxx.app.name + String keyWithoutCamel = transFromCamel(keyReplaceMiddleLine); + if (!keyReplaceMiddleLine.equals(keyWithoutCamel)) { + fixedValue = getValueByOrder(argsMap, keyWithoutCamel); + if (fixedValue.isPresent()) { + return fixedValue.get(); + } + } + return configVal; + } + + /** + * 由KeyFormatter处理后读取环境变量 + * 优先级:入参 > 环境变量 > 系统变量 > 配置 + * + * @param key 键 + * @param argsMap 入参 + * @return 最终配置参考值 + */ + private static Optional getValueByOrder(Map argsMap, String key) { + Optional fixedValue; + for (ValueReferFunction, String> function : VALUE_REFER_FUNCTION) { + for (KeyFormatter keyFormatter : KEY_FORMATTERS) { + fixedValue = Optional.ofNullable(function.apply(keyFormatter.format(key), argsMap)); + if (fixedValue.isPresent()) { + return fixedValue; + } + } + } + return Optional.empty(); + } + + /** + * 配置键分割驼峰单词 + *

若需读取环境变量,service.meta.applicationName先处理为service.meta.application.name再 + * 由KeyFormatter处理后读取环境变量

+ * + * @param key 需处理的键 + * @return 处理后的键 + */ + private static String transFromCamel(String key) { + Matcher matcher = PATTERN.matcher(key); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + matcher.appendReplacement(sb, "." + matcher.group(0).toLowerCase(Locale.ROOT)); + } + matcher.appendTail(sb); + return sb.toString(); + } + + /** + * 配置键中划线格式化 + *

若需读取环境变量 service.meta.application-name, 则先处理为service.meta.application.name再 + * 由KeyFormatter处理后读取环境变量

+ * + * @param key 需处理的键 + * @return 处理后的键 + */ + private static String transFromMiddleLine(String key) { + return key.replace("-", "."); + } + /** * 通过环境变量或者系统变量获取 环境变量 > 系统变量 * @@ -361,6 +461,25 @@ interface ValueFixFunction { R apply(K key, B bootstrapArgsMap, P sourceProvider); } + /** + * 配置值参考, 该类仅用于配置值参考 + * + * @param 键 + * @param 源数据 + * @param 结果 + * @since 2022-08-18 + */ + interface ValueReferFunction { + /** + * 应用修正 + * + * @param key 键 + * @param bootstrapArgsMap 启动参数Map + * @return 最终参考值 + */ + R apply(K key, B bootstrapArgsMap); + } + /** * 配置键格式化器 * diff --git a/sermant-example/demo-plugin/src/main/java/com/huawei/example/demo/config/DemoConfig.java b/sermant-example/demo-plugin/src/main/java/com/huawei/example/demo/config/DemoConfig.java index bc48a9c588..6b18ab3ad7 100644 --- a/sermant-example/demo-plugin/src/main/java/com/huawei/example/demo/config/DemoConfig.java +++ b/sermant-example/demo-plugin/src/main/java/com/huawei/example/demo/config/DemoConfig.java @@ -36,7 +36,11 @@ public class DemoConfig implements PluginConfig { // 有设置拦截器别名需 /** * 基础类型配置(除byte和char) + * + *

添加@ConfigFieldKey("int-field")后,config.yaml中配置demo.test.intField或demo.test.int-field皆可

+ *

如果不添加注解,config.yaml中只能配置为demo.test.intField

*/ + @ConfigFieldKey("int-field") private int intField; /**