1.介绍
Spring Boot具有许多有用的功能,包括外部化配置和轻松访问属性文件中定义的属性。
2.简单的Properties
官方文档建议将配置属性隔离到单独的POJO中。
因此,这么做:
@Data
@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
}
@Configuration,以便Spring在应用程序上下文中创建一个Spring bean。
@ConfigurationProperties与所有具有相同前缀的分层属性一起使用效果最佳; 因此,添加了一个mail前缀。
Spring框架使用标准的Java bean设置器,因此我们必须为每个属性声明设置器。
注意:如果不在POJO中使用@Configuration,那么需要在主Spring应用程序类中添加@EnableConfigurationProperties(ConfigProperties.class)来将属性绑定到POJO中:
@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Spring将自动绑定属性文件中定义的任何属性,该属性文件中带有前缀mail与ConfigProperties类中的字段之一相同。
Spring使用一些宽松的规则来绑定属性。 结果,以下变体都绑定到属性hostName:
mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME
因此,可以使用以下属性文件来设置所有字段:
#Simple properties
mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com
2.1. Spring Boot 2.2
从Spring Boot 2.2开始,Spring通过类路径扫描查找并注册@ConfigurationProperties类。 因此,无需使用@Component(和其他元注释,如@Configuration)注释此类,甚至无需使用@EnableConfigurationProperties:

@Data
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
}
@SpringBootApplication启用的类路径扫描程序会找到ConfigProperties类,即使没有使用@Component对该类进行注释也是如此。
此外,可以使用@ConfigurationPropertiesScan批注来扫描配置属性类的自定义位置:
@SpringBootApplication
@ConfigurationPropertiesScan("com.example.demo.properties")
public class DemoApplication implements ApplicationRunner {
@Resource
private ConfigProperties configProperties;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(configProperties);
}
}
这样,Spring将仅在com.example.demo.properties包中查找配置属性类。
3.嵌套Properties
可以在List,Map和类中嵌套属性。
创建一个新的Credentials类用于一些嵌套属性:
@Data
public class Credentials {
private String authMethod;
private String username;
private String password;
}
我们还需要更新ConfigProperties类以使用List,Map和Credentials类:
@Data
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostname;
private int port;
private String from;
private List<String> defaultRecipients;
private Map<String, String> additionalHeaders;
private Credentials credentials;
}
以下属性文件将设置所有字段:
#Simple properties
[email protected]
mail.port=9000
[email protected]
#List properties
mail.defaultRecipients[0][email protected]
mail.defaultRecipients[1][email protected]
#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
打印结果:
ConfigProperties(host=null, port=9000, [email protected], defaultRecipients=[[email protected], [email protected]], additionalHeaders={redelivery=true, secure=true}, credentials=Credentials(authMethod=SHA1, username=john, password=password))
4.在@Bean方法上使用@ConfigurationProperties
还可以在@Bean注释的方法上使用@ConfigurationProperties注释。
当要将属性绑定到控制范围之外的第三方组件时,此方法可能特别有用。
创建一个简单的Item类,将在下一个示例中使用它:
@Configuration
public class ConfigPropertiesV2 {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
item.name=apple
item.size=100
任何带有项目前缀的属性都将映射到Spring上下文管理的Item实例。
5.Properties校验
引入依赖
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
@ConfigurationProperties使用JSR-303格式提供属性验证。
@Data
@ConfigurationProperties(prefix = "mail")
@Configuration
@Validated
public class ConfigProperties {
@NotBlank
private String hostname;
@Min(1025)
@Max(65536)
private int port;
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
private List<String> defaultRecipients;
private Map<String, String> additionalHeaders;
private Credentials credentials;
}
这有助于减少代码中的if-else条件,并使它看起来更加简洁明了。
如果这些验证中的任何一个失败,则主应用程序将无法以IllegalStateException启动。
Hibernate Validation框架使用标准的Java bean的getter和setter,因此对每个属性声明getter和setter很重要。
6.属性转化
@ConfigurationProperties支持将属性绑定到其对应bean的多种类型的转换。
6.1. Duration
从查看将属性转换为Duration对象开始。
在这里,有两个类型为Duration的字段:
@Data
@ConfigurationProperties(prefix = "conversion")
@Configuration
public class PropertyConversion {
private Duration timeInDefaultUnit;
private Duration timeInNano;
}
properties文件
conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns
结果,字段timeInDefaultUnit的值为10毫秒,而timeInNano字段的值为9纳秒。
支持的单位分别为ns,us,ms,s,m,h和d,分别为纳秒,微秒,毫秒,秒,分钟,小时和天。
默认单位是毫秒,这意味着如果我们不指定数值旁边的单位,Spring会将值转换为毫秒。
也可以使用@DurationUnit覆盖默认单位:
@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;
conversion.timeInDays=2
6.2. DataSize
同样,Spring Boot @ConfigurationProperties支持DataSize类型转换。
private DataSize sizeInDefaultUnit;
private DataSize sizeInGB;
@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;
这些是相应的属性:
conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4
在这种情况下,sizeInDefaultUnit的值为300个字节,因为默认单位为字节。
支持的单位是B,KB,MB,GB和TB。 还可以使用@DataSizeUnit覆盖默认单位。