1 序
SpringBoot.jpg
- 示例代码(
maven
分支,load-properties
模块):https://gitee.com/eugene-example/springboot - 首先,我们通常读取的配置文件是指
properties
和yaml
两类。无论是使用Maven
还是Gradle
工具来构建,我们读取都是基于类路径,也就是工程resources
目录下存放的文件。本文先讲解读取properties
类型的配置文件。 - SpringBoot配置文件,例如工程
resources
目录下存放的:bootstrap.properties
、application.properties
、application-dev.properties
、application-prod.properties
。 - 用户自定义的配置文件,例如工程
resources
目录下存放的:config.properties
、db/ds.properties
。 -
Spring Framework
相关注解说明:-
@PropertySource
注解,使用value
属性,来指定加载类路径下的properties
文件,读取SpringBoot
配置文件时无需使用此注解,直接通过@Value
注解读取即可。 -
@Value
注解,通过表达式${key.key...}
直接读取SpringBoot
配置文件的属性。或者结合@ConfigurationProperties
注解使用。同时也可使用表达式#{object.prop}
来读取对象属性。 -
@ConfigurationProperties
注解,使用prefix
属性指定读取属性的前缀,可配合@Value
注解使用,便于简化读取属性表达式。
-
2 示例展示
2.1 使用的示例文件
- SpringBoot配置文件:
resource\application.properties
,内容如下:
server.port=9999
- 类路径下的用户自定义配置文件:
resource\config.properties
,内容如下:
user.name=EugeneHeen
user.password=12345678
- 类路径下自定义目录存放的用户自定义配置文件:
resource\db\ds.yml
,内容如下:
ds:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/eugene
username: root
password: 88888888
pool:
name: ds-poll
select: SELECT 1 FROM A
2.2 读取SpringBoot规范的默认配置文件
- 通过定义一个
POJO
封装SpringBoot配置文件的属性读取
@Data // 通过Lombok提供GET和SET方法
@ConfigurationProperties(prefix = "server")
@Component
public class BootProps {
private Integer port;
}
@RestController
@RequestMapping("/boots")
public class BootController {
@Autowired
private BootProps bootProps;
@Value("${server.port}")
private String port;
@GetMapping("/auth")
public String auth() {
return new StringBuilder("SpringBoot Server Port")
.append(": ")
.append(this.port)
.append(", 通过封装Bean获取Port:")
.append(this.bootProps.getPort()).toString();
}
}
- 直接在使用的类中通过
@Value
注解标记示例变量读取,例如,Controller
和Service
类
@RestController
@RequestMapping("/configs")
public class BootController {
@Value("${server.port}")
private Integer port;
@GetMapping("/value")
public String value() {
return new StringBuilder("SpringBoot Server Port")
.append(": ")
.append(this.port).toString();
}
}
2.3 读取用户自定义的配置文件
- 通过定义一个
POJO
类 ,@PropertySource
+@Value
注解来读取
@Data
@PropertySource(value = {"config.properties"})
@Component
public class ConfigProps {
@Value("${user.name}")
private String name;
@Value("${user.password}")
private String password;
}
- 通过定义一个
POJO
类 ,@PropertySource
+@ConfigurationProperties
注解来简化读取,也可配合@Value
注解使用。这种方法对YAML
文件无效,后续会通过详细示例阐述如何解决此问题
@Data
@PropertySource(value = {"db/ds.properties"})
@ConfigurationProperties(prefix = "master")
@Component
public class DsProps {
private String username;
private String password;
}
经实际测试,
SpringBoot2.3+
的版本,会自动将配置文件中的单词
、-
连接的属性,同自定义POJO
类中遵循驼峰命名
的属性匹配,无需使用@Value
注解来完成值读取。例如,1. 配置文件username
自动对应POJO
类中的userName
属性。2. 配置文件driver-class-name
自动对应POJO
类中的driverClassName
属性。
3 读取用户自定义YAML文件
3.1 User Define YAML,SpringBoot Say No!我不支持下面这些骚操作
-
@PropertySource
+@Value
注解 -
@PropertySource
+@ConfigurationProperties
注解
Tip:
@PropertySource
不支持YAML
文件加载,它仅仅支持Properties
文件加载
3.2 单层级YAML配置文件读取
-
单层级
VS多层级
- 但层级配置文件
ds: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/eugene username: root password: 88888888
- 多层级配置文件
ds: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/eugene username: root password: 88888888 pool: name: ds-poll select: SELECT 1 FROM A
- 但层级配置文件
- 通过定义一个
POJO
类 ,@PropertySource
+@ConfigurationProperties
+@Value
注解来实现单层级YAML
配置文件读取
@Data
@PropertySource(value = {"db/ds.yml"})
@ConfigurationProperties(prefix = "ds")
@Component
public class DsYaml {
@Value("${driver-class-name}")
private String driverClassName;
@Value("${username}")
private String userName;
@Value("${password}")
private String password;
}
3.3 多层级YAML配置文件读取
-
User Define YAML,SpringBoot Only Supports!我仅支持唯一的骚操作
-
@PropertySource
指定factory
属性为自定义DefaultPropertySourceFactory
的扩展类 +@Value
注解(别再瞎搞!切记!此处无法再使用@ConfigurationProperties
注解的prefix
属性指定前缀了)
-
-
关于
Spring Framework
中与配置文件相关的3
个类:-
YamlPropertiesFactoryBean
:用于将YAML
文件加载为Properties
文件。 -
YamlMapFactoryBean
:用于将YAML
文件加载为Map
对象。 -
DefaultPropertySourceFactory
:@PropertySource
注解中的factory
属性默认使用的实现类。
-
扩展
DefaultPropertySourceFactory
类,自定义YAML
文件加载工厂类
public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {
public YamlPropertySourceFactory() {
super();
}
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = Optional.ofNullable(name).orElse(resource.getResource().getFilename());
if (!resource.getResource().exists()) {
// return an empty Properties
return new PropertiesPropertySource(sourceName, new Properties());
} else if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
Properties propertiesFromYaml = loadYaml(resource);
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
} else {
return super.createPropertySource(name, resource);
}
}
/**
* 加载YAML文件
* @param resource YAML文件
* @return Properties对象
* @throws IOException 文件加载异常
*/
private Properties loadYaml(EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
- 加载多层级
YAML
配置文件
@Data
@PropertySource(factory = YamlPropertySourceFactory.class, value = {"db/ds.yml"})
@Component
public class DsAYaml {
@Value("${ds.driver-class-name}")
private String driverClassName;
@Value("${ds.username}")
private String userName;
@Value("${ds.password}")
private String password;
@Value("${ds.pool.name}")
private String poolName;
@Value("${ds.pool.select}")
private String poolSelect;
}