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核心技術篇
轉載說明: 支援轉載,但請保留原作者,原文連結,微信公眾號二維碼