SpringBoot学习笔记(十二)–@Value获取值和@ConfigurationProperties获取值比较
@Value
使用 @Value 类似于
<bean class="Person">
<property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"> </property>
<bean/>
使用示例
package demo.yangxu.springboot.bean;
@Component
public class Person {
//${key}从环境变量、配置文件中获取值
@Value("${person.last-name}")
private String lastName;
//#{SpEL}: Spring Expression Language
@Value("#{11*2}")
private Integer age;
//字面量
@Value("true")
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
运行结果
Person{lastName='小明', age=22, boss=true, birth=null, maps=null, lists=null, dog=null}
松散绑定(松散语法)
@Value 不支持松散绑定,如果在 @Value 中使用松散语法
@Value("${person.lastName}")
private String lastName;
person.last-name=小明
会出现以下报错
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.lastName' in value "${person.lastName}"
SpEL (Spring Expression Language)
@Value 支持 SpEL
@Value("#{11*2}")
private Integer age;
运行结果
age=22
JSR303 数据校验
@Value 不支持 JSR303 数据校验
添加 @Validated 与 @Email 校验
package demo.yangxu.springboot.bean;
@Component
@Validated
public class Person {
@Email
@Value("${person.last-name}")
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
运行结果为
Person{lastName='小明', age=null, boss=null, birth=null, maps=null, lists=null, dog=null}
数据校验不起作用。
复杂类型封装
@Value 不支持复杂类型封装
在 @Value 中使用复杂类型封装
package demo.yangxu.springboot.bean;
@Component
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
@Value("${person.maps}")
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
运行结果为
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}"
@ConfigurationProperties
不论配置文件是 yml,还是 properties,他们都能获取到值。
松散绑定(松散语法)
@ConfigurationProperties 支持松散绑定
package demo.yangxu.springboot.bean;
@Component
@ConfigurationProperties(prefix="person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
person.last-name=小明
person.age=18
person.birth=2020/6/6
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=小狗
person.dog.age=3
运行结果
Person{lastName='小明', age=18, boss=false, birth=Sat Jun 06 00:00:00 CST 2020, maps={k1=v1, k2=14}, lists=[a, b, c], dog=Dog{name='小狗', age=3}}
SpEL (Spring Expression Language)
@ConfigurationProperties 不支持 SpEL
package demo.yangxu.springboot.bean;
@Component
@ConfigurationProperties(prefix="person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
person.age=#{11*2}
运行后会报错
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'person.age' to java.lang.Integer:
Property: person.age
Value: #{11*2}
Origin: class path resource [application.properties]:4:12
Reason: failed to convert java.lang.String to java.lang.Integer
Action:
Update your application's configuration
JSR303 数据校验
@ConfigurationProperties 支持 JSR303 数据校验
Spirng Boot 升级到 2.3 之后,需要自行添加以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
以下是官方的说法
As of #19550, Web and WebFlux starters do not depend on the validation starter by default anymore. If your application is using validation features, for example you find that javax.validation.* imports are not being resolved, you’ll need to add the starter yourself.
添加 @Validated 与 @Email 校验
package demo.yangxu.springboot.bean;
@Component
@ConfigurationProperties(prefix="person")
@Validated
public class Person {
@Email
private String lastName;
}
运行结果为
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to demo.yangxu.springboot.bean.Person failed:
Property: person.lastName
Value: 小明
Origin: class path resource [application.properties]:3:18
Reason: 不是一个合法的电子邮件地址
Action:
Update your application's configuration
复杂类型封装
@ConfigurationProperties 支持复杂类型封装
实例
Controller
package demo.yangxu.springboot.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Value("${person.last-name}")
private String name;
@RequestMapping("/sayHello")
public String sayHello(){
return "Hello, "+ name;
}
}
运行结果
@Value 和 @ConfigurationProperties 的使用场景
只在某个业务逻辑中,获取一下配置文件中的某项值,使用 @Value。
若专门编写了一个 javaBean 来和配置文件进行映射,就直接使用 @ConfigurationProperties。
也可以根据实际情况,两种方式结合着用。