注解ConfigurationProperties和EnableAutoConfiguration的區別:
@EnableConfigurationProperties tells Spring to treat this class as a consumer of application.yml/properties values(
{@link ConfigurationProperties} beans can be registered in the standard way (for example using {@link Bean @Bean} methods)
or, for convenience, can be specified directly on this annotation.
)
@ConfigurationProperties tells Spring what section this class represents.
Annotation for externalized configuration(外面化配置). Add this to a class definition or a{@code @Bean} method in a {@code @Configuration} class
if you want to bind and validate some external Properties (e.g. from a .properties file).
之前在兩篇文章中都有簡單介紹或者提到過 自定義屬性的用法:
25.Spring Boot使用自定義的properties【從零開始學Spring Boot】
51. spring boot屬性文件之多環境配置【從零開始學Spring Boot】
但是在實際開發過程中有更復雜的需求,我們在對properties進一步的升華。在本篇博客中您將會學到如下知識(這節中有對之前的知識的溫故,對之前的升華):
(1) 在application.properties文件中添加自定義屬性(單個屬性使用);
(2) 在application.properties文件中添加自定義屬性(多個屬性使用);
(3) 配置數組注入;
(4) 松散的綁定;
(5) 參數的引用;
(6) 隨機數;
(7) 使用自定義的配置文件company.properties怎么操作;
(8) 在方法上使用@Bean的時候如何進行注入;
(9) 自定義結構;
(10) 校驗;
好了,本文大綱就這么多,那么我一起來看看每個知識點都應該怎么去操作吧。
(1) 在application.properties文件中添加自定義屬性(單個屬性使用);
在這里我們新建一個maven java project進行測試,取名為:spring-boot-hello4。
對pom.xml基本的spring boot 配置,主要用到的一個核心依賴是:
官方中對於spring-boot-configuration-processor是這么說明的:
通過使用spring-boot-configuration-processor jar, 你可以從被@ConfigurationProperties注解的節點輕松的產生自己的配置元數據文件。該jar包含一個在你的項目編譯時會被調用的Java注解處理器。想要使用該處理器,你只需簡單添加spring-boot-configuration-processor依賴。
好了,官方已經說得很清楚了,這個依賴主要可以在代碼中輕松的使用@ConfigurationProperties注解注入屬性文件配置的屬性值。
單屬性注入的比較簡單,只需要在application.properties加入配置,如下:
這里使用@Value注解就可以為我們的變量filePathLocation設置上我們在application.properties文件中設置的key值了。
在實際開發中可能我們期望的是,如果沒有設置key的話,設置一個默認值,使用如下代碼即可實現(以上@Value的使用方式如果在沒有設置key的話是會拋出異常的):
@Value("${filePathLocation1:d:/data/myfiles}") private String filePathLocation1;
這里的filePathLocation1我們並沒有在application.properties文件中進行指定,但是查看打印信息是可以看到我們設置的默認值的,所以設置默認值的方式就是:
@Value(“${key:defaultVlaue}”) 的形式進行設置。
(2) 在application.properties文件中添加自定義屬性(多個屬性使用);
多屬性的設置也可以屬性單屬性的注入方式,但是這種方式不好,那么怎么比較優雅的注入多個屬性值進行使用了。假設我們在application.properties定義了如下的屬性:
#公司簡稱;
com.kfit.company.name =知遠信科
#公司位置;
com.kfit.company.location =北京海淀區
#公司聯系方式;
com.kfit.company.mobile = 110****1195
#公司員工人數;
com.kfit.company.employCount = 100
接下來我們定義一個ComapnyProperties類進行設置這些參數。
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; //prefix設置key的前綴; @ConfigurationProperties(prefix = "com.kfit.company") @Component public class CompanyProperties { private String name; private String location; private String mobile; private int employCount; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public int getEmployCount() { return employCount; } public void setEmployCount(int employCount) { this.employCount = employCount; } @Override public String toString() { return "CompanyProperties{" + "name='" + name + '\'' + ", location='" + location + '\'' + ", mobile='" + mobile + '\'' + ", employCount=" + employCount + '}'; } }
那么之后我們就可以使用如下代碼注入到要使用的這些屬性的類進行使用了:
@Autowired private CompanyProperties companyProperties;
這里需要注意下:
第一:我們使用了@ConfigurationProperties(prefix = "com.kfit.company") 快速注入我們的屬性,這里prefix是key的公共部分。
第二:這里我們使用@Component 注解為spring 管理的類,那么在別的類才可以進行注入使用。
第三:在之前的文章中並沒有使用@Component注冊到spring 容器中,而是使用了@EnableConfigurationProperties({WiselySettings.class}) 這樣的方式進行注入的。這兩種方式都可以。
(3) 配置數組注入;
我們在application.properties定義數組:
private List<String> employs = new ArrayList<String>();
這里的屬性名稱employs需要和application.properties文件的key是對應的。
這樣employs注入了配置中的數據,打印為如下:
[張三, 李四, 王五]
(4) 松散的綁定;
Spring Boot使用寬松的規則用於綁定屬性到@ConfigurationProperties beans,所以Environment屬性名和bean屬性名不需要精確匹配。常見的示例中有虛線分隔的(比如,context-path綁定到contextPath),環境屬性大寫轉為小寫字母(比如:PORT綁定port)。
示例:
在application.properties文件中的配置:
com.kfit.company.firstName = lin com.kfit.company.logo-path = d:/data/files/logo.png com.kfit.company.COMPANY_FULLNAME =北京知遠科技公司
對應的CompanyProperties類中的對應定義:
//對應:com.kfit.company.firstName = lin private String firstName; //對應:com.kfit.company.logo-path = d:/data/files/logo.png private String logoPath; //對應:com.kfit.company.COMPANY_FULLNAME = 北京知遠科技公司 private String companyFullname; private List<String> employs = new ArrayList<String>();
看到這里,你是否終於知道為什么context-path,spring.jpa.show-sql
其實是被解釋為contextPath和showSql了,不然要是指定定義一個show-sql變量是無法編譯通過的,oh,原來是這么回事呢,這真是太神奇了,就是因為編程無奇不有,所以才有那么多人愛編程。
(5) 參數的引用;
在application.properties
中的各個參數之間也可以直接引用來使用,就像下面的設置:
com.kfit.blog.desc=${com.kfit.blog.name}正在寫《${com.kfit.blog.title}》
這個就很好理解了,使用${key} 的方式進行引用。
(6) 隨機數;
在一些情況下,有些參數我們需要希望它不是一個固定的值,比如密鑰、服務端口等。Spring Boot的屬性配置文件中可以通過${random}來產生int值、long值或者string字符串,來支持屬性的隨機值。
# 隨機字符串 com.kfit.blog.value=${random.value} # 隨機int com.kfit.blog.number=${random.int} # 隨機long com.kfit.blog.bignumber=${random.long} # 10以內的隨機數 com.kfit.blog.test1=${random.int(10)} # 10-20的隨機數 com.kfit.blog.test2=${random.int[10,20]}
好了,這些在之前的文章都有介紹過了,就不多說了。
(7) 使用自定義的配置文件company.properties怎么操作;
如果我們自己定義一個company.properties文件,
#key = value的形式; filePathLocation = d:/data/files #公司簡稱; com.kfit.company.name =知遠信科-custom #公司位置; com.kfit.company.location =北京海淀區-custom #公司聯系方式; com.kfit.company.mobile = 110****1195-custom #公司員工人數; com.kfit.company.employCount = 100 # 員工列表 com.kfit.company.employs[0]=張三-custom com.kfit.company.employs[1]=李四-custom com.kfit.company.employs[2]=王五-custom com.kfit.company.firstName = lin-custom com.kfit.company.logo-path = d:/data/files/logo.png-custom com.kfit.company.COMPANY_FULLNAME =北京知遠科技公司-custom
這個定義就是我們剛剛提到的一些配置,那么怎么引入了,如果使用上面的CompanyProperties的方式肯定是不行了,那么怎么呢?其實很簡單,只需要在CompanyProperties稍微修改下即可,修改的地方如下:
@ConfigurationProperties( prefix = "com.kfit.company", locations="classpath:company.properties")
大家注意,這里唯一不一樣的地方是加入了一個屬性locations指定了我們要使用的配置文件路徑和名稱,如果我們的配置文件不在application.properties下,可以這么定義:
classpath:config/company.properties。
好了這一個知識點就這么簡單,只要掌握要點,一句代碼就可以搞定。
(8) 在方法上使用@Bean的時候如何進行注入;
這個需求點是怎么產生的呢?我們經常會配置多個數據源,那么我們有些配置還是希望從application.properties文件中進行讀取,那么自然而然的在我們定義的@bean中就需要能夠讀取配置文件的屬性。這里我們簡單做個試驗,我們定義CompanyProperties3,具體代碼如下:
- package com.kfit.properties;
- import java.util.ArrayList;
- import java.util.List;
- public class CompanyProperties3 {
- private String name;
- private String location;
- private String mobile;
- private int employCount;
- //對應:com.kfit.company.firstName = lin
- private String firstName;
- //對應:com.kfit.company.logo-path = d:/data/files/logo.png
- private String logoPath;
- //對應:com.kfit.company.COMPANY_FULLNAME = 北京知遠科技公司
- private String companyFullname;
- private List<String> employs = new ArrayList<String>();
- public String getFirstName() {
- return firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- public String getLogoPath() {
- return logoPath;
- }
- public void setLogoPath(String logoPath) {
- this.logoPath = logoPath;
- }
- public String getCompanyFullname() {
- return companyFullname;
- }
- public void setCompanyFullname(String companyFullname) {
- this.companyFullname = companyFullname;
- }
- public List<String> getEmploys() {
- return employs;
- }
- public void setEmploys(List<String> employs) {
- this.employs = employs;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getLocation() {
- return location;
- }
- public void setLocation(String location) {
- this.location = location;
- }
- public String getMobile() {
- return mobile;
- }
- public void setMobile(String mobile) {
- this.mobile = mobile;
- }
- public int getEmployCount() {
- return employCount;
- }
- public void setEmployCount(intemployCount) {
- this.employCount = employCount;
- }
- @Override
- public String toString() {
- return "CompanyProperties [name=" + name + ", location=" + location + ", mobile=" + mobile + ", employCount="
- + employCount + ", firstName=" + firstName + ", logoPath=" + logoPath + ", companyFullname="
- + companyFullname + ", employs=" + employs + "]";
- }
- }
注意這里的代碼和以上不一樣的是類上的注解全沒有了,之后我們在App.java啟動類中或者其它的類也是可以的,使用@Bean的方式進行注入。
@Bean
@ConfigurationProperties(prefix = "com.kfit.company")
public CompanyProperties3 companyProperties3(){
returnnew CompanyProperties3();
}
那么在其它的類中我們就使用@Autowired進行注入使用了,如下:
- @Autowired
- private CompanyProperties3 companyProperties3;
是不是很好玩呢。
(9) 自定義結構;
對於復雜的配置或嵌套的kv,我們可以編寫自定義結構屬性以更好的方式進行管理。
比如我們在application.properties文件中有如下信息:
- com.kfit.employForzs.name =張三
- com.kfit.employForzs.age = 20
- com.kfit.employForzs.gender =男
- com.kfit.employForls.name =李四
- com.kfit.employForls.age = 25
- com.kfit.employForzs.gender =女
com.kfit.properties.CompanyEmployee的代碼如下:
- package com.kfit.properties;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
- //prefix設置key的前綴;
- @ConfigurationProperties(prefix = "com.kfit")
- @Component
- public class CompanyEmployee {
- private CompanyEmployeeInfo employForzs;
- private CompanyEmployeeInfo employForls;
- public CompanyEmployeeInfo getEmployForzs() {
- return employForzs;
- }
- publicvoid setEmployForzs(CompanyEmployeeInfo employForzs) {
- this.employForzs = employForzs;
- }
- public CompanyEmployeeInfo getEmployForls() {
- return employForls;
- }
- publicvoid setEmployForls(CompanyEmployeeInfo employForls) {
- this.employForls = employForls;
- }
- public static class CompanyEmployeeInfo {
- private String name;
- private int age;
- private String gender;
- public String getName() {
- return name;
- }
- publicvoid setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(intage) {
- this.age = age;
- }
- public String getGender() {
- returngender;
- }
- public void setGender(String gender) {
- this.gender = gender;
- }
- @Override
- public String toString() {
- return "EmployForzs [name=" + name + ", age=" + age + ", gender=" + gender + "]";
- }
- }
- @Override
- public String toString() {
- return "CompanyEmployee [employForzs=" + employForzs + ", employForls=" + employForls + "]";
- }
- }
觀察以上的代碼我們定義了一個內部靜態類進行處理相同的屬性,那么在外部類中定義兩個變量進行接收application.properties文件中的配置信息。
之后在其它類就可以使用@Autowired進行注入使用了。
(10) 校驗;
當我們使用@ConfigurationProperties的時候,我們希望對一些參數進行校驗,比如有些參數為空或者數字超出的限制就拋出異常信息,那么這個怎么操作呢?
在application.properties文件中加入:
com.kfit.company.url = http://www.kfit.com
在CompanyProperties類中加入:
@URL
private String url;
這里使用了@URL對url進行校驗,如果是非法的url在啟動的時候是會拋出異常信息的。
其中@URL對應的包路徑為:org.hibernate.validator.constraints.URL
那么還有其它的什么校驗器呢?看下文:
@Max(value = 99)
private int employCount;
定義最大值只能是99,那么如果運行的話,顯然就會報錯了,因為之前我們配置的值是100,那么就會看到控制台拋出異常信息:
default message [最大不能超過99]
這里只是截取了一小部分異常信息,具體的異常信息是可以參數那個參數的設置有問題的。
既然有最大值就有最小值的配置:
@Max(value = 1000)
@Min(value = 1)
private int employCount;
接着往下看:
@NotNull
private String name;
@NotNull說明name不能為null,如果為null就拋出異常。
接着往下看:
@NotEmpty
private String location;
@NotEmpty不能為空,當沒有定義key和key的值為空字符的時候都會拋出異常信息。
在validation-api下包javax.validation.constraints下還有其它的校驗器,大家可以根據需要自行學習。當然校驗器是可以自定定義的,大家可以自己在擴展下,好了這個章節就介紹到這里了。
【Spring Boot 系列博客】
54. spring boot日志升級篇—logback【從零開始學Spring Boot】
52. spring boot日志升級篇—log4j多環境不同日志級別的控制【從零開始學Spring Boot】
51. spring boot屬性文件之多環境配置【從零開始學Spring Boot】
50. Spring Boot日志升級篇—log4j【從零開始學Spring Boot】
49. spring boot日志升級篇—理論【從零開始學Spring Boot】
48. spring boot單元測試restfull API【從零開始學Spring Boot】
47. Spring Boot發送郵件【從零開始學Spring Boot】
46. Spring Boot中使用AOP統一處理Web請求日志
45. Spring Boot MyBatis連接Mysql數據庫【從零開始學Spring Boot】
44. Spring Boot日志記錄SLF4J【從零開始學Spring Boot】
43. Spring Boot動態數據源(多數據源自動切換)【從零開始學Spring Boot】
42. Spring Boot多數據源【從零開始學Spring Boot】
41. Spring Boot 使用Java代碼創建Bean並注冊到Spring中【從零開始學Spring Boot】
40. springboot + devtools(熱部署)【從零開始學Spring Boot】
39.4 Spring Boot Shiro權限管理【從零開始學Spring Boot】
39.3 Spring Boot Shiro權限管理【從零開始學Spring Boot】
39.2. Spring Boot Shiro權限管理【從零開始學Spring Boot】
39.1 Spring Boot Shiro權限管理【從零開始學Spring Boot】
38 Spring Boot分布式Session狀態保存Redis【從零開始學Spring Boot】
37 Spring Boot集成EHCache實現緩存機制【從零開始學Spring Boot】
36 Spring Boot Cache理論篇【從零開始學Spring Boot】
35 Spring Boot集成Redis實現緩存機制【從零開始學Spring Boot】
34Spring Boot的啟動器Starter詳解【從零開始學Spring Boot】
33 Spring Boot 監控和管理生產環境【從零開始學Spring Boot】
32 Spring Boot使用@SpringBootApplication注解【從零開始學Spring Boot】
31 Spring Boot導入XML配置【從零開始學Spring Boot】
更多查看博客: http://412887952-qq-com.iteye.com/
http://412887952-qq-com.iteye.com/blog/2311017