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
mail.hostname=mailer@mail.com
mail.port=9000
mail.from=mailer@mail.com

#List properties
mail.defaultRecipients[0]=admin@mail.com
mail.defaultRecipients[1]=owner@mail.com

#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, from=mailer@mail.com, defaultRecipients=[admin@mail.com, owner@mail.com], 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覆盖默认单位。

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