1. 程式人生 > >SpringBoot簡明教程之專案屬性配置(二):@ConfigurationProperties與@Value簡單比較

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; } }

這裡寫圖片描述

錯誤提示:如果執行過程中報錯: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核心技術篇

轉載說明: 支援轉載,但請保留原作者,原文連結,微信公眾號二維碼

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