Spring Boot2.0 @ConfigurationProperties使用详解

引言

Spring Boot的一个便捷功能是外部化配置,可以轻松访问属性文件中定义的属性。本文将详细介绍@ConfigurationProperties的使用。

配置项目POM

在pom.xml中定义Spring-Boot 为parent

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.4.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

添加依赖

  1. 添加web,因为我们需要使用到JSR-303规范的Validator,如果不想使用web依赖,也可以直接依赖hibernate-validator
  2. 添加spring-boot-configuration-processor,可以在编译时生成属性元数据(spring-configuration-metadata.json).
  3. 添加lombok,可以方便使用注释处理器的功能省去Pojo定义中get set这些麻烦工作.
  <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对象,下面这个文档服务器配置是我假设的,主要是为了演示属性配置的大部分情况

@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注解直接进行注入

@ConfigurationProperties(prefix = "doc")
@Component
public class DocumentServerProperties {
  //代码...
}

使用@EnableConfigurationProperties,通常配置在标有@Configuration的类上,当然其他@Component注解的派生类也可以,不过不推荐.

@ConfigurationProperties(prefix = "doc")
public class DocumentServerProperties {
  //代码...
}
@EnableConfigurationProperties
@Configuration
public class SomeConfiguration {
  private DocumentServerProperties documentServerProperties

  public SomeConfiguration(DocumentServerProperties documentServerProperties) {
    this.documentServerProperties = documentServerProperties;
  }

}

使用@Bean方式在标有@Configuration的类进行注入,这种方式通常可以用在对第三方类进行配置属性注册

@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

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

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注解,使用方式如下片段:

@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,代码如下:

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接口,不过是需要验证的属性配置类本身去实现这个接口

@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的源码片段

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里面去的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring @Configuration和@Component的区别

    Spring @Configuration 和 @Component 区别 一句话概括就是 @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例. 下面看看实现的细节. @Configuration 注解: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration

  • @Configuration与@Component作为配置类的区别详解

    @Configuration注解的类: /** * @Description 测试用的配置类 * @Author 弟中弟 * @CreateTime 2019/6/18 14:35 */ @Configuration public class MyBeanConfig { @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(cou

  • Spring中基于Java的配置@Configuration和@Bean用法详解

    一.首先,需要xml中进行少量的配置来启动Java配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://ww

  • Spring @Bean vs @Service注解区别

    今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式.笔者倾向于使用第一种,即@Configuration和@Bean的组合. 先来看一个例子,目标是创建SearchService的一个Bean. 直接使用@Service的方式: // SearchService.java package li.koly.search; import java.util.List; public in

  • Spring Boot2.0 @ConfigurationProperties使用详解

    引言 Spring Boot的一个便捷功能是外部化配置,可以轻松访问属性文件中定义的属性.本文将详细介绍@ConfigurationProperties的使用. 配置项目POM 在pom.xml中定义Spring-Boot 为parent <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId>

  • Spring MVC的文件下载实例详解

    Spring MVC的文件下载实例详解 读取文件 要下载文件,首先是将文件内容读取进来,使用字节数组存储起来,这里使用spring里面的工具类实现 import org.springframework.util.FileCopyUtils; public byte[] downloadFile(String fileName) { byte[] res = new byte[0]; try { File file = new File(BACKUP_FILE_PATH, fileName); i

  • Dubbo在Spring和Spring Boot中的使用详解

    一.在Spring中使用Dubbo 1.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3.6</version> <exclusions> <exclusion> <groupId>log4j</groupId> <artif

  • spring的IoC和DI详解

    这里先来简单介绍下IoC和DI的区别: IOC:翻译过来是控制反转,将对象的创建权由Spring管理,HelloService不需要自己去创建,Spring可以帮你创建. DI:依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中. 我们现在编写的类是没有其它的属性的,如果你学过UML这种设计的话,面向对象中对象中的几种关系 简单来书,IoC更像是一种思想,DI是一种行为. 另一种说法是,ioc是目的,di是手段.ioc是指让生成类的方式由传统方式(new)反过来,既程序员不调用n

  • Spring Boot 集成MyBatis 教程详解

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 在集成MyBatis前,我们先配置一个druid数据源. Spring Boot 系列 1.Spring Boot 入门 2.Spring Boot 属性配置

  • Spring之ORM模块代码详解

    Spring框架七大模块简单介绍 Spring中MVC模块代码详解 ORM模块对Hibernate.JDO.TopLinkiBatis等ORM框架提供支持 ORM模块依赖于dom4j.jar.antlr.jar等包 在Spring里,Hibernate的资源要交给Spring管理,Hibernate以及其SessionFactory等知识Spring一个特殊的Bean,有Spring负责实例化与销毁.因此DAO层只需要继承HibernateDaoSupport,而不需要与Hibernate的AP

  • Spring中MVC模块代码详解

    SpringMVC的Controller用于处理用户的请求.Controller相当于Struts1里的Action,他们的实现机制.运行原理都类似 Controller是个接口,一般直接继承AbstrcatController,并实现handleRequestInternal方法.handleRequestInternal方法相当于Struts1的execute方法 import org.springframework.web.servlet.ModelAndView; import org.

  • spring boot linux启动方式详解

    前台启动 java -jar XXX.jar 后台启动 java -jar xxx.jar & 区别:前台启动ctrl+c就会关闭程序,后台启动ctrl+c不会关闭程序 制定控制台的标准输出 java -jar xxx.jar > catalina.out 2>&1 & catalina.out将标准输出指向制定文件catalina.out 2>&1 输出所有的日志文件 & 后台启动  脚本启动 #!/bin/sh #功能简介:启动上层目录下的ja

  • spring、mybatis 配置方式详解(常用两种方式)

    在之前的文章中总结了三种方式,但是有两种是注解sql的,这种方式比较混乱所以大家不怎么使用,下面总结一下常用的两种总结方式: 一. 动态代理实现 不用写dao的实现类 这种方式比较简单,不用实现dao层,只需要定义接口就可以了,这里只是为了记录配置文件所以程序写的很简单: 1.整体结构图: 2.三个配置文件以及一个映射文件 (1).程序入口以及前端控制器配置 web.xml <?xml version="1.0" encoding="UTF-8"?> &

  • spring cloud-zuul的Filter使用详解

    在前面我们使用zuul搭建了网关http://www.jb51.net/article/133235.htm 关于网关的作用,这里就不再次赘述了,我们今天的重点是zuul的Filter.通过Filter,我们可以实现安全控制,比如,只有请求参数中有用户名和密码的客户端才能访问服务端的资源.那么如何来实现Filter了? 要想实现Filter,需要以下几个步骤: 1.继承ZuulFilter类,为了验证Filter的特性,我们这里创建3个Filter 根据用户名来过滤 package com.ch

随机推荐