SpringBoot簡明教程之項目屬性配置(二):@ConfigurationProperties與@Value簡單比較

前文回顧

在上一篇博文:SpringBoot簡明教程之項目屬性配置(一):YAML簡介 中我們簡單的介紹了SpringBoot的項目屬性配置中有關YAML文件的簡單語法以及簡單展示了通過配置文件進行值注入。

@ConfigurationProperties與@Value簡單比較

在上一篇博客中,我們主要是通過@ConfigurationProperties進行的配置文件值注入。這一節,我們將演示如何通過@Value來實現配置文件值注入以及其與@ConfigurationProperties注入的的異同點。

如何通過@Value來實現注入值

只需要將我們上一節的Person.java更改爲如下即可:

package com.example.springboot03.bean;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author: REN
 * @Description:
 * @Date: Created in 0:25 2018/8/22
 */

@Component
//@ConfigurationProperties(prefix = "person")
public class Person {
    @Value("${person.name}")
    private String name;
    @Value("#{2*18}")
    private Integer age;
    @Value("2018/08/24")
    private Date birth;
    private List<Object> list;
    private Map<String,Object> maps;
    @Value("${person.dog}")
    private Dog dog;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birth=" + birth +
                ", list=" + list +
                ", maps=" + maps +
                ", dog=" + dog +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
}

然後,我們運行主函數,在瀏覽器輸入:http://localhost:8081/person 即可看到:

這裏寫圖片描述

錯誤提示:如果運行過程中報錯:java.lang.IllegalStateException: Failed to load property source from location ‘classpath:/application.yml 就需要重新檢查下配置文件是否書寫正確。

是否支持鬆散綁定(Relaxed Binding)

對於Spring Boot來說,下面的四種寫法在配置文件中其實是等價的:

spring:
  jpa:
    databaseplatform: mysql
    database-platform: mysql
    databasePlatform: mysql
    database_platform: mysql

例如:我們將上面Person.java中的

@Value("${person.name}") 

更改爲

