Properties读取yaml/yml值为null
在分模块,单体项目多模块情况下,在其他模块的Properties使用@ConfigurationProperties是会去默认找主启动类模块的yml,所以会导致找不到对应值,解决方案就是指定类去读取哪个模块的yml值,可以使用 @PropertySource 指定额外的 YAML 文件,但是发现 @PropertySource 并不直接支持解析 .yml,导致属性无法注入、出现 null 值或报错。
最终解决方案
准备自定义的 YamlPropertySourceFactory
package com.example.config;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.PropertySourceFactory;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
import java.util.Properties;
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
// 利用 Spring 的 YamlPropertiesFactoryBean 将 YAML 转换为 Properties
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
Properties properties = factory.getObject();
// 如果 name 为空,就用文件名做 name
return new PropertiesPropertySource(
(name != null ? name : resource.getResource().getFilename()),
properties
);
}
}
在配置类上使用 @PropertySource + @ConfigurationProperties
package com.ssy.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import com.example.config.YamlPropertySourceFactory;
@Data
@Component
@PropertySource(value = "classpath:security.yml", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
private String secretKey;
private long ttl;
private String headName;
private String headBase;
}
常见注意点
1. 包路径:要保证 JwtProperties(以及 YamlPropertySourceFactory)在主应用类扫描范围内;否则需使用 @ComponentScan 或 @EnableConfigurationProperties 手动导入。
2. 文件位置:security.yml 必须在 classpath 中(通常放在 src/main/resources),并确保命名正确。
3. 覆盖优先级:若项目中还有 application.yml,则 Spring Boot 也会自动加载;如果同样存在 jwt: 字段,可能产生覆盖。要避免冲突,请在 application.yml 中去掉同样的前缀,或使用不同 key。
4. 自定义工厂原理:@PropertySource 内部调用 PropertySourceFactory 处理资源文件。Spring 原生仅支持 .properties,我们通过 YamlPropertiesFactoryBean 将 .yml 转为 Properties,再注入到 Environment。