Spring Boot中读取半已知键名的配置属性
处理Spring Boot中动态结构的配置属性读取需求
嘿,这个场景我之前在项目里碰到过!Spring Boot自带的@ConfigurationProperties并不直接支持你说的?通配符语法,但我们有两种很实用的方式来读取这类动态结构的配置键,帮你搞定这个需求:
方法一:用Map接收前缀下的所有属性,自行筛选匹配
这种方式最简洁,适合你已经明确顶级前缀(比如US)的情况:
- 定义一个配置类,用
@ConfigurationProperties指定前缀,并用Map接收该前缀下的所有键值对:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Map; @Component @ConfigurationProperties(prefix = "us") public class UsDynamicProperties { // 键会自动转换为去掉前缀后的部分,比如"georgia.visa.2233" -> 值"4400" private Map<String, String> details; // Getter和Setter public Map<String, String> getDetails() { return details; } public void setDetails(Map<String, String> details) { this.details = details; } }
- 在业务代码中注入这个配置类,然后根据你的通配需求筛选键:
import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; @Service public class PropertyProcessingService { @Resource private UsDynamicProperties usDynamicProperties; public Map<String, String> getMatchedProperties() { Map<String, String> result = new HashMap<>(); Map<String, String> allProperties = usDynamicProperties.getDetails(); // 示例1:匹配类似"US.georgia.?.2233"的键 allProperties.forEach((key, value) -> { String[] segments = key.split("\\."); // 分割后应该是[georgia, xxx, 2233],所以长度为3,第一段是georgia,第三段是2233 if (segments.length == 3 && "georgia".equals(segments[0]) && "2233".equals(segments[2])) { result.put("US." + key, value); } }); // 示例2:匹配类似"US.NC.visa.?"的键 allProperties.forEach((key, value) -> { String[] segments = key.split("\\."); // 分割后应该是[NC, visa, xxx],长度为3,前两段是NC和visa if (segments.length == 3 && "NC".equals(segments[0]) && "visa".equals(segments[1])) { result.put("US." + key, value); } }); return result; } }
方法二:结合Environment和正则表达式精准匹配
如果你的匹配规则更复杂,或者不想依赖固定前缀,可以直接通过Environment获取所有配置,再用正则筛选:
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; @Component public class DynamicPropertyMatcher { private final Environment environment; private Map<String, String> matchedProperties = new HashMap<>(); public DynamicPropertyMatcher(Environment environment) { this.environment = environment; } @PostConstruct public void loadMatchedProperties() { ConfigurableEnvironment configurableEnv = (ConfigurableEnvironment) environment; // 遍历所有配置源 configurableEnv.getPropertySources().forEach(source -> { if (source instanceof MapPropertySource) { Map<String, Object> sourceMap = ((MapPropertySource) source).getSource(); sourceMap.forEach((key, value) -> { // 用正则匹配你需要的键格式 // 匹配"US.georgia.任意内容.2233" if (key.matches("US\\.georgia\\..*\\.2233")) { matchedProperties.put(key, value.toString()); } // 匹配"US.NC.visa.任意内容" if (key.matches("US\\.NC\\.visa\\..*")) { matchedProperties.put(key, value.toString()); } }); } }); } // Getter public Map<String, String> getMatchedProperties() { return matchedProperties; } }
补充说明
- 正则表达式里的
.需要转义成\\.,因为原生正则中.代表任意字符 - 如果使用Spring Boot 2.2+,可以用
@ConfigurationPropertiesScan替代@Component来自动扫描配置类,更规范
内容的提问来源于stack exchange,提问作者Kiran
相关产品推荐
相关产品推荐

