Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【feature】优化properties和config.yaml配置文件驼峰和中划线支持以及相应环境变量读取 #658

Merged
merged 1 commit into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,25 @@ 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;
}
final Object fixedVal;
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
* 对配置中参数值进行处理的工具
Expand Down Expand Up @@ -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]");

/**
* 配置键格式化器, 针对不同环境变量格式读取
* <p>若读取环境变量 service.meta.applicationName, 则会尝试从下面的变量进行读取, 否则取默认值</p>
Expand All @@ -87,6 +95,20 @@ public class ConfigValueUtil {
key -> key.toLowerCase(Locale.ROOT).replace('.', '-'),
};

/**
* 配置参考值获取表达式
* <p>优先级: 启动配置 > 环境变量 > 启动参数 > 配置文件</p>
*/
private static final List<ValueReferFunction<String, Map<String, Object>, 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)
);

/**
* 值获取表达式
* <p>优先级: 启动配置 > 环境变量 > 启动参数 > 配置文件</p>
Expand Down Expand Up @@ -296,7 +318,7 @@ public static String fixValue(String configKey, String configVal, Map<String, Ob
configVal.substring(0, startIndex - ENV_PREFIX_LEN) + value + configVal.substring(endIndex + 1),
argsMap, provider);
} else {
final String valFromEnv = getFormatKeyFixVal(configKey, configVal, argsMap, provider);
final String valFromEnv = getValByFixedKey(configKey, configVal, argsMap);
justforstudy-A marked this conversation as resolved.
Show resolved Hide resolved
if (valFromEnv != null) {
return valFromEnv;
}
Expand Down Expand Up @@ -326,6 +348,84 @@ private static String getFormatKeyFixVal(String key, String defaultVal, Map<Stri
return defaultVal;
}

/**
* 获取配置键的参考值,优先级:入参 > 环境变量 > 系统变量 > 配置
* <p>修正不同配置格式获取值, 含'-','_','.',大写以及小写</p>
*
* @param key 键
* @param configVal 配置值
* @return 最终配置参考值
*/
private static String getValByFixedKey(String key, String configVal, Map<String, Object> argsMap) {
// 1. xxx.xxx.appName直接获取 2. xxx.xxx.app-name处理为xxx.xxx.app.name再获取
String keyReplaceMiddleLine = transFromMiddleLine(key);
Optional<String> 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<String> getValueByOrder(Map<String, Object> argsMap, String key) {
Optional<String> fixedValue;
for (ValueReferFunction<String, Map<String, Object>, 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();
}

/**
* 配置键分割驼峰单词
* <p>若需读取环境变量,service.meta.applicationName先处理为service.meta.application.name再
* 由KeyFormatter处理后读取环境变量</p>
*
* @param key 需处理的键
* @return 处理后的键
*/
private static String transFromCamel(String key) {
Matcher matcher = PATTERN.matcher(key);
StringBuffer sb = new StringBuffer();
justforstudy-A marked this conversation as resolved.
Show resolved Hide resolved
while (matcher.find()) {
matcher.appendReplacement(sb, "." + matcher.group(0).toLowerCase(Locale.ROOT));
}
matcher.appendTail(sb);
return sb.toString();
}

/**
* 配置键中划线格式化
* <p>若需读取环境变量 service.meta.application-name, 则先处理为service.meta.application.name再
* 由KeyFormatter处理后读取环境变量</p>
*
* @param key 需处理的键
* @return 处理后的键
*/
private static String transFromMiddleLine(String key) {
return key.replace("-", ".");
}

/**
* 通过环境变量或者系统变量获取 环境变量 > 系统变量
*
Expand Down Expand Up @@ -361,6 +461,25 @@ interface ValueFixFunction<K, B, P, R> {
R apply(K key, B bootstrapArgsMap, P sourceProvider);
}

/**
* 配置值参考, 该类仅用于配置值参考
*
* @param <K> 键
* @param <B> 源数据
* @param <R> 结果
* @since 2022-08-18
*/
interface ValueReferFunction<K, B, R> {
/**
* 应用修正
*
* @param key 键
* @param bootstrapArgsMap 启动参数Map
* @return 最终参考值
*/
R apply(K key, B bootstrapArgsMap);
}

/**
* 配置键格式化器
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ public class DemoConfig implements PluginConfig { // 有设置拦截器别名需

/**
* 基础类型配置(除byte和char)
*
* <p>添加@ConfigFieldKey("int-field")后,config.yaml中配置demo.test.intField或demo.test.int-field皆可</p>
* <p>如果不添加注解,config.yaml中只能配置为demo.test.intField</p>
*/
@ConfigFieldKey("int-field")
private int intField;

/**
Expand Down