SpringBoot读取配置文件的几种方式

Spring读取配置文件的几种方法,SpringBoot也都支持。具体查看:https://www.cnblogs.com/myitnews/p/14028588.html

本文主要介绍SpringBoot独有的一种读取方法,使用注解:@ConfigurationProperties。

使用 @Value 注解或者使用 Spring Environment bean 访问这些属性,是这种注入配置方式有时显得很笨重。使用@ConfigurationProperties )来获取这些属性会更灵活。

@ConfigurationProperties 的基本用法非常简单:为每个要捕获的外部属性提供一个带有字段的类。请注意以下几点:

  • 前缀定义了哪些外部属性将绑定到类的字段上
  • 根据 Spring Boot 宽松的绑定规则,类的属性名称必须与外部属性的名称匹配
  • 我们可以简单地用一个值初始化一个字段来定义一个默认值
  • 类本身可以是包私有的
  • 类的字段必须有公共 setter 方法

Spring 宽松绑定规则 (relaxed binding)

Spring使用一些宽松的绑定属性规则。因此,以下变体都将绑定到 hostName 属性上:

mail.hostName=localhost
mail.hostname=localhost
mail.host_name=localhost
mail.host-name=localhost
mail.HOST_NAME=localhost

一、激活@ConfigurationProperties

  • 添加@Component等注组件注解
  • 通过 Spring 的 Java Configuration 特性实现(@Bena)。
  • 使用@EnableConfigurationProperties 注解
    • 该注解中其实是用了@Import(EnableConfigurationPropertiesImportSelector.class) 实现(不推荐)。

二、无法转换的属性和未知的属性

无法转换的属性

如果我们在 application.properties 属性上定义的属性不能被正确的解析会发生什么?默认情况下,Spring Boot 将会启动失败,并抛出异常。

当我们为属性配置错误的值时,而又不希望 Spring Boot 应用启动失败,我们可以设置 ignoreInvalidFields 属性为 true (默认为 false)。

未知的属性

如果我们在 application.properties 文件提供了 MailModuleProperties 类不知道的属性会发生什么?

默认情况下,Spring Boot 会忽略那些不能绑定到 @ConfigurationProperties 类字段的属性。
然而,当配置文件中有一个属性实际上没有绑定到 @ConfigurationProperties 类时,我们可能希望启动失败。也许我们以前使用过这个配置属性,但是它已经被删除了,这种情况我们希望被触发告知手动从 application.properties 删除这个属性。
为了实现上述情况,我们仅需要将 ignoreUnknownFields 属性设置为 false (默认是 true)。

弃用警告⚠️(Deprecation Warning)
ignoreUnknownFields 在未来 Spring Boot 的版本中会被标记为 deprecated,因为我们可能有两个带有 @ConfigurationProperties 的类,同时绑定到了同一个命名空间 (namespace) 上,其中一个类可能知道某个属性,另一个类却不知道某个属性,这样就会导致启动失败

三、启动时校验 @ConfigurationProperties

 如果我们希望配置参数在传入到应用中时有效的,我们可以通过在字段上添加 bean validation 注解,同时在类上添加 @Validated 注解。

应用启动时,我们将会得到 BindValidationException。

当然这些默认的验证注解不能满足你的验证要求,我们也可以自定义注解。

如果你的验证逻辑很特殊,我们可以实现一个方法,并用 @PostConstruct 标记,如果验证失败,方法抛出异常即可。

四、复杂属性类型

多数情况,我们传递给应用的参数是基本的字符串或数字。但是,有时我们需要传递诸如 List 的数据类型。

List 和 Set

我们有两种方式让 Spring Boot 自动填充该 list 属性。

(1) application.properties

在 application.properties 文件中以数组形式书写:

(2) application.yml

YAML 本身支持 list 类型,所以可以在 application.yml 文件中添加:

set 集合也是这种方式的配置方式,不再重复书写。另外YAML 是更好的阅读方式,层次分明,所以在实际应用中更推荐大家使用该种方式做数据配置。

Map<String, String>

SpringBoot也支持Map<String,String>的读取。

1、application.properties配置如下:

