前言
SpringBoot 项目从 *.properties
中读取中文内容配置,出现了乱码。下面就针对读取乱码现象,随便谈一下……
IDEA 文件编码
有个习惯,每次新建项目都会先去设置文件编码。在 IDEA 中,Ctrl + Alt + s
打开设置面板,搜索 encoding ,在 File Encoding 一栏中,可以对当前项目下的文件编码进行全局设置(一般都设置 UTF-8)。
Spring Boot 的读取方式
读取配置文件,需要使用与之对应的编码进行解码,才能正确读取到正确的值。所以,Spring Boot 读取配置文件的方式,就是是否会导致乱码的关键。
搜索位置(SearchLocations)
1 |
|
属性资源加载器(PropertySourceLoader)
Spring Boot 通过 PropertySourceLoader
根据它所支持的文件后缀,尝试加载配置文件,最终以 PropertySource
的形式呈现。
1 |
|
这里的 PropertySourceLoader
来自于 ConfigFileApplicationListener
的内部类 Loader
,该内部类只有一个构造器,并在此初始化 PropertySourceLoader
。
1 |
|
SpringFactoriesLoader
会读取类路径下的所有 spring.factories
文件,找寻指定类的具体实现(服务)。
加载器加载配置
PropertiesPropertySourceLoader
会使用 OriginTrackedPropertiesLoader
加载配置,并将返回的结果封装成 PropertySource
集合返回。
1 |
|
OriginTrackedPropertiesLoader
加载配置使用的是 CharacterReader
1 |
|
下图是 CharacterReader
的继承结构,可以看出,其最终将读取的任务交由 java.io.Reader
处理。并且根据 debug
显示的对象信息,java.io.Reader
使用的字符集是 ISO-8859-1,而这就是导致乱码的罪魁祸首。
IDEA 勾选 Transparent native-to-ascii conversion
网上给出解决方法,大多都是勾选 IDEA Settings 的 Transparent native-to-ascii conversion
(上述的 Settings 面板有)。
根据官方文档解释,它会将非 ISO 8859-1
字符转义。但是在 IDEA 中,你仍能看到你所编辑的内容,如果使用普通的编辑器打开,会发现需要转义的字符已转义。
再根据上述的 properties
文件的加载过程,最终不会产生乱码。
yml/yaml 文件读取
之前 properties
文件的方式走不通,临时采用 yml
的方式解决了问题。在配置文件的加载过程中,我们可以看到 PropertySourceLoader
除了有 PropertiesPropertySourceLoader
还有一个 YamlPropertySourceLoader
,所以也顺便看看 yml
文件又是如何加载的。
Spring Boot 启动读取
直到使用 YamlPropertySourceLoader
加载,之前的步骤跟 properties
文件方式是一致的,这里就不赘述。
1 |
|
与 properties
类似,yml/yaml
也有与之对应的 OriginTrackedYamlLoader
。其底层使用 UnicodeReader
读取资源,而在 read() 调用中的第一件事就是使用 init() 初始化 internalIn2。其中根据 BOM 来判断资源该使用何种 Unicode 编码(UTF8/UTF16BE/UTF16LE)。如果没有 BOM ,则使用 UTF-8。所以,在我们使用 UTF-8 编码配置文件,Spring Boot 读取结果不会产生乱码。
@PropertySource 读取
有时需要将多个配置项存储到一个对象中,一个一个使用 @Value
不太方便,@PropertySource
则可以将配置封装在一个对象中。
1 |
|
所以默认情况下,@PropertySource
不支持 yml/yaml
的读取。使用自定义的 PropertySourceFactory
,重写 createPropertySource() 方法。
1 |
|