diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/ConfigurationPropertiesUtils.java b/commons/common-util/src/main/java/com/schbrain/common/util/ConfigurationPropertiesUtils.java index 3d6ae2ecf1a332831d97625e3fc98c032abf5974..13b9f8e87d3fa919aca0938655acff24c12469c7 100644 --- a/commons/common-util/src/main/java/com/schbrain/common/util/ConfigurationPropertiesUtils.java +++ b/commons/common-util/src/main/java/com/schbrain/common/util/ConfigurationPropertiesUtils.java @@ -1,9 +1,11 @@ package com.schbrain.common.util; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; import com.google.common.base.CaseFormat; import com.google.common.base.Converter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.core.annotation.MergedAnnotation; import java.util.Collections; @@ -22,11 +24,11 @@ public class ConfigurationPropertiesUtils { return toMap(source, true); } - public static Map toMap(Object source, boolean ignoreNull) { + public static Map toMap(Object source, boolean ignoreNullValue) { return toMap(source, true, DEFAULT_CONVERTER); } - public static Map toMap(Object source, boolean ignoreNull, Converter converter) { + public static Map toMap(Object source, boolean ignoreNullValue, Converter converter) { if (source == null) { return Collections.emptyMap(); } @@ -35,15 +37,24 @@ public class ConfigurationPropertiesUtils { if (sourceClass.isAnnotationPresent(ConfigurationProperties.class)) { String prefix = getPrefix(sourceClass); Map sourceMap = new LinkedHashMap<>(); - return BeanUtil.beanToMap(source, sourceMap, ignoreNull, key -> prefix + "." + converter.convert(key)); + CopyOptions copyOptions = CopyOptions.create() + .setIgnoreNullValue(ignoreNullValue) + .setPropertiesFilter((field, value) -> !field.isAnnotationPresent(NestedConfigurationProperty.class)) + .setFieldNameEditor(key -> prefix + "." + converter.convert(key)); + return BeanUtil.beanToMap(source, sourceMap, copyOptions); } return BeanUtil.beanToMap(source); } public static String getPrefix(Class sourceClass) { - ConfigurationProperties configurationProperties = sourceClass.getAnnotation(ConfigurationProperties.class); - MergedAnnotation mergedAnnotation = MergedAnnotation.from(configurationProperties); + ConfigurationProperties annotation = sourceClass.getAnnotation(ConfigurationProperties.class); + if (annotation == null) { + String className = ConfigurationProperties.class.getName(); + String errorDetail = sourceClass.getSimpleName() + " must annotated @" + className + " or overwrite getPropertiesPrefix method"; + throw new IllegalStateException(errorDetail); + } + MergedAnnotation mergedAnnotation = MergedAnnotation.from(annotation); return mergedAnnotation.getString(MergedAnnotation.VALUE); } -} \ No newline at end of file +} diff --git a/commons/common-util/src/main/java/com/schbrain/common/util/support/ConfigurableProperties.java b/commons/common-util/src/main/java/com/schbrain/common/util/support/ConfigurableProperties.java index ea04596dd31fb7b8ec0384ae3cf336d6e06e97e2..187126db8fdb1b12bd0960ca41207c275c8e2494 100644 --- a/commons/common-util/src/main/java/com/schbrain/common/util/support/ConfigurableProperties.java +++ b/commons/common-util/src/main/java/com/schbrain/common/util/support/ConfigurableProperties.java @@ -1,7 +1,6 @@ package com.schbrain.common.util.support; import com.schbrain.common.util.ConfigurationPropertiesUtils; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.core.Ordered; @@ -33,14 +32,8 @@ public interface ConfigurableProperties extends Ordered { /** * the prefix of properties */ - private String getPropertiesPrefix() { - ConfigurationProperties annotation = getClass().getAnnotation(ConfigurationProperties.class); - if (annotation == null) { - String className = ConfigurationProperties.class.getName(); - String errorDetail = getClass().getSimpleName() + " must annotated @" + className + " or overwrite getPrefix method"; - throw new IllegalStateException(errorDetail); - } + default String getPropertiesPrefix() { return ConfigurationPropertiesUtils.getPrefix(getClass()); } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/properties/WebProperties.java b/commons/web-common/src/main/java/com/schbrain/common/web/properties/WebProperties.java index f73c522c72dcb13e14b7fc5e7bfcd2c8faf68046..48892bb5bb5d60193340ff29fd51038b339b2510 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/properties/WebProperties.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/properties/WebProperties.java @@ -44,4 +44,4 @@ public class WebProperties implements ConfigurableProperties { return "web-common"; } -} \ No newline at end of file +} diff --git a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/ConfigurablePropertiesLoader.java b/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/ConfigurablePropertiesLoader.java index 763df45356465b9a589a1519419aea022f8cb97f..dd33988da15c244e4fda624e49a0861ee14d555e 100644 --- a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/ConfigurablePropertiesLoader.java +++ b/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/ConfigurablePropertiesLoader.java @@ -2,13 +2,15 @@ package com.schbrain.framework.autoconfigure.apollo; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; +import com.google.common.collect.Maps; +import com.schbrain.common.util.ConfigurationPropertiesUtils; import com.schbrain.common.util.support.ConfigurableProperties; import com.schbrain.framework.autoconfigure.apollo.config.OrderedMapPropertySource; import com.schbrain.framework.autoconfigure.apollo.event.ConfigLoadedEvent; import com.schbrain.framework.autoconfigure.apollo.event.listener.ConfigLoadedEventListener; import com.schbrain.framework.autoconfigure.apollo.properties.ApolloProperties; -import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.logging.Log; import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.SpringApplication; @@ -18,10 +20,11 @@ import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.core.ResolvableType; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import org.springframework.util.ClassUtils; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.Map.Entry; import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactories; @@ -47,7 +50,7 @@ class ConfigurablePropertiesLoader { void load(ConfigurableEnvironment environment, SpringApplication application) { List propertiesList = loadFactories(ConfigurableProperties.class, getClass().getClassLoader()); if (CollectionUtils.isEmpty(propertiesList)) { - log.warn("There is no configuration properties found"); + log.warn("There is no configurable properties found"); return; } @@ -55,33 +58,34 @@ class ConfigurablePropertiesLoader { boolean remoteFirst = ApolloProperties.get(environment).isRemoteFirst(); for (ConfigurableProperties properties : propertiesList) { - OrderedMapPropertySource propertySource = loadFromRemote(environment, remoteFirst, properties.getNamespace()); - if (propertySource == null) { - continue; - } - // multicast event + OrderedMapPropertySource propertySource = buildPropertySource(environment, remoteFirst, properties); ConfigLoadedEvent event = createEvent(environment, application, propertySource, properties); eventMulticaster.multicastEvent(event, ResolvableType.forClass(event.getClass())); } } - private OrderedMapPropertySource loadFromRemote(ConfigurableEnvironment environment, boolean remoteFirst, String namespace) { - Config config = ConfigService.getConfig(namespace); - OrderedMapPropertySource propertySource = ConfigUtils.toPropertySource(namespace, config); - if (propertySource == null) { - log.warn("No configuration properties loaded under namespace: " + namespace); - return null; - } + private OrderedMapPropertySource buildPropertySource(ConfigurableEnvironment environment, boolean remoteFirst, ConfigurableProperties properties) { + Map mergedProperties = loadAndMergeLocalDefaults(properties); + OrderedMapPropertySource propertySource = createPropertySource(environment, properties.getNamespace(), mergedProperties); if (remoteFirst) { environment.getPropertySources().addFirst(propertySource); } else { environment.getPropertySources().addLast(propertySource); } - // resolve any placeHolders - ConfigUtils.resolvePlaceHolders(environment, propertySource); return propertySource; } + private Map loadAndMergeLocalDefaults(ConfigurableProperties properties) { + String namespace = properties.getNamespace(); + Config config = ConfigService.getConfig(namespace); + Map loadedProperties = toPropertiesMap(config); + if (MapUtils.isEmpty(loadedProperties)) { + log.warn("No configuration properties loaded under namespace: " + namespace); + } + Map defaultProperties = ConfigurationPropertiesUtils.toMap(properties); + return mergeProperties(loadedProperties, defaultProperties); + } + private ConfigLoadedEvent createEvent(ConfigurableEnvironment environment, SpringApplication application, OrderedMapPropertySource propertySource, ConfigurableProperties properties) { ConfigurableProperties boundProperties = properties.bind(environment); @@ -98,4 +102,35 @@ class ConfigurablePropertiesLoader { return eventMulticaster; } -} \ No newline at end of file + private Map toPropertiesMap(Config config) { + Set propertyNames = config.getPropertyNames(); + if (propertyNames.isEmpty()) { + return Collections.emptyMap(); + } + Map configs = Maps.newLinkedHashMapWithExpectedSize(propertyNames.size()); + for (String propertyName : propertyNames) { + String property = config.getProperty(propertyName, null); + configs.put(propertyName, property); + } + return configs; + } + + private Map mergeProperties(Map loadedProperties, Map defaultProperties) { + Map mergedProperties = new LinkedHashMap<>(); + mergedProperties.putAll(defaultProperties); + mergedProperties.putAll(loadedProperties); + return mergedProperties; + } + + private OrderedMapPropertySource createPropertySource(Environment environment, String namespace, Map source) { + for (Entry entry : source.entrySet()) { + Object value = entry.getValue(); + if (value instanceof String) { + String resolvedValue = environment.resolvePlaceholders((String) value); + source.put(entry.getKey(), resolvedValue); + } + } + return new OrderedMapPropertySource(namespace, source); + } + +} diff --git a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/config/OrderedMapPropertySource.java b/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/config/OrderedMapPropertySource.java index b73a70676bc1ce2b26226245fd70f6aafacd595c..b9ba883a201ddaee2921a14dcb0df40821ac73d3 100644 --- a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/config/OrderedMapPropertySource.java +++ b/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/config/OrderedMapPropertySource.java @@ -13,16 +13,16 @@ import java.util.Map; */ public class OrderedMapPropertySource extends MapPropertySource { - public OrderedMapPropertySource(String name, Map source) { + public OrderedMapPropertySource(String name, Map source) { super(name, new LinkedHashMap<>(source)); } - public void addProperties(Map properties) { + public void addProperties(Map properties) { getSource().putAll(properties); } - public void addProperty(String propertyName, String propertyValue) { + public void addProperty(String propertyName, Object propertyValue) { getSource().put(propertyName, propertyValue); } -} \ No newline at end of file +} diff --git a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/util/ConfigUtils.java b/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/util/ConfigUtils.java deleted file mode 100644 index cab29e7967d4c7ab0a53eb34badc583ae6e67a9b..0000000000000000000000000000000000000000 --- a/starters/apollo-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/apollo/util/ConfigUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.schbrain.framework.autoconfigure.apollo.util; - -import com.ctrip.framework.apollo.Config; -import com.google.common.collect.Maps; -import com.schbrain.framework.autoconfigure.apollo.config.OrderedMapPropertySource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.env.ConfigurableEnvironment; - -import javax.annotation.Nullable; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * @author liaozan - * @since 2021/12/6 - */ -@Slf4j -public class ConfigUtils { - - @Nullable - public static OrderedMapPropertySource toPropertySource(String name, Config config) { - Set propertyNames = config.getPropertyNames(); - if (propertyNames.isEmpty()) { - return null; - } - Map configs = Maps.newLinkedHashMapWithExpectedSize(propertyNames.size()); - for (String propertyName : propertyNames) { - String property = config.getProperty(propertyName, null); - configs.put(propertyName, property); - } - return new OrderedMapPropertySource(name, configs); - } - - public static void resolvePlaceHolders(ConfigurableEnvironment environment, OrderedMapPropertySource propertySource) { - Map source = propertySource.getSource(); - for (Entry entry : source.entrySet()) { - Object value = entry.getValue(); - if (value instanceof String) { - String resolvedValue = environment.resolvePlaceholders((String) value); - source.put(entry.getKey(), resolvedValue); - } - } - } - -} \ No newline at end of file diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/properties/CacheProperties.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/properties/CacheProperties.java index adc65ed3ad1ff2390c977a8f29fd228820939c37..7bf2fc04efe6a541493793e91a2905f5491c5cef 100644 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/properties/CacheProperties.java +++ b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/properties/CacheProperties.java @@ -32,4 +32,4 @@ public class CacheProperties implements ConfigurableProperties { return "cache-common"; } -} \ No newline at end of file +} diff --git a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/provider/redis/RedisProperties.java b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/provider/redis/RedisProperties.java index 49f5c83dd53adcfb77329818c68c5fedddb93bf0..fcc308b28bad8f8492230028660af9d696b5e99c 100644 --- a/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/provider/redis/RedisProperties.java +++ b/starters/cache-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/cache/provider/redis/RedisProperties.java @@ -17,4 +17,4 @@ public class RedisProperties implements ConfigurableProperties { return "redis-common"; } -} \ No newline at end of file +} diff --git a/starters/elasticsearch-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/elasticsearch/properties/ElasticsearchProperties.java b/starters/elasticsearch-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/elasticsearch/properties/ElasticsearchProperties.java index 795275d5fb4850da6abf1941c60a62ac06687c06..3adc1a93e255b3c1552b4e8c3529904f3606c10b 100644 --- a/starters/elasticsearch-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/elasticsearch/properties/ElasticsearchProperties.java +++ b/starters/elasticsearch-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/elasticsearch/properties/ElasticsearchProperties.java @@ -17,4 +17,4 @@ public class ElasticsearchProperties implements ConfigurableProperties { return "elasticsearch-common"; } -} \ No newline at end of file +} diff --git a/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/listener/LoggerConfigLoadedEventListener.java b/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/listener/LoggerConfigLoadedEventListener.java index 96d13c1549c195620b603d86fcd15449aca8d364..ece638c7e6d338148093772d7a34d7f38822ebf5 100644 --- a/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/listener/LoggerConfigLoadedEventListener.java +++ b/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/listener/LoggerConfigLoadedEventListener.java @@ -43,7 +43,7 @@ public class LoggerConfigLoadedEventListener extends GenericConfigLoadedEventLis @Override protected void onConfigLoaded(ConfigLoadedEvent event, LoggerProperties properties) { HostInfo hostInfo = InetUtils.findFirstNonLoopBackHostInfo(); - Map hostInfoProperties = buildHostInfoProperties(hostInfo); + Map hostInfoProperties = buildHostInfoProperties(hostInfo); event.getPropertySource().addProperties(hostInfoProperties); configLoggingFileLocation(event.getEnvironment(), properties.getLogConfigNamespace()); this.loggerInitializer = new LoggerConfigurationInitializer(event.getEnvironment(), properties, hostInfo); @@ -52,8 +52,8 @@ public class LoggerConfigLoadedEventListener extends GenericConfigLoadedEventLis /** * hostInfo properties, for logging pattern */ - private Map buildHostInfoProperties(HostInfo hostInfo) { - Map properties = Maps.newHashMapWithExpectedSize(2); + private Map buildHostInfoProperties(HostInfo hostInfo) { + Map properties = Maps.newHashMapWithExpectedSize(2); properties.put("application.hostname", hostInfo.getHostname()); properties.put("application.ipAddress", hostInfo.getIpAddress()); return properties; diff --git a/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/properties/LoggerProperties.java b/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/properties/LoggerProperties.java index 5e73080e8971cdc53c358ae7adfde14a6dc91a62..6abe1355e099df65f518a891f3004c19711a57c1 100644 --- a/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/properties/LoggerProperties.java +++ b/starters/logger-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/logger/properties/LoggerProperties.java @@ -41,4 +41,4 @@ public class LoggerProperties implements ConfigurableProperties, PriorityOrdered return HIGHEST_PRECEDENCE; } -} \ No newline at end of file +} diff --git a/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/DataSourceProperties.java b/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/DataSourceProperties.java index b34aa1e92e9f747c64fef138b5e25f78bdd53db0..9d553c6891313c8f8d068189061193edbb709659 100644 --- a/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/DataSourceProperties.java +++ b/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/DataSourceProperties.java @@ -17,4 +17,4 @@ public class DataSourceProperties implements ConfigurableProperties { return "jdbc-common"; } -} \ No newline at end of file +} diff --git a/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/MybatisProperties.java b/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/MybatisProperties.java index d6e3b393dbe51d699e230a0f50add4696e966d22..7e083bc7e0e5b9a142240fdbef9f9f7955e2d926 100644 --- a/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/MybatisProperties.java +++ b/starters/mybatis-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/mybatis/properties/MybatisProperties.java @@ -37,4 +37,4 @@ public class MybatisProperties implements ConfigurableProperties { return "mybatis-common"; } -} \ No newline at end of file +} diff --git a/starters/oss-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/oss/properties/OssProperties.java b/starters/oss-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/oss/properties/OssProperties.java index 424295ad72ee88d3d39e278e0f8cca549d44b64c..cb2d43c9390973c17c2702063210c3f503722ab5 100644 --- a/starters/oss-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/oss/properties/OssProperties.java +++ b/starters/oss-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/oss/properties/OssProperties.java @@ -50,4 +50,4 @@ public class OssProperties implements ConfigurableProperties { } -} \ No newline at end of file +} diff --git a/starters/xxl-job-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/xxl/properties/XxlJobProperties.java b/starters/xxl-job-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/xxl/properties/XxlJobProperties.java index cee1626cbde55e84dbdce11161e68de4034fe395..45d65d8dc62ab668f731e6ddf1a71b855995d60c 100644 --- a/starters/xxl-job-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/xxl/properties/XxlJobProperties.java +++ b/starters/xxl-job-spring-boot-starter/src/main/java/com/schbrain/framework/autoconfigure/xxl/properties/XxlJobProperties.java @@ -30,4 +30,4 @@ public class XxlJobProperties implements ConfigurableProperties { return "xxl-job-common"; } -} \ No newline at end of file +}