对于最新的稳定版本,请使用 Spring Boot 3.5.5spring-doc.cadn.net.cn

外部化配置

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

属性值可以通过使用@Value注释,通过 Spring 的Environment抽象,或者通过@ConfigurationProperties.spring-doc.cadn.net.cn

Spring Boot 使用非常特殊的PropertySourceorder 的命令,旨在允许合理地覆盖值。 较高的属性源可以覆盖较早的属性源中定义的值。spring-doc.cadn.net.cn

按以下顺序考虑来源:spring-doc.cadn.net.cn

  1. 默认属性(通过设置SpringApplication.setDefaultProperties(Map)).spring-doc.cadn.net.cn

  2. @PropertySource注释@Configuration类。 请注意,此类属性源不会添加到Environment直到刷新应用程序上下文。 这为时已晚,无法配置某些属性,例如logging.*spring.main.*在刷新开始之前读取。spring-doc.cadn.net.cn

  3. 配置数据(例如application.properties文件)。spring-doc.cadn.net.cn

  4. 一个RandomValuePropertySource仅在random.*.spring-doc.cadn.net.cn

  5. 作系统环境变量。spring-doc.cadn.net.cn

  6. Java 系统属性 (System.getProperties()).spring-doc.cadn.net.cn

  7. JNDI 属性java:comp/env.spring-doc.cadn.net.cn

  8. ServletContextinit 参数。spring-doc.cadn.net.cn

  9. ServletConfiginit 参数。spring-doc.cadn.net.cn

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

  11. 命令行参数。spring-doc.cadn.net.cn

  12. properties属性。 适用于@SpringBootTest以及用于测试应用程序特定切片的测试注释spring-doc.cadn.net.cn

  13. @DynamicPropertySource测试中的注释。spring-doc.cadn.net.cn

  14. @TestPropertySource测试上的注释。spring-doc.cadn.net.cn

  15. Devtools 全局设置属性中的$HOME/.config/spring-boot目录。spring-doc.cadn.net.cn

配置文件按以下顺序考虑:spring-doc.cadn.net.cn

  1. 打包在 jar 中的应用程序属性application.properties和 YAML 变体)。spring-doc.cadn.net.cn

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

  3. 打包 jar 外部的应用程序属性application.properties和 YAML 变体)。spring-doc.cadn.net.cn

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

建议对整个应用程序坚持使用一种格式。 如果您有包含两者的配置文件.properties和 YAML 格式在同一位置,.properties优先。
如果使用环境变量而不是系统属性,则大多数作系统不允许使用以句点分隔的键名,但可以改用下划线(例如,SPRING_CONFIG_NAME而不是spring.config.name). 有关详细信息,请参阅从环境变量绑定。
如果您的应用程序在 Servlet 容器或应用程序服务器中运行,那么 JNDI 属性(在java:comp/env) 或 servlet 上下文初始化参数可以代替环境变量或系统属性,或者与环境变量或系统属性一起使用。

为了提供一个具体的例子,假设您开发了一个@Component使用name属性,如以下示例所示:spring-doc.cadn.net.cn

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

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

	// ...

}
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class MyBean {

	@Value("\${name}")
	private val name: String? = null

	// ...

}

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

envconfigprops终结点可用于确定属性具有特定值的原因。 可以使用这两个终结点来诊断意外的属性值。 有关详细信息,请参阅生产就绪功能部分。

访问命令行属性

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

如果您不希望将命令行属性添加到Environment,您可以使用以下命令禁用它们SpringApplication.setAddCommandLineProperties(false).spring-doc.cadn.net.cn

JSON 应用程序属性

环境变量和系统属性通常具有限制,这意味着某些属性名称无法使用。 为了帮助解决这个问题,Spring Boot 允许您将属性块编码为单个 JSON 结构。spring-doc.cadn.net.cn

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

例如,SPRING_APPLICATION_JSON属性可以在 UN*X shell 的命令行中作为环境变量提供:spring-doc.cadn.net.cn

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

在前面的示例中,您最终会遇到my.name=test在SpringEnvironment.spring-doc.cadn.net.cn

也可以将相同的 JSON 作为系统属性提供:spring-doc.cadn.net.cn

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

或者,您可以使用命令行参数提供 JSON:spring-doc.cadn.net.cn

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

如果您要部署到经典的 Application Server,您还可以使用名为java:comp/env/spring.application.json.spring-doc.cadn.net.cn

虽然nullJSON 中的值将添加到生成的属性源中,PropertySourcesPropertyResolver对待null属性作为缺失值。这意味着 JSON 无法使用null价值。

外部应用程序属性

Spring Boot 将自动查找并加载application.propertiesapplication.yaml应用程序启动时从以下位置发送的文件:spring-doc.cadn.net.cn

  1. 从类路径spring-doc.cadn.net.cn

    1. 类路径根spring-doc.cadn.net.cn

    2. 类路径/configspring-doc.cadn.net.cn

  2. 从当前目录spring-doc.cadn.net.cn

    1. 当前目录spring-doc.cadn.net.cn

    2. config/子目录spring-doc.cadn.net.cn

    3. 的直接子目录config/子目录spring-doc.cadn.net.cn

该列表按优先级排序(较低项的值覆盖较早的项)。 加载文件中的文档将添加为PropertySource实例到 SpringEnvironment.spring-doc.cadn.net.cn

如果你不喜欢application作为配置文件名,您可以通过指定spring.config.nameenvironment 属性。 例如,要查找myproject.propertiesmyproject.yaml文件,您可以按如下方式运行您的应用程序:spring-doc.cadn.net.cn

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

您还可以使用spring.config.locationenvironment 属性。 此属性接受一个或多个要检查的位置的逗号分隔列表。spring-doc.cadn.net.cn

以下示例演示如何指定两个不同的文件:spring-doc.cadn.net.cn

$ java -jar myproject.jar --spring.config.location=\
	optional:classpath:/default.properties,\
	optional:classpath:/override.properties
