引言
spring boot的一個便捷功能是外部化配置,可以輕松訪問屬性文件中定義的屬性。本文將詳細介紹@configurationproperties的使用。
配置項目pom
在pom.xml中定義spring-boot 為parent
1
2
3
4
5
6
|
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version> 2.0 . 4 .release</version> <relativepath/> <!-- lookup parent from repository --> </parent> |
添加依賴
- 添加web,因為我們需要使用到jsr-303規范的validator,如果不想使用web依賴,也可以直接依賴hibernate-validator
- 添加spring-boot-configuration-processor,可以在編譯時生成屬性元數據(spring-configuration-metadata.json).
- 添加lombok,可以方便使用注釋處理器的功能省去pojo定義中get set這些麻煩工作.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <!--<dependency>--> <!--<groupid>org.hibernate.validator</groupid>--> <!--<artifactid>hibernate-validator</artifactid>--> <!--<version> 6.0 . 11 . final </version>--> <!--<scope>compile</scope>--> <!--</dependency>--> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-configuration-processor</artifactid> <optional> true </optional> </dependency> |
例子編寫
首先定義一個documentserverproperties對象,下面這個文檔服務器配置是我假設的,主要是為了演示屬性配置的大部分情況
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@getter @setter public class documentserverproperties { private string remoteaddress; private boolean preferipaddress; private int maxconnections= 0 ; private int port; private authinfo authinfo; private list<string> whitelist; private map<string,string> converter; private list<person> defaultshareusers; @getter @setter public static class authinfo { private string username; private string password; } } |
綁定屬性配置
注意@configurationproperties并沒有把當前類注冊成為一個spring的bean,下面介紹@configurationproperties配置注入的三種方式.
配合@component注解直接進行注入
1
2
3
4
5
|
@configurationproperties (prefix = "doc" ) @component public class documentserverproperties { //代碼... } |
使用@enableconfigurationproperties,通常配置在標有@configuration的類上,當然其他@component注解的派生類也可以,不過不推薦.
1
2
3
4
|
@configurationproperties (prefix = "doc" ) public class documentserverproperties { //代碼... } |
1
2
3
4
5
6
7
8
9
10
|
@enableconfigurationproperties @configuration public class someconfiguration { private documentserverproperties documentserverproperties public someconfiguration(documentserverproperties documentserverproperties) { this .documentserverproperties = documentserverproperties; } } |
使用@bean方式在標有@configuration的類進行注入,這種方式通??梢杂迷趯Φ谌筋愡M行配置屬性注冊
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@configuration public class someconfiguration { @bean public documentserverproperties documentserverproperties(){ return new documentserverproperties(); } @configurationproperties ( "demo.third" ) @bean public thirdcomponent thirdcomponent(){ return new thirdcomponent(); } } |
編寫配置文件
spring-boot中配置文件的格式有properties和yaml兩種格式,針對上面的配置對象分別寫了兩種格式的配置文件例子.
properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
doc.remote-address= 127.0 . 0.1 doc.port= 8080 doc.max-connections= 30 doc.prefer-ip-address= true #doc.whitelist= 192.168 . 0.1 , 192.168 . 0.2 # 這種等同于下面的doc.whitelist[ 0 ] doc.whitelist[ 1 ] doc.whitelist[ 0 ]= 192.168 . 0.1 doc.whitelist[ 1 ]= 192.168 . 0.2 doc. default -share-users[ 0 ].name=jack doc. default -share-users[ 0 ].age= 18 doc.converter.a=xxconverter doc.converter.b=xxconverter doc.auth-info.username=user doc.auth-info.password=password |
yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
doc: remote-address: 127.0 . 0.1 port: 8080 max-connections: 30 prefer-ip-address: true whitelist: - 192.168 . 0.1 - 192.168 . 0.2 default -share-users: - name: jack age: 18 converter: a: aconverter b: bconverter auth-info: username: user password: password |
在上面的兩個配置文件中,其實已經把我們平常大部分能使用到的屬性配置場景都覆蓋了,可能還有一些特殊的未介紹到,比如duration、inetaddress等。
增加屬性驗證
下面我們利用jsr303規范的實現對documentserverproperties屬性配置類,添加一些常規驗證,比如null檢查、數字校驗等操作,
需要注意在spring-boot 2.0版本以后,如果使用jsr303對屬性配置進行驗證必須添加@validated注解,使用方式如下片段:
1
2
3
4
5
6
7
8
9
10
11
12
|
@configurationproperties (prefix = "doc" ) @validated public class documentserverproperties { @notnull // 判斷不為空的情況 private string remoteaddress; //限制端口只能是80-65536之間 @min ( 80 ) @max ( 65536 ) private int port; //其他代碼 } |
在有些數情況下,我們希望自定義驗證器,有兩種方式可以進行實現
實現org.springframework.validation.validator接口,并且在配置一個bean名稱必須叫configurationpropertiesvalidator,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class userloginvalidator implements validator { private static final int minimum_password_length = 6 ; public boolean supports( class clazz) { return userlogin. class .isassignablefrom(clazz); } public void validate(object target, errors errors) { validationutils.rejectifemptyorwhitespace(errors, "username" , "field.required" ); validationutils.rejectifemptyorwhitespace(errors, "password" , "field.required" ); userlogin login = (userlogin) target; if (login.getpassword() != null && login.getpassword().trim().length() < minimum_password_length) { errors.rejectvalue( "password" , "field.min.length" , new object[]{integer.valueof(minimum_password_length)}, "the password must be at least [" + minimum_password_length + "] characters in ); } } } |
和上面一樣也是實現org.springframework.validation.validator接口,不過是需要驗證的屬性配置類本身去實現這個接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@configurationproperties (prefix = "doc" ) public class documentserverproperties implements validator{ @notnull private string remoteaddress; private boolean preferipaddress; //其他屬性 @override public boolean supports( class <?> clazz) { return true ; } @override public void validate(object target, errors errors) { //判斷邏輯其實可以參照上面的代碼片段 } } |
特別注意:
- 只有在需要使用jsr303規范實現的驗證器時,才需要對對象配置@validated,剛剛上面兩種方式并不需要。
- 第一種實現和第二種實現都是實現org.springframework.validation.validator接口,但是前者是針對全局的,后者只針對實現這個接口的配置對象
關于上述兩點,我為啥確定? 來自configurationpropertiesbinder的源碼片段
1
2
3
4
5
6
7
8
9
10
11
12
13
|
private list<validator> getvalidators(bindable<?> target) { list<validator> validators = new arraylist<>( 3 ); if ( this .configurationpropertiesvalidator != null ) { validators.add( this .configurationpropertiesvalidator); } if ( this .jsr303present && target.getannotation(validated. class ) != null ) { validators.add(getjsr303validator()); } if (target.getvalue() != null && target.getvalue().get() instanceof validator) { validators.add((validator) target.getvalue().get()); } return validators; } |
總結
通過上面的例子,我們了解了@configurationproperties的使用以及如何進行驗證,包括屬性驗證器的幾種實現方式.下個章節我會從源碼的角度分析屬性的加載,以及如何解析到bean里面去的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://segmentfault.com/a/1190000016941757