自定义Spring PropertySourceLoader解析的TOML配置值未生效如何解决
问题根因
你当前的实现核心问题在于Jackson将TOML解析后返回的是嵌套层级的Map结构,而Spring Boot的属性绑定逻辑要求PropertySource中存储的是扁平格式的配置Key,例如server.port、myapp.foo这种用点分隔的字符串作为Key,而非嵌套的server对应子Map的结构,因此Spring无法匹配到对应的属性值,导致所有配置都不生效。
解决方案
你需要在解析得到嵌套Map后,将其递归扁平化为带点分隔符的单层Map,再传入OriginTrackedMapPropertySource即可。
修复后的核心代码
public final class TomlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { if (!ClassUtils.isPresent("com.fasterxml.jackson.dataformat.toml.TomlFactory", null)) { throw new IllegalStateException( "Attempted to load " + name + " but jackson-dataformat-toml was not found on the classpath"); } if (!ClassUtils.isPresent("com.fasterxml.jackson.core.io.ContentReference", null)) { throw new IllegalStateException( "Attempted to load " + name + " but jackson-core was either not found on the classpath or below version 2.13.0"); } final ObjectMapper mapper = new ObjectMapper(new TomlFactory()); final Map<String, Object> nestedMap = mapper.convertValue(mapper.readTree(resource.getInputStream()), new TypeReference<Map<String, Object>>(){}); // 扁平化处理嵌套Map Map<String, Object> flatMap = new HashMap<>(); flattenMap(nestedMap, "", flatMap); return new OriginTrackedMapPropertySource(Optional.ofNullable(name).orElseGet(resource.getResource()::getFilename), flatMap); } /** * 递归扁平化嵌套Map,生成带点分隔的Key */ private void flattenMap(Map<String, Object> source, String prefix, Map<String, Object> target) { source.forEach((key, value) -> { String currentKey = prefix.isEmpty() ? key : prefix + "." + key; if (value instanceof Map) { @SuppressWarnings("unchecked") Map<String, Object> subMap = (Map<String, Object>) value; flattenMap(subMap, currentKey, target); } else { // 基础类型、集合类型直接存储,Spring属性绑定可自动适配对应格式 target.put(currentKey, value); } }); } }
你原有TomlPropertySourceLoader的逻辑不需要修改,重启应用后server.port、@ConfigurationProperties注入都会正常生效。
内容的提问来源于stack exchange,提问作者oa54
相关产品推荐
相关产品推荐