使用前缀optional:如果位置是可选的,并且您不介意它们是否存在。
spring.config.name,spring.config.locationspring.config.additional-location很早就用于确定必须加载哪些文件。 它们必须定义为环境属性(通常是作系统环境变量、系统属性或命令行参数)。

如果spring.config.location包含目录(与文件相反),它们应该以 结尾。 在运行时,它们将附加从/spring.config.name在加载之前。 中指定的文件spring.config.location直接导入。spring-doc.cadn.net.cn

目录和文件位置值也会展开,以检查特定于配置文件的文件。 例如,如果您有spring.config.locationclasspath:myconfig.properties,您还会发现合适的classpath:myconfig-<profile>.properties文件已加载。

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

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

使用spring.config.location替换默认位置。 例如,如果spring.config.location配置为optional:classpath:/custom-config/,optional:file:./custom-config/,考虑的完整位置集为:spring-doc.cadn.net.cn

  1. optional:classpath:custom-config/spring-doc.cadn.net.cn

  2. optional:file:./custom-config/spring-doc.cadn.net.cn

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

  1. optional:classpath:/;optional:classpath:/config/spring-doc.cadn.net.cn

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/spring-doc.cadn.net.cn

  3. optional:classpath:custom-config/spring-doc.cadn.net.cn

  4. optional:file:./custom-config/spring-doc.cadn.net.cn

通过此搜索顺序,您可以在一个配置文件中指定默认值,然后有选择地覆盖另一个配置文件中的这些值。您可以在application.properties(或您选择的任何其他基本名称spring.config.name) 在默认位置之一。然后,可以在运行时使用位于其中一个自定义位置的不同文件覆盖这些默认值。spring-doc.cadn.net.cn

可选地点

默认情况下,当指定的配置数据位置不存在时,Spring Boot 将抛出一个ConfigDataLocationNotFoundException并且您的应用程序将不会启动。spring-doc.cadn.net.cn

如果您想指定一个位置,但您不介意它是否总是存在,您可以使用optional:前缀。 您可以将此前缀与spring.config.locationspring.config.additional-location属性,以及spring.config.import声明。spring-doc.cadn.net.cn

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

如果您想忽略所有ConfigDataLocationNotFoundException错误并始终继续启动您的应用程序,您可以使用spring.config.on-not-found财产。 将值设置为ignoreSpringApplication.setDefaultProperties(…​)或使用系统/环境变量。spring-doc.cadn.net.cn

通配符位置

如果配置文件位置包含最后一个路径段的字符,则该位置被视为通配符位置。加载配置时,通配符会展开,以便同时检查直接子目录。当配置属性有多个来源时,通配符位置在 Kubernetes 等环境中特别有用。*spring-doc.cadn.net.cn

例如,如果你有一些 Redis 配置和一些 MySQL 配置,你可能希望将这两部分配置分开,同时要求这两部分都存在于application.properties文件。 这可能会导致两个单独的application.properties挂载在不同位置的文件,例如/config/redis/application.properties/config/mysql/application.properties. 在这种情况下,通配符位置为config/*/,将导致两个文件都被处理。spring-doc.cadn.net.cn

默认情况下,Spring Boot 包括config/*/在默认搜索位置中。 这意味着/config将搜索 jar 外部的目录。spring-doc.cadn.net.cn

您可以自己使用通配符位置,并使用spring.config.locationspring.config.additional-location性能。spring-doc.cadn.net.cn