fyk.db-script.check-sql.[1-FYK_PROPERTIES-DQL]=select case when exists(select 1 from all_tables t where t.TABLE_NAME = upper('fyk_properties')) then 1 else 0 end as result from dual
fyk.db-script.check-sql.[2-FYK_PROPERTIES-DML-fyk-oauth]=select case when exists(select 1 from fyk_properties t where t.application='fyk-oauth') then 1 else 0 end as result from dual

注意:如果Map类型的key包含非字母数字和-的字符,需要用[]括起来,否则不需要使用中括号。

2、配置类读取如下:

@Component
@ConfigurationProperties(prefix = "fyk.db-script")
public class CheckSqlProperties {
    private Map<String, String> checkSql;

    public Map<String, String> getCheckSql() {
        return checkSql;
    }

    public void setCheckSql(Map<String, String> checkSql) {
        this.checkSql = checkSql;
    }
}

3、扩展:使用@Value的方式获取

要使用@Value的方式获取,首先配置文件中,配置的方式要改下,如下:

fyk.db-script.check-sql={\
  "1-FYK_PROPERTIES-DQL":"select case when exists(select 1 from all_tables t where t.TABLE_NAME = upper('fyk_properties')) then 1 else 0 end as result from dual",\
  "2-FYK_PROPERTIES-DML-fyk-oauth":"select case when exists(select 1 from fyk_properties t where t.application='fyk-oauth') then 1 else 0 end as result from dual"\
  }

注意:如果Map类型的key包含非字母数字和-的字符,需要用引号括起来,否则不需要使用引号(建议都用上引号);value值,都必须要用引号括起来。

在使用该配置的地方,使用@Value的使用获取:

@Value("#{${fyk.db-script.check-sql}}")
private Map<String, String> checkSql
Duration

Spring Boot 内置支持从配置参数中解析 durations (持续时间)。

我们既可以配置毫秒数数值,也可配置带有单位的文本。

配置 duration 不写单位,默认按照毫秒来指定,我们也可已通过 @DurationUnit 来指定单位。

常用单位如下:

  • ns for nanoseconds (纳秒)
  • us for microseconds (微秒)
  • ms for milliseconds (毫秒)
  • s for seconds (秒)
  • m for minutes (分)
  • h for hours (时)
  • d for days (天)
DataSize

与 Duration 的用法一样,默认单位是 byte (字节),可以通过 @DataSizeUnit 单位指定。

添加配置

但是,我测试的时候打印出来结果都是以 B (bytes) 来显示

常见单位如下:

  • B for bytes
  • KB for kilobytes
  • MB for megabytes
  • GB for gigabytes
  • TB for terabytes
自定义类型

有些情况,我们想解析配置参数到我们自定义的对象类型上,假设,我们我们设置最大包裹重量:

在 MailModuleProperties 中添加 Weight 属性

我们可以模仿 DataSize 和 Duration 创造自己的 converter (转换器)

将其注册到 Spring Boot 上下文中

@ConfigurationPropertiesBinding 注解是让 Spring Boot 知道使用该转换器做数据绑定。

五、使用 Spring Boot Configuration Processor 完成自动补全

添加依赖:

重新 build 项目之后,configuration processor 会为我们创建一个 JSON 文件:

这样,当我们在 application.properties 和 application.yml 中写配置的时候会有自动提醒。

六、标记配置属性为 Deprecated

configuration processor 允许我们标记某一个属性为 deprecated

我们可以通过添加 @DeprecatedConfigurationProperty 注解到字段的 getter 方法上,来标示该字段为 deprecated,重新 build 项目,看看 JSON 文件发生了什么?

当我们再编写配置文件时,已经给出了明确 deprecated 提示:

七、总结

Spring Boot 的 @ConfigurationProperties 注解在绑定类型安全的 Java Bean 时是非常强大的,我们可以配合其注解属性和 @DeprecatedConfigurationProperty 注解获取到更友好的编程方式,同时这样让我们的配置更加模块化。

注意:如果使用 SpEL 表达式,我们只能选择 @Value 注解。

 

转自:https://www.cnblogs.com/jimoer/p/11374229.html

 

posted @ 2020-12-01 13:18  codedot  阅读(4290)  评论(0编辑  收藏  举报