springBoot深度解析-02springboot配置介绍详细版

目录

2. 外化配置

2.1. 访问命令行属性

2.2. JSON 应用程序属性

2.4. 加密属性

2.5. 使用 YAML

2.6. 配置随机值

2.7. 配置系统环境属性

2.8. 类型安全的配置属性


阅读本文更有助于你使用springboot的特性

2. 外化配置

Spring Boot 允许您将配置外部化,以便您可以在不同环境中使用相同的应用程序代码。您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。

属性值可以通过直接注射到你的bean@Value注释,通过Spring的访问Environment抽象,或者被绑定到结构化对象通过@ConfigurationProperties

Spring Boot 使用一个非常特殊的PropertySource顺序,旨在允许合理地覆盖值。属性按以下顺序考虑(来自较低项目的值覆盖较早的项目):

  1. 默认属性(由设置指定SpringApplication.setDefaultProperties)。

  2. @PropertySource你的@Configuration类的注释。请注意,Environment在刷新应用程序上下文之前,不会将此类属性源添加到。现在配置某些属性(例如在刷新开始之前读取的logging.*和)为时已晚spring.main.*

  3. 配置数据(如application.properties文件)。

  4. RandomValuePropertySource,只有在拥有性能random.*

  5. 操作系统环境变量。

  6. Java 系统属性 ( System.getProperties())。

  7. JNDI 属性来自java:comp/env.

  8. ServletContext 初始化参数。

  9. ServletConfig 初始化参数。

  10. 来自SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联 JSON)的属性。

  11. 命令行参数。

  12. properties属性在您的测试中。可用于测试应用程序的特定部分@SpringBootTest测试注释

  13. @TestPropertySource 测试中的注释。

  14. $HOME/.config/spring-boot当 devtools 处于活动状态时,目录中的Devtools 全局设置属性

配置数据文件按以下顺序考虑:

  1. 打包在 jar 中的应用程序属性application.properties和 YAML 变体)。

  2. 打包在 jar 中的特定于配置文件的应用程序属性application-{profile}.properties和 YAML 变体)。

  3. 打包 jar 之外的应用程序属性application.properties和 YAML 变体)。

  4. 打包的 jar(application-{profile}.properties和 YAML 变体)之外的特定于配置文件的应用程序属性

 为了提供一个具体示例,假设您开发了一个@Component使用name属性的 ,如以下示例所示:

@Component
public class MyBean {

    @Value("${name}")
    private String name;
    // ..
}

在您的应用程序类路径上(例如,在您的 jar 中),您可以拥有一个application.properties文件,该文件为name. 在新环境中运行时,application.properties可以在 jar 之外提供一个覆盖name. 对于一次性测试,您可以使用特定的命令行开关(例如,java -jar app.jar --name="Spring")启动。


2.1. 访问命令行属性

默认情况下,SpringApplication将任何命令行选项参数(即以--开头的参数,例如--server.port=9000)转换为一个属性并将它们添加到 Spring Environment。如前所述,命令行属性始终优先于基于文件的属性源。

如果您不希望将命令行属性添加到 中Environment,可以使用在启动类中禁用它们SpringApplication.setAddCommandLineProperties(false)

2.2. JSON 应用程序属性

环境变量和系统属性通常有限制,这意味着某些属性名称不能使用。为了解决这个问题,Spring Boot 允许您将一组属性编码为单个 JSON 结构。

当您的应用程序启动时,任何spring.application.jsonSPRING_APPLICATION_JSON属性将被解析并添加到Environment.

例如,SPRING_APPLICATION_JSON可以在 UN*X shell 的命令行上提供该属性作为环境变量:

$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar

在前面的示例中,您最终my.name=test在 Spring 中Environment

同样的 JSON 也可以作为系统属性提供:

$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar

或者您可以使用命令行参数提供 JSON:

$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'

如果要部署到经典应用程序服务器,还可以使用名为java:comp/env/spring.application.json.

 2.3. 外部应用程序属性

spring开机就会自动查找和加载application.properties和application.yaml文件,应用程序启动时得文件从以下位置加载:

1、classpath/root/config