@Value("${person.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.Name' in value "${person.Name}"

我們在application.yml的文件中,更改屬性爲:

server:
  port: 8081

---

person:
  Name: ren  ## 將之前的name更改爲Name
  age: 18
  birth: 2018/08/22
  maps: {k1: v1,k2: v2}
  list:
    - hi
    - hello
  dog:
    name: rack
    age: 2

並使用@ConfigurationProperties的方式來注入值,我們發現綁定成功;

這裏寫圖片描述

總結:@ConfigurationProperties支持鬆散綁定,@Value不支持鬆散綁定

是否支持SpEL語法

對於SpEL表達式有不懂的小夥伴,可以先查看:這篇博客

我們在使用@Value進行值注入時,使用瞭如下的代碼:

@Value("#{2*18}")
private Integer age;

我們發現在運行過程中,Spring Boot成功的給我們算出了結果:

這裏寫圖片描述

但是,在通過@ConfigurationProperties進行注入時,就無法進行計算。(可自行檢驗,這裏就不再展示)

總結:@Value支持SpEL,但是@ConfigurationProperties不支持.需要注意的是:@Value(“#{}”)才用於SpEL表達式,通過@Value(“${}”) 用來獲取對應屬性文件中定義的屬性值。

是否支持JSR303數據校驗

JSR-303 是 JAVA EE 6 中的一項子規範,叫做 Bean Validation,用於對 Java Bean 中的字段的值進行驗證。其的基本校驗規則如下:

空檢查
@Null :驗證對象是否爲null
@NotNull: 驗證對象是否不爲null, 無法查檢長度爲0的字符串
@NotBlank :檢查約束字符串是不是Null還有被Trim的長度是否大於0,只對字符串,且會去掉前後空格.
@NotEmpty :檢查約束元素是否爲NULL或者是EMPTY.

Booelan檢查
@AssertTrue :驗證 Boolean 對象是否爲 true
@AssertFalse :驗證 Boolean 對象是否爲 false

長度檢查
@Size(min=, max=): 驗證對象(Array,Collection,Map,String)長度是否在給定的範圍之內
@Length(min=, max=): Validates that the annotated string is between min and max included.

日期檢查
@Past: 驗證 Date 和 Calendar 對象是否在當前時間之前,驗證成立的話被註釋的元素一定是一個過去的日期
@Future: 驗證 Date 和 Calendar 對象是否在當前時間之後 ,驗證成立的話被註釋的元素一定是一個將來的日期
@Pattern: 驗證 String 對象是否符合正則表達式的規則,被註釋的元素符合制定的正則表達式,regexp:正則表達式 flags: 指定 Pattern.Flag 的數組,表示正則表達式的相關選項。

數值檢查
建議使用在Stirng,Integer類型,不建議使用在int類型上,因爲表單值爲“”時無法轉換爲int,但可以轉換爲Stirng爲”“,Integer爲null
@Min: 驗證 Number 和 String 對象是否大等於指定的值
@Max: 驗證 Number 和 String 對象是否小等於指定的值
@DecimalMax: 被標註的值必須不大於約束中指定的最大值. 這個約束的參數是一個通過BigDecimal定義的最大值的字符串表示.小數存在精度
@DecimalMin: 被標註的值必須不小於約束中指定的最小值. 這個約束的參數是一個通過BigDecimal定義的最小值的字符串表示.小數存在精度
@Digits: 驗證 Number 和 String 的構成是否合法
@Digits(integer=,fraction=): 驗證字符串是否是符合指定格式的數字,interger指定整數精度,fraction指定小數精度。
@Range(min=, max=) :被指定的元素必須在合適的範圍內
@Range(min=10000,max=50000,message=”range.bean.wage”)
@Valid: 遞歸的對關聯對象進行校驗, 如果關聯對象是個集合或者數組,那麼對其中的元素進行遞歸校驗,如果是一個map,則對其中的值部分進行校驗.(是否進行遞歸驗證)
@CreditCardNumber:信用卡驗證
@Email: 驗證是否是郵件地址,如果爲null,不進行驗證,算通過驗證。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

我們在Person.java中更改如下代碼:

@Component
@Validated  //增加@Validated 進行驗證
@ConfigurationProperties(prefix = "person")  //使用@ConfigurationProperties來支持鬆散綁定
public class Person {

//     @Value("${person.name}")
//    @Value("${person.Name}")     將 @Value("${person.name}") 更改爲@Value("${person.Name}")   發現@Value不支持鬆散綁定
    @Email //對name字段進行郵箱驗證
    private String name;

//其餘代碼不變

啓動程序,發現報錯:

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to com.example.springboot03.bean.Person failed:

    Property: person.name
    Value: ren
    Origin: class path resource [application.yml]:7:9
    Reason: 不是一個合法的電子郵件 

如果我們使用@Value進行值注入,就會發現程序正常啓動,則證明@Eamil註解未起作用。

總結: @ConfigurationProperties支持JSR303數據校驗,@Value不支持。

是否支持複雜類型的封裝

在上一篇博文中,我們使用@ConfigurationProperties進行值注入時,發現;Map、list、javaBean等類型均能順利注入:

這裏寫圖片描述

但是在@Value中卻是無法進行注入的

總結:總結: @ConfigurationProperties支持複雜類型的封裝注入,@Value不支持。

總結

我們將上面的討論的情況,總結爲下面的一張表:

@ConfigurationProperties @Value
適用場景 批量注入配置文件中的屬性
鬆散綁定(鬆散語法) 支持
SpEL表達式 不支持
JSR303數據校驗 支持
複雜類型封裝 支持

@Value:我們只是在某個業務邏輯中需要獲取一下配置文件中的某項值;
@ConfigurationProperties:如果說,我們專門編寫了一個javaBean來和配置文件進行映射;

源碼下載

點擊下載

特別說明:

參考文獻:

尚硅谷,SpringBoot核心技術篇

徐劉根,JSR 303 - Bean Validation 簡介及使用方法

轉載說明: 支持轉載,但請保留原作者,原文鏈接,微信公衆號二維碼

這裏寫圖片描述 掃碼關注作者個人技術公衆號,不定期將有學習資源分享

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