Spring Boot 1.4.2中@ConfigurationProperties处理YAML文件异常求助
我之前也踩过完全一样的坑!这问题的根源其实是Spring Boot版本的特性限制:
在Spring Boot 1.4.2里,@PropertySource注解默认只支持解析.properties格式的配置文件,它并没有内置处理YAML文件的能力。当你用它加载global1.yml时,Spring会把整个YAML内容当成普通的字符串键值对来解析——menus下面的列表结构会被错误识别成一串杂乱的字符串,自然就无法转换成List<Menu>类型,这就是你看到类型转换报错的直接原因。
而application.yml能正常工作,是因为Spring Boot启动时会专门用YamlPropertySourceLoader这个类来处理默认的YAML配置文件,它能正确解析嵌套结构、列表这类YAML特有的语法。
下面给你两个实用的修复方案:
方案一:自定义PropertySourceFactory支持YAML解析
自己实现一个能加载YAML文件的工厂类,让@PropertySource具备解析YAML的能力:
- 先编写YAML属性源工厂类:
import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import org.springframework.boot.env.YamlPropertySourceLoader; import java.io.IOException; public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { if (resource == null) { throw new IllegalArgumentException("EncodedResource must not be null"); } // 用Spring Boot自带的YamlPropertySourceLoader加载YAML文件 return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()).get(0); } }
- 在配置类上指定这个工厂:
@Component @PropertySource(value = "classpath:global1.yml", factory = YamlPropertySourceFactory.class) @ConfigurationProperties public class GlobalProperties { private String name; private List<Menu> menus = new ArrayList<>(); // getter、setter及toString方法保留即可 }
这样@PropertySource就能正确识别YAML里的列表结构了。
方案二:改用.properties格式配置文件
如果不想写自定义代码,也可以把global1.yml转换成global1.properties,用properties的列表语法来写:
name=helloworld menus[0].title=Home menus[0].name=Home menus[0].path=/ menus[1].title=Login menus[1].name=Login menus[1].path=/login
然后把配置类的@PropertySource指向这个properties文件,Spring就能直接解析成List<Menu>类型。
最后提一句:如果你之后升级到Spring Boot 2.4及以上版本,@PropertySource已经原生支持YAML文件了,就不需要这些额外操作啦。
内容的提问来源于stack exchange,提问作者marcterenzi