2、当前目录

        a.当前目录

        b./config当前目录下得子目录

        c.子目录下/config得子目录

该列表按优先级排序(较低项目的值覆盖较早的项目)。来自加载文件的文档被添加PropertySources到 Spring Environment

如果你不喜欢application作为配置文件名,你可以通过指定一个spring.config.name环境属性来切换到另一个文件名。例如,要查找myproject.propertiesmyproject.yaml文件,您可以按如下方式运行您的应用程序:

$ java -jar myproject.jar --spring.config.name=myproject

您还可以使用spring.config.location环境属性来引用显式位置。此属性接受一个或多个要检查的位置的逗号分隔列表。

以下示例显示了如何指定两个不同的文件:

$ java -jar myproject.jar --spring.config.location=\
    optional:classpath:/default.properties,\
    optional:classpath:/override.properties

如果spring.config.location包含目录(而不是文件),它们应该以/. 在运行时,它们将附加spring.config.name在加载之前生成的名称。中指定的文件spring.config.location直接导入。

在大多数情况下,spring.config.location您添加的每个项目都将引用单个文件或目录。位置按照定义的顺序进行处理,后面的位置可以覆盖前面位置的值。

如果您有一个复杂的位置设置,并且您使用特定于配置文件的配置文件,您可能需要提供进一步的提示,以便 Spring Boot 知道它们应该如何分组。位置组是所有被视为同一级别的位置的集合。例如,您可能希望对所有类路径位置进行分组,然后对所有外部位置进行分组。位置组中的项目应以 分隔;。有关更多详细信息,请参阅“配置文件特定文件”部分中的示例。

使用配置的位置spring.config.location替换默认位置。例如,如果spring.config.location配置了 value optional:classpath:/custom-config/,optional:file:./custom-config/,则考虑的完整位置集是:

  1. optional:classpath:custom-config/

  2. optional:file:./custom-config/

如果您更喜欢添加其他位置而不是替换它们,您可以使用spring.config.additional-location. 从其他位置加载的属性可以覆盖默认位置中的属性。例如,如果spring.config.additional-location配置了 value optional:classpath:/custom-config/,optional:file:./custom-config/,则考虑的完整位置集是:

  1. optional:classpath:/;optional:classpath:/config/

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/

  3. optional:classpath:custom-config/

  4. optional:file:./custom-config/

这种搜索顺序允许您在一个配置文件中指定默认值,然后在另一个配置文件中选择性地覆盖这些值。您可以在默认位置之一中为您的应用程序提供默认值application.properties(或您选择的任何其他基本名称spring.config.name)。然后可以在运行时使用位于自定义位置之一的不同文件覆盖这些默认值。

2.3.1. 可选位置

默认情况下,当指定的配置数据位置不存在时,Spring Boot 将抛出 aConfigDataLocationNotFoundException并且您的应用程序将不会启动。

如果要指定位置,但不介意它是否始终存在,则可以使用optional:前缀。您可以将此前缀与spring.config.locationspring.config.additional-location属性以及spring.config.import声明一起使用。

例如,spring.config.importoptional:file:./myconfig.properties允许您的应用程序启动,即使myconfig.properties文件丢失。

如果您想忽略所有ConfigDataLocationNotFoundExceptions并始终继续启动您的应用程序,您可以使用该spring.config.on-not-found属性。将值设置为ignoreusingSpringApplication.setDefaultProperties(…​)或 with 系统/环境变量。

2.3.2. 通配符位置

如果配置文件位置包含*最后一个路径段的字符,则将其视为通配符位置。加载配置时会扩展通配符,以便还检查直接子目录。当有多个配置属性源时,通配符位置在 Kubernetes 等环境中特别有用。

例如,如果您有一些 Redis 配置和一些 MySQL 配置,您可能希望将这两个配置分开,同时要求它们都存在于一个application.properties文件中。这可能会导致两个单独的application.properties文件安装在不同的位置,例如/config/redis/application.properties/config/mysql/application.properties。在这种情况下,通配符位置为config/*/, 将导致两个文件都被处理。

默认情况下,Spring Boot 包含config/*/在默认搜索位置。这意味着/config将搜索 jar 之外目录的所有子目录。