通配符位置必须仅包含一个并以 结尾的搜索位置,即目录或**/*/<filename>用于文件搜索位置。 带有通配符的位置根据文件名的绝对路径按字母顺序排序。
通配符位置仅适用于外部目录。不能在classpath:位置。

配置文件特定文件

以及application属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}. 例如,如果您的应用程序激活名为prod并使用 YAML 文件,则同时使用application.yamlapplication-prod.yaml将被考虑。spring-doc.cadn.net.cn

特定于配置文件的属性从与标准相同的位置加载application.properties,特定于配置文件的文件始终覆盖非特定文件。如果指定了多个配置文件,则应用后赢策略。例如,如果配置文件prod,livespring.profiles.active属性,值application-prod.properties可以被那些application-live.properties.spring-doc.cadn.net.cn

后赢策略适用于位置组级别。 一个spring.config.locationclasspath:/cfg/,classpath:/ext/将不会具有与classpath:/cfg/;classpath:/ext/.spring-doc.cadn.net.cn

例如,继续我们的prod,live上面的示例,我们可能有以下文件:spring-doc.cadn.net.cn

/cfg
  application-live.properties
/ext
  application-live.properties
  application-prod.properties

当我们有一个spring.config.locationclasspath:/cfg/,classpath:/ext/我们处理所有/cfg文件在所有文件之前/ext文件:spring-doc.cadn.net.cn

  1. /cfg/application-live.propertiesspring-doc.cadn.net.cn

  2. /ext/application-prod.propertiesspring-doc.cadn.net.cn

  3. /ext/application-live.propertiesspring-doc.cadn.net.cn

当我们有classpath:/cfg/;classpath:/ext/相反(使用分隔符)我们处理;/cfg/ext在同一级别:spring-doc.cadn.net.cn

  1. /ext/application-prod.propertiesspring-doc.cadn.net.cn

  2. /cfg/application-live.propertiesspring-doc.cadn.net.cn

  3. /ext/application-live.propertiesspring-doc.cadn.net.cn

Environment具有一组默认配置文件(默认情况下,[default]),如果未设置活动配置文件,则使用该配置文件。换句话说,如果没有显式激活配置文件,则属性application-default被考虑。spring-doc.cadn.net.cn

属性文件只加载一次。如果您已经直接导入了配置文件特定的属性文件,则不会再次导入该文件。

导入其他数据

应用程序属性可以使用spring.config.import财产。 导入在发现时进行处理,并被视为插入紧邻声明导入的文档下方的附加文档。spring-doc.cadn.net.cn

例如,您的类路径中可能有以下内容application.properties文件:spring-doc.cadn.net.cn

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

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

无论声明多少次,导入都只会导入一次。spring-doc.cadn.net.cn

使用“固定”和“导入相对”位置

导入可以指定为固定导入相对位置。 固定位置始终解析为相同的底层资源,无论spring.config.import属性被声明。 导入相对位置相对于声明spring.config.import财产。spring-doc.cadn.net.cn

以正斜杠 () 或 URL 样式前缀 (/file:,classpath:等)被认为是固定的。 所有其他位置都被视为进口相对位置。spring-doc.cadn.net.cn

optional:在确定位置是固定位置还是导入相对位置时,不考虑前缀。

例如,假设我们有一个/demo包含我们的application.jar文件。 我们可能会添加一个/demo/application.properties文件,内容如下:spring-doc.cadn.net.cn

spring.config.import=optional:core/core.properties

这是一个导入相对位置,因此将尝试加载文件/demo/core/core.properties如果存在的话。spring-doc.cadn.net.cn

如果/demo/core/core.properties内容如下:spring-doc.cadn.net.cn

spring.config.import=optional:extra/extra.properties

它将尝试加载/demo/core/extra/extra.properties. 这optional:extra/extra.properties相对于/demo/core/core.properties所以完整目录是/demo/core/ + extra/extra.properties.spring-doc.cadn.net.cn

属性排序

在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。 例如,下面的两个示例产生相同的结果:spring-doc.cadn.net.cn

spring.config.import=my.properties
my.property=value
spring:
  config:
    import: "my.properties"
my:
  property: "value"
my.property=value
spring.config.import=my.properties
my:
  property: "value"
spring:
  config:
    import: "my.properties"

在上述两个示例中,来自my.properties文件将优先于触发其导入的文件。spring-doc.cadn.net.cn

可以在单个spring.config.import钥匙。 位置将按照定义的顺序进行处理,以后导入优先。spring-doc.cadn.net.cn

在适当的情况下,还会考虑导入特定于配置文件的变体。 上面的示例将导入my.properties以及任何my-<profile>.properties变种。

Spring Boot 包括可插拔的 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和配置树spring-doc.cadn.net.cn

第三方 jar 可以提供对其他技术的支持(不需要文件是本地的)。 例如,您可以想象配置数据来自外部存储,例如 Consul、Apache ZooKeeper 或 Netflix Archaius。spring-doc.cadn.net.cn

如果您想支持自己的位置,请参阅ConfigDataLocationResolverConfigDataLoaderorg.springframework.boot.context.config包。spring-doc.cadn.net.cn

导入无扩展名文件

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

例如,假设您有一个/etc/config/myconfig您希望作为 yaml 导入的文件。 您可以从application.properties使用以下内容:spring-doc.cadn.net.cn

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

使用配置树

在云平台(如 Kubernetes)上运行应用程序时,通常需要读取平台提供的配置值。 出于此类目的使用环境变量并不少见,但这可能有缺点,特别是如果该值应该保密。spring-doc.cadn.net.cn

作为环境变量的替代方法,许多云平台现在允许您将配置映射到已挂载的数据卷中。 例如,Kubernetes 可以同时卷挂载ConfigMapsSecrets.spring-doc.cadn.net.cn

可以使用两种常见的卷挂载模式:spring-doc.cadn.net.cn

  1. 单个文件包含一组完整的属性(通常写为 YAML)。spring-doc.cadn.net.cn

  2. 多个文件被写入目录树,文件名成为“键”,内容成为“值”。spring-doc.cadn.net.cn

对于第一种情况,您可以使用spring.config.import上所述。 对于第二种情况,您需要使用configtree:前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。spring-doc.cadn.net.cn

例如,假设 Kubernetes 已挂载以下卷:spring-doc.cadn.net.cn

etc/
  config/
    myapp/
      username
      password

的内容usernamefile 将是一个配置值,而password将是一个秘密。spring-doc.cadn.net.cn

要导入这些属性,您可以将以下内容添加到application.propertiesapplication.yaml文件:spring-doc.cadn.net.cn

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

然后,您可以访问或注入myapp.usernamemyapp.password属性Environment以通常的方式。spring-doc.cadn.net.cn

配置树下的文件夹和文件的名称构成属性名称。在上面的示例中,要访问属性usernamepassword,您可以设置spring.config.importoptional:configtree:/etc/config/myapp.
带有点表示法的文件名也会被正确映射。例如,在上面的示例中,名为myapp.username/etc/config将导致myapp.username属性中的Environment.
配置树值可以绑定到两个字符串Stringbyte[]类型取决于预期的内容。

如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。 任何configtree:location 结尾为 将所有直接子项导入为配置树。 与非通配符导入一样,每个配置树下的文件夹和文件的名称构成属性名称。/*/spring-doc.cadn.net.cn

例如,给定以下卷:spring-doc.cadn.net.cn

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

