SpringBoot——实现获取配置文件里的配置值
程序员文章站
2022-05-03 22:29:14
...
SpringBoot: 2.2.1.RELEASE
IDE: IDEA
使用模块和POM文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.demo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--Web模块所需要的依赖启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--获取配置文件值所需要的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!--测试模块所需要的依赖启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
一、使用@ConfigurationProperties实现获取
测试文件两个;
/**
* @Component 表示这个类是springboot的一个组件,只有这个组件在容器中才可以使用
* @ConfigurationProperties 表示这是一个配置类,它的值是通过配置文件获取的
* prefix 表示获取的值是这个父节点下的值,这里获取的是 person 节点下的值
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean student;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private School school;
// getter 、setter 和toString省略
}
public class School {
private String name;
private Date startDate;
// getter 、setter 和toString省略
}
配置文件:
person:
name: Li Ming
age: 12
student: true
birth: 2019/11/14
maps: {k1: v1,k2: v2}
lists: [list1,list2]
school:
name: shuguang
startDate: 2019/09/01
测试类:
@SpringBootTest
class DemoApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
测试结果:
Person{name='Li Ming', age=12, student=true, birth=Thu Nov 14 00:00:00 GMT+08:00 2019, maps={k1=v1, k2=v2}, lists=[list1, list2], school=School{name='shuguang', startDate=Sun Sep 01 00:00:00 GMT+08:00 2019}}
这样我们就可以获取到值了
下面我们减少配置文件里的值
person:
name: Li Ming
# age: 12
student: true
birth: 2019/11/14
maps: {k1: v1,k2: v2}
lists: [list1,list2]
school:
name: shuguang
startDate: 2019/09/01
测试结果:
Person{name='Li Ming', age=null, student=true, birth=Thu Nov 14 00:00:00 GMT+08:00 2019, maps={k1=v1, k2=v2}, lists=[list1, list2], school=School{name='shuguang', startDate=Sun Sep 01 00:00:00 GMT+08:00 2019}}
我们发现,没有匹配的值这里会填充 null ;
我们在改一下,把 startDate 写成 start-date 我们看是否匹配上
person:
name: Li Ming
age: 12
student: true
birth: 2019/11/14
maps: {k1: v1,k2: v2}
lists: [list1,list2]
school:
name: shuguang
start-date: 2019/09/01
测试结果:
Person{name='Li Ming', age=12, student=true, birth=Thu Nov 14 00:00:00 GMT+08:00 2019, maps={k1=v1, k2=v2}, lists=[list1, list2], school=School{name='shuguang', startDate=Sun Sep 01 00:00:00 GMT+08:00 2019}}
我们发现也可以获取,这说明它的识别是松散的 -字母 当成大写字母处理了
当然,这些在 .properties 中也可以同样实现
如果 .properties 文件乱码,按照下面配置
下面是例子
配置文件
person.name=黎明
person.age=12
person.student=true
person.birth=2019/11/14
person.maps.k1=v1
person.maps.k2=v2
person.lists=list1,list2
person.school.name=曙光
person.school.start-date=2019/09/01
测试结果:
Person{name='黎明', age=12, student=true, birth=Thu Nov 14 00:00:00 GMT+08:00 2019, maps={k1=v1, k2=v2}, lists=[list1, list2], school=School{name='曙光', startDate=Sun Sep 01 00:00:00 GMT+08:00 2019}}
这里发现他们几乎是可以一样的使用。
二、使用@Value实现获取
这个标签支持三种获取值的方式,从配置文件获取只是它的一种方式:
方式 | 例 |
---|---|
通过${配置文件键} | @Value("${person.name}") |
通过#{SqEL} spring表达式 | @Value("#{3*4}") |
字面值 | @Value(“true”) |
下面我们改写一下上面的Person类
@Component
public class Person {
@Value("${person.name}") //通过${配置文件键}
private String name;
@Value("#{3*4}") //通过#{SqEL} spring表达式
private Integer age;
@Value("true") //字面值
private Boolean student;
private Date birthDate;
private Map<String,Object> maps;
private List<Object> lists;
private School school;
// getter 、setter 和toString省略
}
测试结果:
Person{name='Li Ming', age=12, student=true, birthDate=null, maps=null, lists=null, school=null}
这样就可以获取到了,但是他没办法支持松散绑定,和当没有这个配置值时就会报错
例如 birthDate 在配置文件里如果是 birth-date 就会报错,或者配置文件的键不存在也会报错,而不是填充 null ;
三、对比
我们修改一下Person类
@Component
@Validated
public class Person {
@Email
@Value("${person.name}") //通过${配置文件键}
private String name;
@Value("#{3*4}") //通过#{SqEL} spring表达式
private Integer age;
@Value("true") //字面值
private Boolean student;
private Date birthDate;
private Map<String,Object> maps;
private List<Object> lists;
private School school;
// getter 、setter 和toString省略
}
测试结果:
Person{name='Li Ming', age=12, student=true, birthDate=null, maps=null, lists=null, school=null}
我们发现JSR303没有校验住
我们改成@ConfigurationProperties的方式
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String name;
private Integer age;
private Boolean student;
private Date birthDate;
private Map<String,Object> maps;
private List<Object> lists;
private School school;
// getter 、setter 和toString省略
}
运行结果
//省略
Caused by: org.springframework.boot.context.properties.bind.validation.BindValidationException: Binding validation errors on person
- Field error in object 'person' on field 'name': rejected value [Li Ming]; codes [Email.person.name,Email.name,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [person.name,name]; arguments []; default message [name],[Ljavax.validation.constraints.Pattern$Flag;@ddf20fd,.*]; default message [不是一个合法的电子邮件地址]; origin class path resource [application.yml]:2:9
//省略
从测试结果我们可以看出它是支持的
我们看一下复杂类型的注入
@ConfigurationProperties是支持的,上面map和对象的注入就是个例子
@Value不支持,举例说明:
@Component
public class Person {
@Value("${person.name}") //通过${配置文件键}
private String name;
@Value("#{3*4}") //通过#{SqEL} spring表达式
private Integer age;
@Value("true") //字面值
private Boolean student;
private Date birthDate;
@Value("${person.maps}")
private Map<String,Object> maps;
private List<Object> lists;
private School school;
// getter 、setter 和toString省略
}
测试结果:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'person.maps' in value "${person.maps}"
我们发现报错了。也验证了@Value不支持复杂类型的注入
归纳:
@ConfigurationProperties | @Value | |
---|---|---|
配置文件注入方式 | 批量注入 | 一个一个注入 |
配置文件不存在值 | 用null填充 | 报错,不允许 |
SpEL | 不支持 | 支持 |
松散绑定 | 支持 | 不支持 |
JSR303校验 | 支持 | 不支持 |
配置文件复杂类型注入 | 支持 | 不支持 |