您可以自己将通配符位置与spring.config.locationspring.config.additional-location属性一起使用。

2.3.3. 配置文件特定文件

除了application属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}。例如,如果你的应用程序启动了一个名为轮廓prod,并使用YAML文件,然后双方application.ymlapplication-prod.yml会予以考虑。

特定于配置文件的属性从与标准相同的位置加载application.properties,特定于配置文件的文件始终覆盖非特定文件。如果指定了多个配置文件,则采用最后获胜的策略。例如,如果配置文件prod,livespring.profiles.active属性指定,则 中的值application-prod.properties可以被 中的值覆盖application-live.properties

2.3.4. 导入附加数据

应用程序属性可以使用该spring.config.import属性从其他位置导入更多配置数据。进口在被发现时进行处理,并被视为附加文件,紧接在声明进口的文件之下。

例如,您的类路径application.properties文件中可能包含以下内容:

特性
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties

这将触发dev.properties在当前目录中导入文件(如果存在这样的文件)。导入的值dev.properties将优先于触发导入的文件。在上面的示例中,dev.properties可以重新定义spring.application.name为不同的值。

一个导入无论声明多少次都只会被导入一次。在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。例如,下面的两个示例产生相同的结果:

特性
spring.config.import=my.properties
my.property=value
特性
my.property=value
spring.config.import=my.properties

在上述两个示例中,my.properties文件中的值将优先于触发其导入的文件。

可以在一个spring.config.import键下指定多个位置。位置将按照定义的顺序进行处理,以后的导入优先。

2.3.5. 导入无扩展名文件

某些云平台无法为卷挂载文件添加文件扩展名。要导入这些无扩展名的文件,您需要给 Spring Boot 一个提示,以便它知道如何加载它们。您可以通过将扩展提示放在方括号中来做到这一点。

例如,假设您有一个/etc/config/myconfig要作为 yaml 导入的文件。您可以application.properties使用以下方法导入它:

spring.config.import=file:/etc/config/myconfig[.yaml]

2.3.6. 使用配置树

在云平台(例如 Kubernetes)上运行应用程序时,您通常需要读取平台提供的配置值。出于此类目的使用环境变量的情况并不少见,但这可能有缺点,尤其是在值应该保密的情况下。

作为环境变量的替代方案,许多云平台现在允许您将配置映射到安装的数据卷中。例如,Kubernetes 可以卷挂载ConfigMapsSecrets.

可以使用两种常见的卷安装模式:

  1. 单个文件包含一组完整的属性(通常编写为 YAML)。

  2. 多个文件被写入目录树,文件名成为“键”,内容成为“值”。

对于第一种情况,你可以直接导入使用YAML或属性文件中spring.config.import所描述的以上。对于第二种情况,您需要使用configtree:前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。

例如,让我们假设 Kubernetes 已经挂载了以下卷:

etc/
  config/
    myapp/
      username
      password

username文件的内容将是一个配置值,而 的内容password将是一个秘密。

要导入这些属性,您可以将以下内容添加到您的application.propertiesapplication.yaml文件中:

spring.config.import=optional:configtree:/etc/config/

然后,您可以以通常的方式访问或注入myapp.usernamemyapp.password属性Environment

如果您有多个配置树要从同一个父文件夹导入,您可以使用通配符快捷方式。configtree:以 结尾的任何位置/*/都会将所有直接子项导入为配置树。

例如,给定以下体积:

etc/
  config/
    dbconfig/
      db/
        username
        password
    mqconfig/
      mq/
        username
        password

您可以configtree:/etc/config/*/用作导入位置:

