一般说来,读取 SpringBoot 配置文件的方式大致可以分为三种(见下↓)。更详细的分类包括是否使用自定义配置文件、自定义配置文件的文件类型(.properties还是.yml)以及配置的 key 是否使用”前缀”等等。
- @Value + [@PropertySource]
- setXxx() + @ConfigurationProperties + [@PropertySource]
- environment.getProperty(“xxx”)
多说无益,直接上一个综合的栗子,一切不言自明。
需求场景: 一个接口需要从 application.properties 、diy.properties 以及 diy.yml 中读取配置给变量赋值(包括给静态变量赋值),然后再进行其它的业务逻辑的操作。
代码目录结构:
package com.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
//@PropertySource("classpath:config/diy.properties")
//@PropertySources({
// @PropertySource("classpath:config/diy.properties"),
// @PropertySource("classpath:diy.yml")}
//)
@PropertySource(value = {"classpath:config/diy.properties", "classpath:diy.yml"})
@ConfigurationProperties(prefix = "person")
public class TestController {
//@Value("${name}")
//注意事项:读取 .properties 中的配置时,变量名必须加上前缀,否则运行报错
@Value("${person.name}")
private String name;
private Integer age;
public void setAge(Integer age) {
this.age = age;
}
// 静态变量获取配置文件中的配置
private static String password;
@Value("${person.password}")
//注意事项:注意不是使用默认的 setXxx,而是去掉"static"的 setXxx 方法
public void setPassword(String password) {
TestController.password = password;
}
@Autowired
public Environment environment;
//@Value("${person.num}")
//注意事项:读取 .yml 中的配置时,变量名不能添加前缀,否则运行报错
@Value("${num}")
private int num;
private int num2;
public void setNum2(int num2) {
this.num2 = num2;
}
@RequestMapping("/test")
@ResponseBody
public String test() {
System.out.println("name = " + name);
System.out.println("age = " + age);
System.out.println("password = " + password);
System.out.println("num = " + num);
System.out.println("num2 = " + num2);// 0,无法设置前缀,导致无法获取到值,结论:形如 person.num2 使用 @Value 获取,不要使用 @setXxx 方式
System.out.println("environment.getProperty(\"person.sex\"):" + environment.getProperty("person.sex"));
return "springboot 访问成功!";
}
}
diy.yml
person:
num: 2020
num2: 2022
application.properties
person.name=from applictionn.properties
diy.properties
person.name=name from diy.properties
person.age=20
person.password=pwd form diy.properties
person.sex=sex form diy.properties
访问 http://localhost:8080/test 测试,运行结果:
- 控制台输出:
name = from applictionn.properties
age = 20
password = pwd form diy.properties
num = 2020
num2 = 0
environment.getProperty("person.sex"):sex form diy.properties
- 浏览器:
【小结】
- 当一个配置在
application.properties
和自定义配置文件中同时存在时,取application.properties。也就是说application.properties 的优先级高于自定义配置文件。 - 当使用
@Value
读取配置信息时,
① 如果读取的是.properties
文件,@Value("${xxx.xxx}")
必须使用配置中 key全称(即加上”前缀”),且如果是自定义配置文件,还要加上@PropertySource("classpath:xxx/xxx.properties)
指定配置文件位置。
② 如果读取的是.yml
文件,@Value("${xxx}")
使用的配置的 key 需要去掉”前缀”。同样如果是自定义配置文件,也要指定配置文件位置。 - 使用
@Value
时,如果获取的是application.properties
中的配置,则不需要在@PropertySource("classpath:xxx/xxx.properties")
设置文件路径。也不需要在@ConfigurationProperties(prefix = "xxx")
中设置”前缀”(因为@Value
获取.properties
中的配置,必须使用配置中 key 的全称)。 - 大多数情况下,一个类文件中只读取一个配置文件,使用
@PropertySource("classpath:xxx/xxx.properties")
即可。实在需要使用多个配置文件的情况下,使用@PropertySources({ @PropertySource("classpath:config/diy.properties"), @PropertySource("classpath:diy.yml")} )
或者@PropertySource(value = {"classpath:config/diy.properties", "classpath:diy.yml"})
- 静态变量读取配置信息,需要使用
setXxx
,这里尤其要注意使用public void setXxx(E e)
的形式,不要使用编辑器默认生成的setXxx
方法 —public static void setXxx(E e)
形式,否则将无法读取到配置信息。