Spring Boot的一个便捷功能是外部化配置,能够轻松访问属性文件中定义的属性。本文将详细介绍@ConfigurationProperties的使用。java
<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
<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对象,下面这个文档服务器配置是我假设的,主要是为了演示属性配置的大部分状况spring
@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配置注入的三种方式.json
@ConfigurationProperties(prefix = "doc") @Component public class DocumentServerProperties { //代码... }
@ConfigurationProperties(prefix = "doc") public class DocumentServerProperties { //代码... }
@EnableConfigurationProperties @Configuration public class SomeConfiguration { private DocumentServerProperties documentServerProperties public SomeConfiguration(DocumentServerProperties documentServerProperties) { this.documentServerProperties = documentServerProperties; } }
@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两种格式,针对上面的配置对象分别写了两种格式的配置文件例子.服务器
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
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等。ide
下面咱们利用JSR303规范的实现对DocumentServerProperties属性配置类,添加一些常规验证,好比Null检查、数字校验等操做,spring-boot
须要注意在Spring-Boot 2.0版本之后,若是使用JSR303对属性配置进行验证必须添加@Validated注解,使用方式以下片断:ui
@ConfigurationProperties(prefix = "doc") @Validated public class DocumentServerProperties { @NotNull // 判断不为空的状况 private String remoteAddress; //限制端口只能是80-65536之间 @Min(80) @Max(65536) private int port; //其余代码 }
在有些数状况下,咱们但愿自定义验证器,有两种方式能够进行实现this
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 ); } } }
@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) { //判断逻辑其实能够参照上面的代码片断 } }
特别注意:spa
关于上述两点,我为啥肯定? 来自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里面去的。