spring.config.import=optional:configtree:/etc/config/*/

这将增加db.usernamedb.passwordmq.usernamemq.password属性。

配置树也可用于 Docker 机密。当 Docker swarm 服务被授予访问机密的权限时,机密会被挂载到容器中。例如,如果db.password在 location 挂载了一个名为的秘密,则/run/secrets/可以db.password使用以下命令将其提供给 Spring 环境:

spring.config.import=optional:configtree:/run/secrets/

2.3.7. 属性占位符

application.propertiesapplication.yml中的值在Environment使用时通过现有值进行过滤,因此您可以参考以前定义的值(例如,来自系统属性)。标准${name}属性占位符语法可用于值内的任何地方。

例如,以下文件将设置app.description为“MyApp is a Spring Boot application”:

app.name=MyApp
app.description=${app.name} is a Spring Boot application


2.3.8. 处理多文档文件

Spring Boot 允许您将单个物理文件拆分为多个独立添加的逻辑文档。文档按顺序处理,从上到下。后面的文档可以覆盖在前面的文档中定义的属性。

对于application.yml文件,使用标准的 YAML 多文档语法。三个连续的连字符代表一个文档的结束和下一个文档的开始。

例如,以下文件有两个逻辑文档:

spring:
  application:
    name: MyApp
---
spring:
  application:
    name: MyCloudApp
  config:
    activate:
      on-cloud-platform: kubernetes

对于application.properties文件,使用特殊#---注释来标记文档拆分:

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes

2.3.9. 激活属性

有时仅在满足某些条件时激活给定的属性 get 很有用。例如,您可能拥有仅在特定配置文件处于活动状态时才相关的属性。

您可以使用 有条件地激活属性文档spring.config.activate.*

以下激活属性可用:

表 2. 激活属性
财产笔记

on-profile

必须匹配才能使文档处于活动状态的配置文件表达式。

on-cloud-platform

CloudPlatform必须对文件进行检测活跃。

 例如,以下指定第二个文档仅在 Kubernetes 上运行时才处于活动状态,并且仅当“prod”或“staging”配置文件处于活动状态时:

myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set

2.4. 加密属性

Spring Boot 不提供任何对加密属性值的内置支持,但是,它提供了修改 Spring 中包含的值所需的挂钩点Environment。该EnvironmentPostProcessor界面允许您Environment在应用程序启动之前进行操作

2.5. 使用 YAML

YAML是 JSON 的超集,因此是一种用于指定分层配置数据的便捷格式。该SpringApplication级自动支持YAML来替代,只要你有属性SnakeYAML在classpath库

2.5.1. 将 YAML 映射到属性

yaml 文档需要从其分层格式转换为可与 Spring 一起使用的平面结构Environment。例如,考虑以下 YAML 文档:

environments:
  dev:
    url: https://dev.example.com
    name: Developer Setup
  prod:
    url: https://another.example.com
    name: My Cool App

为了从文件中访问这些属性,它们将被展平如下:

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

同样,YAML 列表也需要扁平化。它们表示为带有[index]解引用器的属性键。例如,考虑以下 YAML

my:
 servers:
 - dev.example.com
 - another.example.com

前面的示例将转换为以下属性:

my.servers[0]=dev.example.com
my.servers[1]=another.example.com

无法使用@PropertySource@TestPropertySource注释加载 YAML 文件。因此,如果您需要以这种方式加载值,则需要使用.properties文件。

2.5.2. 直接加载 YAML

Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。该YamlPropertiesFactoryBean负载YAML作为PropertiesYamlMapFactoryBean负载YAML作为Map

YamlPropertySourceLoader如果要将 YAML 作为 Spring 加载,也可以使用该类PropertySource


2.6. 配置随机值

RandomValuePropertySource对于注入随机值很有用(例如,注入机密或测试用例)。它可以生成整数、长整数、uuid 或字符串,如以下示例所示:

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}

random.int*语法是OPEN value (,max) CLOSE其中的OPEN,CLOSE任何字符和value,max是整数。如果max提供,则value是最小值和max最大值(不包括)。

2.7. 配置系统环境属性

Spring Boot 支持为环境属性设置前缀。如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将非常有用。系统环境属性的前缀可以直接设置在SpringApplication.

例如,如果您将前缀设置为input,则诸如在系统环境中的属性remote.timeout也将被解析input.remote.timeout


2.8. 类型安全的配置属性

使用@Value("${property}")注解注入配置属性有时会很麻烦,尤其是当您使用多个属性或您的数据本质上是分层的时。Spring Boot 提供了一种处理属性的替代方法,它让强类型 bean 管理和验证应用程序的配置

2.8.1. JavaBean 属性绑定

可以绑定声明标准 JavaBean 属性的 bean,如以下示例所示:

@ConfigurationProperties("my.service")
public class MyProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    // getters / setters...

    public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        // getters / setters...

    }

}

前面的 POJO 定义了以下属性:

  • my.service.enabledfalse默认值为。

  • my.service.remote-address, 类型可以从String.

  • my.service.security.username,带有一个嵌套的“安全”对象,其名称由属性的名称决定。特别是,该类型根本没有在那里使用,本来可以使用SecurityProperties.

  • my.service.security.password.

  • my.service.security.roles, 的集合String默认为USER.

 映射到@ConfigurationPropertiesSpring Boot 中可用类的属性,通过属性文件、YAML 文件、环境变量和其他机制配置,是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用.

这种安排依赖于默认的空构造函数,并且 getter 和 setter 通常是强制性的,因为绑定是通过标准的 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。在以下情况下可以省略 setter:

  • 映射,只要它们被初始化,就需要一个 getter,但不一定是一个 setter,因为它们可以被绑定器改变。

  • 可以通过索引(通常使用 YAML)或使用单个逗号分隔值(属性)来访问集合和数组。在后一种情况下,setter 是强制性的。我们建议始终为此类类型添加 setter。如果您初始化一个集合,请确保它不是不可变的(如前面的示例所示)。

  • 如果初始化嵌套的 POJO 属性(如Security前面示例中的字段),则不需要设置器。如果您希望活页夹使用其默认构造函数动态创建实例,则需要一个 setter。

有些人使用 Project Lombok 自动添加 getter 和 setter。确保 Lombok 不会为此类类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。

最后,仅考虑标准 Java Bean 属性,不支持静态属性绑定。

2.8.2. 构造函数绑定

上一节中的示例可以以不可变的方式重写,如下例所示:

@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {

    // fields...

    public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    // getters...

    public static class Security {

        // fields...

        public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        // getters...

    }

}

 在此设置中,@ConstructorBinding注释用于指示应使用构造函数绑定。这意味着绑定器将期望找到一个带有您希望绑定的参数的构造函数。如果您使用的是 Java 16 或更高版本,则构造函数绑定可以与记录一起使用。在这种情况下,除非您的记录有多个构造函数,否则不需要使用@ConstructorBinding.

类的嵌套成员@ConstructorBinding(例如Security在上面的示例中)也将通过它们的构造函数绑定。

可以使用指定默认值,@DefaultValue并且将应用相同的转换服务将String值强制转换为缺失属性的目标类型。默认情况下,如果没有绑定到 的属性Security,则MyProperties实例将包含 的nullsecurity。如果您希望Security即使在没有属性绑定到它的情况下也返回一个非空实例,您可以使用空@DefaultValue注释来执行此操作:

public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
    this.enabled = enabled;
    this.remoteAddress = remoteAddress;
    this.security = security;
}

2.8.3. 启用@ConfigurationProperties 注释类型

Spring Boot 提供基础结构来绑定@ConfigurationProperties类型并将它们注册为 bean。您可以在逐个类的基础上启用配置属性,也可以启用以与组件扫描类似的方式工作的配置属性扫描。

有时,带有注释的类@ConfigurationProperties可能不适合扫描,例如,如果您正在开发自己的自动配置或者您想有条件地启用它们。在这些情况下,请使用@EnableConfigurationProperties注释指定要处理的类型列表。这可以在任何@Configuration类上完成,如以下示例所示:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {

}

要使用配置属性扫描,请将@ConfigurationPropertiesScan注释添加到您的应用程序。通常,它被添加到带有注释的主应用程序类中,@SpringBootApplication但它可以添加到任何@Configuration类中。默认情况下,将从声明注释的类的包中进行扫描。如果要定义要扫描的特定包,可以按照以下示例进行操作:

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {

}

@ConfigurationProperties使用配置属性扫描或 through 注册 bean 时@EnableConfigurationProperties,bean 有一个约定的名称:<prefix>-<fqn>,其中<prefix>@ConfigurationProperties注解中指定的环境键前缀,<fqn>是 bean 的完全限定名称。如果注释不提供任何前缀,则仅使用 bean 的完全限定名称。

上面示例中的 bean 名称是com.example.app-com.example.app.SomeProperties.

 我们建议@ConfigurationProperties只处理环境,特别是不要从上下文中注入其他 bean。对于极端情况,可以使用 setter 注入或*Aware框架提供的任何接口(例如,EnvironmentAware如果您需要访问Environment)。如果您仍想使用构造函数注入其他 bean,则必须@Component使用基于 JavaBean 的属性绑定来注释和使用配置属性 bean 

2.8.4. 使用@ConfigurationProperties 注释类型

这种配置风格特别适用于SpringApplication外部 YAML 配置,如以下示例所示:

my:
  service:
    remote-address: 192.168.1.1
    security:
      username: admin
      roles:
      - USER
      - ADMIN

要使用@ConfigurationPropertiesbean,您可以以与任何其他 bean 相同的方式注入它们,如以下示例所示:

@Service
public class MyService {

    private final SomeProperties properties;

    public MyService(SomeProperties properties) {
        this.properties = properties;
    }

    public void openConnection() {
        Server server = new Server(this.properties.getRemoteAddress());
        server.start();
        // ...
    }

    // ...

}

2.8.5. 第三方配置

除了@ConfigurationProperties用于注释类之外,您还可以在公共@Bean方法上使用它。当您想要将属性绑定到您无法控制的第三方组件时,这样做会特别有用。

要从Environment属性配置 bean ,请添加@ConfigurationProperties到其 bean 注册中,如以下示例所示:

@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "another")
    public AnotherComponent anotherComponent() {
        return new AnotherComponent();
    }

}

使用another前缀定义的任何 JavaBean 属性都AnotherComponent以类似于前面SomeProperties示例的方式映射到该bean 。

2.8.6. 松弛绑定

Spring Boot 使用一些宽松的规则将Environment属性绑定到@ConfigurationPropertiesbean,因此Environment属性名称和 bean 属性名称之间不需要完全匹配。这很有用的常见示例包括以破折号分隔的环境属性(例如,context-path绑定到contextPath)和大写的环境属性(例如,PORT绑定到port)。

例如,考虑以下@ConfigurationProperties类:

@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {

    private String firstName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

使用前面的代码,可以使用以下属性名称:

表 3. 宽松绑定
财产笔记

my.main-project.person.first-name

烤肉盒,推荐用于.properties.yml文件。

my.main-project.person.firstName

标准的驼峰式语法。

my.main-project.person.first_name

下划线表示法,这是在.properties.yml文件中使用的替代格式。

MY_MAINPROJECT_PERSON_FIRSTNAME

大写格式,在使用系统环境变量时推荐使用。

表 4. 每个属性源的宽松绑定规则
物业来源简单的列表

属性文件

Camel case、kebab case 或下划线符号

使用[ ]或逗号分隔值的标准列表语法

YAML 文件

Camel case、kebab case 或下划线符号

标准 YAML 列表语法或逗号分隔值

环境变量

下划线作为分隔符的大写格式(请参阅从环境变量绑定)。

由下划线包围的数值(请参阅从环境变量绑定

系统属性

Camel case、kebab case 或下划线符号

使用[ ]或逗号分隔值的标准列表语法

绑定map

绑定到Map属性时,您可能需要使用特殊的括号表示法,以便key保留原始值。如果键没有被 包围[],则任何非字母数字字符-或被.删除。

例如,考虑将以下属性绑定到 a Map<String,String>

my.map.[/key1]=value1
my.map.[/key2]=value2
my.map./key3=value3

上面的属性将绑定到Mapwith /key1/key2andkey3作为地图中的键。斜线已被删除,key3因为它没有被方括号包围。

如果您key包含 a.并且您绑定到非标量值,您可能偶尔也需要使用括号表示法。例如,绑定a.b=cMap<String, Object>将返回带有条目的 Map{"a"={"b"="c"}}[a.b]=c将返回带有条目的 Map {"a.b"="c"}

从环境变量绑定

大多数操作系统对可用于环境变量的名称施加了严格的规则。例如,Linux shell 变量只能包含字母(atozAto Z)、数字(0to 9)或下划线字符(_)。按照惯例,Unix shell 变量的名称也为大写。

Spring Boot 宽松的绑定规则是为了兼容这些命名限制而设计的。

要将规范形式的属性名称转换为环境变量名称,您可以遵循以下规则:

  • 将点 ( .)替换为下划线 ( _)。

  • 删除所有破折号 ( -)。

  • 转换为大写。

例如,配置属性spring.main.log-startup-info将是一个名为 的环境变量SPRING_MAIN_LOGSTARTUPINFO

绑定到对象列表时也可以使用环境变量。要绑定到 a List,元素编号应在变量名称中用下划线括起来。

例如,配置属性my.service[0].other将使用名为 的环境变量MY_SERVICE_0_OTHER

2.8.7. 合并复杂类型

当列表在多个地方配置时,覆盖通过替换整个列表来工作。

例如,假设一个MyPojo对象具有默认的namedescription属性null。以下示例公开了MyPojo来自的对象列表MyProperties

@ConfigurationProperties("my")
public class MyProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

考虑以下配置:

my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name

如果dev配置文件未激活,则MyProperties.list包含一个MyPojo条目,如先前定义的那样。dev但是,如果配置文件已启用,则该配置文件list 仅包含一个条目(名称为my another name和描述为null)。此配置不会将第二个MyPojo实例添加到列表中,也不会合并项目。

List在多个配置文件中指定了a 时,使用具有最高优先级(并且只有那个)的那个。考虑以下示例:

my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name

在前面的示例中,如果dev配置文件处于活动状态,则MyProperties.list包含一个 MyPojo条目(名称为my another name,描述为null)。对于 YAML,逗号分隔列表和 YAML 列表均可用于完全覆盖列表的内容。

对于Map属性,您可以绑定来自多个来源的属性值。但是,对于多个来源中的同一属性,使用优先级最高的那个。以下示例公开了Map<String, MyPojo>from MyProperties

@ConfigurationProperties("my")
public class MyProperties {

    private final Map<String, MyPojo> map = new LinkedHashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }

}

考虑以下配置:

my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2

如果dev配置文件未激活,则MyProperties.map包含一个带键的条目key1(名称为my name 1,描述为my description 1)。dev但是,如果配置文件已启用,则map包含两个带有键的条目key1(名称为dev name 1,描述为my description 1)和key2(名称为dev name 2,描述为dev description 2)。

2.8.8. 属性转换

Spring Boot 在绑定到@ConfigurationPropertiesbean时尝试将外部应用程序属性强制为正确的类型。如果您需要自定义类型转换,您可以提供一个ConversionServicebean(带有一个名为 的 bean conversionService)或自定义属性编辑器(通过一个CustomEditorConfigurerbean)或自定义Converters(带有注释为 的 bean 定义@ConfigurationPropertiesBinding)。

由于在应用程序生命周期的早期请求此 bean,因此请确保限制您ConversionService正在使用的依赖项。通常,您需要的任何依赖项在创建时可能未完全初始化。您可能需要重命名您的自定义ConversionService如果不需要配置键强制它只有依靠合格的自定义转换器@ConfigurationPropertiesBinding

转换持续时间

Spring Boot 专门支持表达持续时间。如果公开java.time.Duration属性,则应用程序属性中的以下格式可用:

  • 常规long表示(使用毫秒作为默认单位,除非@DurationUnit指定了 a)

  • 标准的ISO-8601格式使用java.time.Duration

  • 一种更易读的格式,其中值和单位耦合(10s表示 10 秒)

考虑以下示例:

@ConfigurationProperties("my")
public class MyProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    private Duration sessionTimeout = Duration.ofSeconds(30);

    private Duration readTimeout = Duration.ofMillis(1000);

    // getters / setters...

}

要将会话超时指定为 30 秒30PT30S30s都是等效的。500ms 的读取超时可以指定为以下任何形式:500,PT0.5S500ms

您还可以使用任何受支持的单位。这些是:

  • ns 纳秒

  • us 微秒

  • ms 毫秒

  • s 几秒钟

  • m 几分钟

  • h 用了几个小时

  • d 持续数天

默认单位是毫秒,可以使用@DurationUnit上面示例中所示的方法覆盖。

如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:

@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {

    // fields...

    public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
            @DefaultValue("1000ms") Duration readTimeout) {
        this.sessionTimeout = sessionTimeout;
        this.readTimeout = readTimeout;
    }

    // getters...

}

转换期

除了持续时间之外,Spring Boot 还可以使用java.time.Period类型。可以在应用程序属性中使用以下格式:

  • 常规int表示(使用天作为默认单位,除非@PeriodUnit指定了 a)

  • 标准的ISO-8601格式使用java.time.Period

  • 一种更简单的格式,其中值和单位对耦合(1y3d表示 1 年零 3 天)

简单格式支持以下单位:

  • y 多年

  • m 几个月

  • w 数周

  • d 持续数天

转换数据大小

Spring Framework 具有DataSize以字节为单位表示大小的值类型。如果公开DataSize属性,则应用程序属性中的以下格式可用:

  • 常规long表示(使用字节作为默认单位,除非@DataSizeUnit指定了 a)

  • 一种更易读的格式,其中值和单位耦合(10MB表示 10 兆字节)

考虑以下示例:

@ConfigurationProperties("my")
public class MyProperties {

    @DataSizeUnit(DataUnit.MEGABYTES)
    private DataSize bufferSize = DataSize.ofMegabytes(2);

    private DataSize sizeThreshold = DataSize.ofBytes(512);

    // getters/setters...

}

指定缓冲区大小为 10 兆字节,10并且10MB是等效的。256 字节的大小阈值可以指定为256256B

您还可以使用任何受支持的单位。这些是:

  • B 对于字节

  • KB 千字节

  • MB 兆字节

  • GB 千兆字节

  • TB TB 级

默认单位是字节,可以使用@DataSizeUnit如上例所示覆盖。

如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:

@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {

    // fields...

    public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
            @DefaultValue("512B") DataSize sizeThreshold) {
        this.bufferSize = bufferSize;
        this.sizeThreshold = sizeThreshold;
    }

    // getters...

}

2.8.9. @ConfigurationProperties 验证

@ConfigurationProperties每当使用 Spring 的@Validated注解进行注解时,Spring Boot 都会尝试验证类。您可以javax.validation直接在配置类上使用 JSR-303约束注释。为此,请确保您的类路径上有一个兼容的 JSR-303 实现,然后向您的字段添加约束注释,如以下示例所示:

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    // getters/setters...

}

为确保始终为嵌套属性触发验证,即使未找到任何属性,关联字段也必须使用@Valid. 以下示例建立在前面的MyProperties示例之上:

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // getters/setters...

    public static class Security {

        @NotEmpty
        private String username;

        // getters/setters...

    }

}

您还可以Validator通过创建一个名为 的 bean 定义来添加自定义 Spring configurationPropertiesValidator。该@Bean方法应该被声明static。配置属性验证器是在应用程序生命周期的早期创建的,将@Bean方法声明为静态方法可以创建 bean,而无需实例化@Configuration类。这样做可以避免早期实例化可能导致的任何问题。

2.8.10. @ConfigurationProperties 与 @Value

@Value注释是核心容器的功能,和它不提供相同的功能,类型安全配置属性。下表总结了@ConfigurationProperties和支持的功能@Value

特征@ConfigurationProperties@Value

Relaxed binding(松弛绑定)

支持

Limited (see note below)

元数据支持

支持

No

SpEL evaluation

支持

Yes

如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个用@ConfigurationProperties. 这样做将为您提供结构化、类型安全的对象,您可以将其注入到您自己的 bean 中。

SpEL在解析这些文件和填充环境时,不会处理来自应用程序属性文件的表达式。但是,可以在 中编写SpEL表达式@Value。如果应用程序属性文件中的属性值是一个SpEL表达式,则在通过@Value.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂攻城师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值