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.

來源:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters

添加 @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。

也可以根據實際情況,兩種方式結合着用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章