好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring Boot2.0 @ConfigurationProperties使用详解

引言

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的类进行注入,这种方式通常可以用在对第三方类进行配置属性注册

?

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

查看更多关于Spring Boot2.0 @ConfigurationProperties使用详解的详细内容...

  阅读:11次