您可以使用configtree:/etc/config/*/作为导入位置:spring-doc.cadn.net.cn

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

这将添加db.username,db.password,mq.usernamemq.password性能。spring-doc.cadn.net.cn

使用通配符加载的目录按字母顺序排序。 如果您需要不同的订单,则应将每个位置列为单独的导入

配置树也可用于 Docker 密钥。 当 Docker swarm 服务被授予对机密的访问权限时,该机密将装载到容器中。 例如,如果名为db.password安装在位置/run/secrets/,您可以制作db.password使用以下命令提供给 Spring 环境:spring-doc.cadn.net.cn

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

属性占位符

中的值application.propertiesapplication.yaml通过现有的Environment使用它们时,您可以返回以前定义的值(例如,从系统属性或环境变量)。 标准${name}属性占位符语法可以在值内的任何位置使用。 属性占位符还可以使用:将默认值与属性名称分开,例如${name:default}.spring-doc.cadn.net.cn

以下示例显示了带默认值和不带默认值的占位符的使用:spring-doc.cadn.net.cn

app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
app:
  name: "MyApp"
  description: "${app.name} is a Spring Boot application written by ${username:Unknown}"

假设username属性未在其他地方设置,app.description将具有价值MyApp is a Spring Boot application written by Unknown.spring-doc.cadn.net.cn

您应该始终使用占位符中的规范形式(仅使用小写字母的烤肉串大小写)来引用占位符中的属性名称。 这将允许 Spring Boot 使用与松绑定时相同的逻辑 @ConfigurationProperties.spring-doc.cadn.net.cn

例如${demo.item-price}会捡起demo.item-pricedemo.itemPrice表格来自application.properties文件,以及DEMO_ITEMPRICE来自系统环境。 如果您使用${demo.itemPrice}相反demo.item-priceDEMO_ITEMPRICE不会被考虑。spring-doc.cadn.net.cn

您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅“作指南”中的“使用”短“命令行参数部分。

使用多文档文件

Spring Boot 允许您将单个物理文件拆分为多个逻辑文档,每个文档都是独立添加的。 文档按从上到下的顺序处理。 较后的文档可以覆盖较早的文档中定义的属性。spring-doc.cadn.net.cn

application.yaml文件中,使用标准的 YAML 多文档语法。 三个连续的连字符表示一个文档的结束,以及下一个文档的开始。spring-doc.cadn.net.cn

例如,以下文件有两个逻辑文档:spring-doc.cadn.net.cn

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

application.properties提交特殊或#---!---comment 用于标记文档拆分:spring-doc.cadn.net.cn

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
属性文件分隔符不得有任何前导空格,并且必须恰好具有三个连字符。 分隔符前后的行不得是相同的注释前缀。
多文档属性文件通常与激活属性(例如spring.config.activate.on-profile. 有关详细信息,请参阅下一节
无法使用@PropertySource@TestPropertySource附注。

激活属性

有时,仅在满足某些条件时激活一组给定的属性很有用。 例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。spring-doc.cadn.net.cn

您可以使用spring.config.activate.*.spring-doc.cadn.net.cn

以下激活属性可用:spring-doc.cadn.net.cn

表 1.激活属性
属性 注意

on-profilespring-doc.cadn.net.cn

必须匹配才能使文档处于活动状态的配置文件表达式,或必须至少匹配一个配置文件表达式的列表才能使文档处于活动状态。spring-doc.cadn.net.cn

on-cloud-platformspring-doc.cadn.net.cn

CloudPlatform必须检测到该文档才能处于活动状态。spring-doc.cadn.net.cn

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

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

加密属性

Spring Boot 不提供任何对加密属性值的内置支持,但是,它确实提供了修改 Spring 中包含的值所需的钩子点Environment. 这EnvironmentPostProcessor接口允许您作Environment在应用程序启动之前。有关详细信息,请参阅在启动之前自定义环境或 ApplicationContextspring-doc.cadn.net.cn

如果您需要一种安全的方式来存储凭据和密码,Spring Cloud Vault 项目支持在 HashiCorp Vault 中存储外部化配置。spring-doc.cadn.net.cn

使用 YAML

YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。 这SpringApplication每当你的类路径上有 SnakeYAML 库时,class 就会自动支持 YAML 作为属性的替代方案。spring-doc.cadn.net.cn

如果您使用Starters,则 SnakeYAML 由spring-boot-starter.

将 YAML 映射到属性

YAML 文档需要从其分层格式转换为可与 Spring 一起使用的平面结构Environment. 例如,考虑以下 YAML 文档:spring-doc.cadn.net.cn

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

为了从Environment,它们将被扁平化如下:spring-doc.cadn.net.cn

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:spring-doc.cadn.net.cn

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

前面的示例将转换为以下属性:spring-doc.cadn.net.cn

my.servers[0]=dev.example.com
my.servers[1]=another.example.com
使用[index]表示法可以绑定到 JavaListSet使用 Spring Boot 的Binder类。 有关更多详细信息,请参阅下面的类型安全配置属性部分。
无法使用@PropertySource@TestPropertySource附注。 因此,如果您需要以这种方式加载值,则需要使用属性文件。

直接加载 YAML

Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 这YamlPropertiesFactoryBean将 YAML 加载为PropertiesYamlMapFactoryBean将 YAML 加载为Map.spring-doc.cadn.net.cn

您还可以使用YamlPropertySourceLoader类,如果要将 YAML 加载为 SpringPropertySource.spring-doc.cadn.net.cn

配置随机值

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

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]}
my:
  secret: "${random.value}"
  number: "${random.int}"
  bignumber: "${random.long}"
  uuid: "${random.uuid}"
  number-less-than-ten: "${random.int(10)}"
  number-in-range: "${random.int[1024,65536]}"

random.int*语法是OPEN value (,max) CLOSE其中OPEN,CLOSE是任何字符和value,max是整数。 如果max,则value是最小值,而max是最大值(不包括)。spring-doc.cadn.net.cn

配置系统环境属性

Spring Boot 支持为环境属性设置前缀。 如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将很有用。 系统环境属性的前缀可以直接在SpringApplication通过调用setEnvironmentPrefix(…​)方法。spring-doc.cadn.net.cn

例如,如果将前缀设置为input,属性,例如remote.timeout将解析为INPUT_REMOTE_TIMEOUT在系统环境中。spring-doc.cadn.net.cn

前缀适用于系统环境属性。 上面的示例将继续使用remote.timeout从其他来源读取属性时。

类型安全配置属性

使用@Value("${property}")注入配置属性的注释有时可能很麻烦,尤其是在您使用多个属性或数据本质上是分层的时。 Spring Boot 提供了一种使用属性的替代方法,允许强类型 Bean 管理和验证应用程序的配置。spring-doc.cadn.net.cn

另请参阅之间的差异 @Value和类型安全的配置属性。

JavaBean 属性绑定

可以绑定声明标准 JavaBean 属性的 bean,如以下示例所示:spring-doc.cadn.net.cn

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

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

	private boolean enabled;

	private InetAddress remoteAddress;

	private final Security security = new Security();

	// getters / setters...

	public boolean isEnabled() {
		return this.enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		private String username;

		private String password;

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

		// getters / setters...

		public String getUsername() {
			return this.username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

		public String getPassword() {
			return this.password;
		}

		public void setPassword(String password) {
			this.password = password;
		}

		public List<String> getRoles() {
			return this.roles;
		}

		public void setRoles(List<String> roles) {
			this.roles = roles;
		}

	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import java.net.InetAddress

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

	var isEnabled = false

	var remoteAddress: InetAddress? = null

	val security = Security()

	class Security {

		var username: String? = null

		var password: String? = null

		var roles: List<String> = ArrayList(setOf("USER"))

	}

}

前面的 POJO 定义了以下属性:spring-doc.cadn.net.cn

在属性名称中使用保留关键字,例如my.service.import,使用@Name属性字段上的注释。
映射到@ConfigurationPropertiesSpring Boot 中可用的类是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。

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

  • 映射,只要它们被初始化,就需要一个 getter,但不一定是 setter,因为它们可以被 binder 改变。spring-doc.cadn.net.cn

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

  • 如果嵌套的 POJO 属性被初始化(如Security字段),不需要 setter。 如果希望 Binder 使用其默认构造函数动态创建实例,则需要一个 setter。spring-doc.cadn.net.cn

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

最后,仅考虑标准的 Java Bean 属性,不支持绑定静态属性。spring-doc.cadn.net.cn

构造函数绑定

上一节中的示例可以以不可变的方式重写,如以下示例所示:spring-doc.cadn.net.cn

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

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

	// fields...

	private final boolean enabled;

	private final InetAddress remoteAddress;

	private final Security security;


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

	// getters...

	public boolean isEnabled() {
		return this.enabled;
	}

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		// fields...

		private final String username;

		private final String password;

		private final List<String> roles;


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

		// getters...

		public String getUsername() {
			return this.username;
		}

		public String getPassword() {
			return this.password;
		}

		public List<String> getRoles() {
			return this.roles;
		}

	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import java.net.InetAddress

@ConfigurationProperties("my.service")
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
		val security: Security) {

	class Security(val username: String, val password: String,
			@param:DefaultValue("USER") val roles: List<String>)

}

在此设置中,单个参数化构造函数的存在意味着应使用构造函数绑定。这意味着绑定器将找到一个构造函数,其中包含您希望绑定的参数。如果您的类有多个构造函数,则@ConstructorBinding注释可用于指定要用于构造函数绑定的构造函数。spring-doc.cadn.net.cn

要选择退出类的构造函数绑定,必须使用@Autowired或制作private. Kotlin 开发人员可以使用空的主构造函数来选择退出构造函数绑定。spring-doc.cadn.net.cn

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

	// fields...

	final MyBean myBean;

	private String name;


	@Autowired
	public MyProperties(MyBean myBean) {
		this.myBean = myBean;
	}

	// getters / setters...


	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}


}
import org.springframework.boot.context.properties.ConfigurationProperties

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

	constructor(name: String) : this() {
		this.name = name
	}

	// vars...

	var name: String? = null

}

构造函数绑定可以与记录一起使用。 除非您的记录有多个构造函数,否则无需使用@ConstructorBinding.spring-doc.cadn.net.cn

构造函数绑定类的嵌套成员(例如Security在上面的示例中)也将通过其构造函数进行绑定。spring-doc.cadn.net.cn

可以使用以下命令指定默认值@DefaultValue在构造函数参数和记录组件上。 转换服务将应用于强制注释的Stringvalue 设置为缺失属性的目标类型。spring-doc.cadn.net.cn

参考前面的例子,如果没有属性绑定到SecurityMyProperties实例将包含一个nullsecurity. 要使其包含Security即使没有属性绑定到它(使用 Kotlin 时,这也需要usernamepassword参数Security声明为可为 null,因为它们没有默认值),请使用空的@DefaultValue注解:spring-doc.cadn.net.cn

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

	class Security(val username: String?, val password: String?,
			@param:DefaultValue("USER") val roles: List<String>)

}
要使用构造函数绑定,必须使用@EnableConfigurationProperties或配置属性扫描。您不能将构造函数绑定与由常规 Spring 机制创建的 bean(例如@Componentbeans,使用@Bean方法或使用@Import)
要使用构造函数绑定,必须使用-parameters. 如果您使用 Spring Boot 的 Gradle 插件或使用 Maven 和spring-boot-starter-parent.
使用Optional@ConfigurationProperties不推荐,因为它主要用作返回类型。因此,它不太适合配置属性注入。为了与其他类型的属性保持一致,如果您确实声明了Optional属性,它没有价值,null而不是空的Optional将被绑定。
在属性名称中使用保留关键字,例如my.service.import,使用@Name构造函数参数上的注释。

启用@ConfigurationProperties注释类型

Spring Boot 提供了绑定的基础设施@ConfigurationProperties类型并将它们注册为 bean。您可以逐类启用配置属性,也可以启用配置属性扫描,其工作方式与组件扫描类似。spring-doc.cadn.net.cn

有时,用@ConfigurationProperties可能不适合扫描,例如,如果您正在开发自己的自动配置或想要有条件地启用它们。在这些情况下,请使用@EnableConfigurationProperties注解。 这可以在任何@Configuration类,如以下示例所示:spring-doc.cadn.net.cn

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

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

}
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties::class)
class MyConfiguration
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("some.properties")
public class SomeProperties {

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("some.properties")
class SomeProperties

要使用配置属性扫描,请将@ConfigurationPropertiesScan注释到您的应用程序。 通常,它被添加到标注为@SpringBootApplication但它可以添加到任何@Configuration类。 默认情况下,将从声明注释的类的包进行扫描。 如果要定义要扫描的特定包,可以按照以下示例所示进行作:spring-doc.cadn.net.cn

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

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

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan

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

@ConfigurationPropertiesbean 使用配置属性扫描或通过@EnableConfigurationProperties,bean 有一个常规名称:<prefix>-<fqn>哪里<prefix>@ConfigurationPropertiesannotation 和<fqn>是 bean 的完全限定名称。 如果注释未提供任何前缀,则仅使用 Bean 的完全限定名称。spring-doc.cadn.net.cn

假设它在com.example.apppackage,则SomeProperties上面的例子是some.properties-com.example.app.SomeProperties.spring-doc.cadn.net.cn

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

使用@ConfigurationProperties注释类型

这种配置风格特别适用于SpringApplication外部 YAML 配置,如以下示例所示:spring-doc.cadn.net.cn

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

@ConfigurationPropertiesbean,您可以像任何其他 bean 一样注入它们,如以下示例所示:spring-doc.cadn.net.cn

import org.springframework.stereotype.Service;

@Service
public class MyService {

	private final MyProperties properties;

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

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

	// ...

}
import org.springframework.stereotype.Service

@Service
class MyService(val properties: MyProperties) {

	fun openConnection() {
		val server = Server(properties.remoteAddress)
		server.start()
		// ...
	}

	// ...

}
@ConfigurationProperties还允许您生成元数据文件,IDE 可以使用这些文件为您自己的键提供自动完成功能。 有关详细信息,请参阅附录

第三方配置

以及使用@ConfigurationProperties要注释类,您也可以在公共上使用它@Bean方法。 当您想要将属性绑定到您无法控制的第三方组件时,这样做可能特别有用。spring-doc.cadn.net.cn

要从Environment属性, 添加@ConfigurationProperties到其 bean 注册,如以下示例所示:spring-doc.cadn.net.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {

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

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class ThirdPartyConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "another")
	fun anotherComponent(): AnotherComponent = AnotherComponent()

}

使用another前缀映射到该AnotherComponentbean 的方式与前面类似SomeProperties例。spring-doc.cadn.net.cn

松绑

Spring Boot 使用一些宽松的绑定规则Environment属性设置为@ConfigurationPropertiesbean,因此不需要Environment属性名称和 bean 属性名称。这有用的常见示例包括破折号分隔的环境属性(例如,context-path绑定到contextPath)和大写的环境属性(例如PORT绑定到port).spring-doc.cadn.net.cn

例如,请考虑以下内容@ConfigurationProperties类:spring-doc.cadn.net.cn

import org.springframework.boot.context.properties.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;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

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

	var firstName: String? = null

}

使用上述代码,可以使用以下属性名称:spring-doc.cadn.net.cn

表 2.松绑
属性 注意

my.main-project.person.first-namespring-doc.cadn.net.cn

烤肉盒,推荐用于.properties和 YAML 文件。spring-doc.cadn.net.cn

my.main-project.person.firstNamespring-doc.cadn.net.cn

标准驼峰命名法语法。spring-doc.cadn.net.cn

my.main-project.person.first_namespring-doc.cadn.net.cn

下划线表示法,这是用于.properties和 YAML 文件。spring-doc.cadn.net.cn

MY_MAINPROJECT_PERSON_FIRSTNAMEspring-doc.cadn.net.cn

大写格式,使用系统环境变量时建议使用。spring-doc.cadn.net.cn

prefix注释的值必须采用 kebab 大小写(小写并以 分隔,例如-my.main-project.person).
表 3.每个属性源的放宽绑定规则
属性来源 简单 列表

属性文件spring-doc.cadn.net.cn

驼峰式大小写、烤肉串大小写或下划线表示法spring-doc.cadn.net.cn

使用或逗号分隔值的标准列表语法[ ]spring-doc.cadn.net.cn

YAML 文件spring-doc.cadn.net.cn

驼峰式大小写、烤肉串大小写或下划线表示法spring-doc.cadn.net.cn

标准 YAML 列表语法或逗号分隔值spring-doc.cadn.net.cn

环境变量spring-doc.cadn.net.cn

大写格式,下划线作为分隔符(请参阅从环境变量绑定)。spring-doc.cadn.net.cn

用下划线括起来的数值(请参阅从环境变量绑定)spring-doc.cadn.net.cn

系统属性spring-doc.cadn.net.cn

驼峰式大小写、烤肉串大小写或下划线表示法spring-doc.cadn.net.cn

使用或逗号分隔值的标准列表语法[ ]spring-doc.cadn.net.cn

我们建议,如果可能,将属性存储为小写烤肉串格式,例如my.person.first-name=Rod.

绑定贴图

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

例如,考虑将以下属性绑定到Map<String,String>:spring-doc.cadn.net.cn

my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
my:
  map:
    "[/key1]": "value1"
    "[/key2]": "value2"
    "/key3": "value3"
对于 YAML 文件,需要用引号括起来才能正确解析键。

上述属性将绑定到Map/key1,/key2key3作为地图中的按键。 斜杠已从key3因为它没有被方括号包围。spring-doc.cadn.net.cn

绑定到标量值时,键.在它们中不需要被 包围。 标量值包括枚举和[]java.lang包,除了Object. 捆绑a.b=cMap<String, String>将保留.并返回带有条目的 Map{"a.b"="c"}. 对于任何其他类型,如果您key包含一个.. 例如,绑定a.b=cMap<String, Object>将返回一个带有条目的地图{"a"={"b"="c"}}[a.b]=c将返回一个带有条目的地图{"a.b"="c"}.spring-doc.cadn.net.cn

从环境变量绑定

大多数作系统对可用于环境变量的名称施加了严格的规则。例如,Linux shell 变量只能包含字母 (azAZ)、数字 (09) 或下划线字符 ()。按照惯例,Unix shell 变量的名称也将以大写形式命名。_spring-doc.cadn.net.cn

Spring Boot 的宽松绑定规则尽可能地设计为与这些命名限制兼容。spring-doc.cadn.net.cn

要将规范表单中的属性名称转换为环境变量名称,您可以遵循以下规则:spring-doc.cadn.net.cn

例如,配置属性spring.main.log-startup-info将是一个名为SPRING_MAIN_LOGSTARTUPINFO.spring-doc.cadn.net.cn

绑定到对象列表时也可以使用环境变量。要绑定到List,则变量名称中的元素编号应用下划线括起来。spring-doc.cadn.net.cn

例如,配置属性my.service[0].other将使用名为MY_SERVICE_0_OTHER.spring-doc.cadn.net.cn

对环境变量绑定的支持应用于systemEnvironment属性源,以及名称以-systemEnvironment.spring-doc.cadn.net.cn

从环境变量绑定映射

当 Spring Boot 将环境变量绑定到属性类时,它会在绑定之前将环境变量名称小写。大多数时候,这个细节并不重要,除非绑定到Map性能。spring-doc.cadn.net.cn

中的键Map始终为小写,如以下示例所示:spring-doc.cadn.net.cn

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.props")
public class MyMapsProperties {

	private final Map<String, String> values = new HashMap<>();

	public Map<String, String> getValues() {
		return this.values;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "my.props")
class MyMapsProperties {

	val values: Map<String, String> = HashMap()

}

设置MY_PROPS_VALUES_KEY=valuevalues Map包含一个{"key"="value"}进入。spring-doc.cadn.net.cn

只有环境变量名称是小写的,而不是值。 设置MY_PROPS_VALUES_KEY=VALUEvalues Map包含一个{"key"="VALUE"}进入。spring-doc.cadn.net.cn

缓存

宽松绑定使用缓存来提高性能。默认情况下,此缓存仅应用于不可变属性源。 若要自定义此行为,例如,若要为可变属性源启用缓存,请使用ConfigurationPropertyCaching.spring-doc.cadn.net.cn

合并复杂类型

当列表配置在多个位置时,覆盖的工作原理是替换整个列表。spring-doc.cadn.net.cn

例如,假设MyPojo对象替换为namedescription属性null默认情况下。 以下示例公开了MyPojo对象来自MyProperties:spring-doc.cadn.net.cn

import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

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

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

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

	val list: List<MyPojo> = ArrayList()

}

请考虑以下配置:spring-doc.cadn.net.cn

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
my:
  list:
  - name: "my name"
    description: "my description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

如果dev配置文件未激活,MyProperties.list包含一个MyPojo条目,如前所述。 如果dev配置文件,但是,list 仍然只包含一个条目(名称为my another name以及null). 此配置不会添加第二个MyPojo实例添加到列表中,并且它不会合并项目。spring-doc.cadn.net.cn

List在多个配置文件中指定,则使用优先级最高的配置文件(并且仅使用该配置文件)。 请考虑以下示例:spring-doc.cadn.net.cn

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
my:
  list:
  - name: "my name"
    description: "my description"
  - name: "another name"
    description: "another description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

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

Map属性,您可以与从多个源提取的属性值绑定。 但是,对于多个源中的同一属性,将使用优先级最高的属性。 以下示例公开了Map<String, MyPojo>MyProperties:spring-doc.cadn.net.cn

import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

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

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

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

	val map: Map<String, MyPojo> = LinkedHashMap()

}

请考虑以下配置:spring-doc.cadn.net.cn

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
my:
  map:
    key1:
      name: "my name 1"
      description: "my description 1"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  map:
    key1:
      name: "dev name 1"
    key2:
      name: "dev name 2"
      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).spring-doc.cadn.net.cn

上述合并规则适用于所有属性源中的属性,而不仅仅是文件。

属性转换

Spring Boot 在绑定到@ConfigurationProperties豆。 如果您需要自定义类型转换,您可以提供ConversionServicebean(一个名为conversionService)或自定义属性编辑器(通过CustomEditorConfigurerbean)或自定义转换器(bean 定义注释为@ConfigurationPropertiesBinding).spring-doc.cadn.net.cn

用于属性转换的 Bean 在应用程序生命周期的早期就被请求,因此请确保限制您的依赖项ConversionService正在使用。 通常,所需的任何依赖项在创建时可能不会完全初始化。spring-doc.cadn.net.cn

您可能想要重命名您的自定义ConversionService如果配置密钥强制不需要它,并且仅依赖于符合@ConfigurationPropertiesBinding. 当对@Bean方法@ConfigurationPropertiesBinding,方法应该是static以避免“Bean 不符合所有 BeanPostProcessors 处理的条件”警告。

转换持续时间

Spring Boot 专门支持表达持续时间。 如果将Duration属性,则应用程序属性中的以下格式可用:spring-doc.cadn.net.cn

请考虑以下示例:spring-doc.cadn.net.cn

import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

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

	private Duration readTimeout = Duration.ofMillis(1000);

	// getters / setters...

	public Duration getSessionTimeout() {
		return this.sessionTimeout;
	}

	public void setSessionTimeout(Duration sessionTimeout) {
		this.sessionTimeout = sessionTimeout;
	}

	public Duration getReadTimeout() {
		return this.readTimeout;
	}

	public void setReadTimeout(Duration readTimeout) {
		this.readTimeout = readTimeout;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties {

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

	var readTimeout = Duration.ofMillis(1000)

}

要将会话超时指定为 30 秒,30,PT30S30s都是等价的。 500毫秒的读取超时可以用以下任何一种形式指定:500,PT0.5S500ms.spring-doc.cadn.net.cn

您还可以使用任何受支持的单元。 这些都是:spring-doc.cadn.net.cn

默认单位为毫秒,可以使用@DurationUnit如上面的示例所示。spring-doc.cadn.net.cn

如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:spring-doc.cadn.net.cn

import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

	// fields...
	private final Duration sessionTimeout;

	private final Duration readTimeout;

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

	// getters...

	public Duration getSessionTimeout() {
		return this.sessionTimeout;
	}

	public Duration getReadTimeout() {
		return this.readTimeout;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties(@param:DurationUnit(ChronoUnit.SECONDS) @param:DefaultValue("30s") val sessionTimeout: Duration,
		@param:DefaultValue("1000ms") val readTimeout: Duration)
如果您要升级Long属性,请确保定义单位(使用@DurationUnit),如果不是毫秒。 这样做可以提供透明的升级路径,同时支持更丰富的格式。

转换期间

除了持续时间之外,Spring Boot 还可以使用Period类型。 应用程序属性中可以使用以下格式:spring-doc.cadn.net.cn

简单格式支持以下单位:spring-doc.cadn.net.cn

Periodtype 实际上从未存储周数,它是一个快捷方式,意思是“7 天”。

转换数据大小

Spring Framework 有一个DataSizevalue 类型,以字节为单位表示大小。如果公开DataSize属性,则应用程序属性中的以下格式可用:spring-doc.cadn.net.cn

请考虑以下示例:spring-doc.cadn.net.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

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

	private DataSize sizeThreshold = DataSize.ofBytes(512);

	// getters/setters...

	public DataSize getBufferSize() {
		return this.bufferSize;
	}

	public void setBufferSize(DataSize bufferSize) {
		this.bufferSize = bufferSize;
	}

	public DataSize getSizeThreshold() {
		return this.sizeThreshold;
	}

	public void setSizeThreshold(DataSize sizeThreshold) {
		this.sizeThreshold = sizeThreshold;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties {

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

	var sizeThreshold = DataSize.ofBytes(512)

}

要指定 10 兆字节的缓冲区大小,1010MB是等效的。256 字节的大小阈值可以指定为256256B.spring-doc.cadn.net.cn

您还可以使用任何受支持的单元。 这些都是:spring-doc.cadn.net.cn

默认单位是字节,可以使用@DataSizeUnit如上面的示例所示。spring-doc.cadn.net.cn

如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:spring-doc.cadn.net.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

	// fields...
	private final DataSize bufferSize;

	private final DataSize sizeThreshold;

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

	// getters...

	public DataSize getBufferSize() {
		return this.bufferSize;
	}

	public DataSize getSizeThreshold() {
		return this.sizeThreshold;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties(@param:DataSizeUnit(DataUnit.MEGABYTES) @param:DefaultValue("2MB") val bufferSize: DataSize,
		@param:DefaultValue("512B") val sizeThreshold: DataSize)
如果您要升级Long属性,请确保定义单位(使用@DataSizeUnit),如果不是字节。 这样做可以提供透明的升级路径,同时支持更丰富的格式。

转换 Base64 数据

Spring Boot 支持解析已经过 Base64 编码的二进制数据。 如果将Resource属性,则 base64 编码的文本可以作为带有base64:prefix,如以下示例所示:spring-doc.cadn.net.cn

my.property=base64:SGVsbG8gV29ybGQ=
my:
  property: base64:SGVsbG8gV29ybGQ=
Resource属性还可用于提供资源的路径,使其更加通用。

@ConfigurationProperties验证

Spring Boot 尝试验证@ConfigurationProperties类,每当它们使用 Spring 的@Validated注解。 您可以使用 JSR-303jakarta.validation约束注释。 为此,请确保您的类路径上有一个合规的 JSR-303 实现,然后向字段添加约束注释,如以下示例所示:spring-doc.cadn.net.cn

import java.net.InetAddress;

import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

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

	@NotNull
	private InetAddress remoteAddress;

	// getters/setters...

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

}
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

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

	var remoteAddress: @NotNull InetAddress? = null

}
您还可以通过注释@Bean使用@Validated.

要将验证级联到嵌套属性,必须使用@Valid. 以下示例基于前面的内容构建MyProperties例:spring-doc.cadn.net.cn

import java.net.InetAddress;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

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

	@NotNull
	private InetAddress remoteAddress;

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

	// getters/setters...

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		@NotEmpty
		private String username;

		// getters/setters...

		public String getUsername() {
			return this.username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

	}

}
import jakarta.validation.Valid
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

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

	var remoteAddress: @NotNull InetAddress? = null

	@Valid
	val security = Security()

	class Security {

		@NotEmpty
		var username: String? = null

	}

}

您还可以添加自定义 SpringValidator通过创建一个名为configurationPropertiesValidator. 这@Bean方法应声明static. 配置属性验证器是在应用程序生命周期的早期创建的,并声明@Bean方法作为 static 可以创建 bean,而无需实例化@Configuration类。 这样做可以避免早期实例化可能导致的任何问题。spring-doc.cadn.net.cn

spring-boot-actuator模块包含一个端点,该端点将所有@ConfigurationProperties豆。 将 Web 浏览器指向/actuator/configprops或使用等效的 JMX 端点。 有关详细信息,请参阅生产就绪功能部分。

@ConfigurationProperties与@Value

@Value注释是核心容器功能,它不提供与类型安全配置属性相同的功能。 下表汇总了@ConfigurationProperties@Value:spring-doc.cadn.net.cn

特征 @ConfigurationProperties @Value

宽松绑定spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

有限(见下面的注释)spring-doc.cadn.net.cn

元数据支持spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

SpEL评估spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

如果您确实想使用@Value,我们建议您使用规范形式(仅使用小写字母的烤肉串大小写)来引用属性名称。 这将允许 Spring Boot 使用与松绑定时相同的逻辑 @ConfigurationProperties.spring-doc.cadn.net.cn

例如@Value("${demo.item-price}")会捡起demo.item-pricedemo.itemPrice表格来自application.properties文件,以及DEMO_ITEMPRICE来自系统环境。 如果您使用@Value("${demo.itemPrice}")相反demo.item-priceDEMO_ITEMPRICE不会被考虑。spring-doc.cadn.net.cn

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

SpEL在分析这些文件并填充环境时,不会处理应用程序属性文件中的表达式。 但是,可以编写一个SpEL表达式@Value. 如果应用程序属性文件中的属性值是SpELexpression,则通过@Value.spring-doc.cadn.net.cn