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

属性值可以使用注解直接注入到你的 Bean 中,通过 Spring 的抽象访问,或者通过 .@ValueEnvironment@ConfigurationPropertiesSpring中文文档

Spring Boot 使用非常特殊的顺序,旨在允许合理地覆盖值。 较晚的属性源可以覆盖较早属性源中定义的值。 按以下顺序考虑来源:PropertySourceSpring中文文档

  1. 默认属性(由设置指定)。SpringApplication.setDefaultPropertiesSpring中文文档

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

  3. 配置数据(例如文件)。application.propertiesSpring中文文档

  4. 仅在 中具有属性的 A 。RandomValuePropertySourcerandom.*Spring中文文档

  5. 操作系统环境变量。Spring中文文档

  6. Java 系统属性 ()。System.getProperties()Spring中文文档

  7. JNDI 属性来自 .java:comp/envSpring中文文档

  8. ServletContextinit 参数。Spring中文文档

  9. ServletConfiginit 参数。Spring中文文档

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

  11. 命令行参数。Spring中文文档

  12. properties属性。 在 @SpringBootTest 上可用,以及用于测试应用程序特定切片的测试注释Spring中文文档

  13. 在测试中@DynamicPropertySource注释。Spring中文文档

  14. @TestPropertySource测试的注释。Spring中文文档

  15. devtools 处于活动状态时目录中的 Devtools 全局设置属性$HOME/.config/spring-bootSpring中文文档

按以下顺序考虑配置文件:Spring中文文档

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

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

  3. 打包的 jar 之外的应用程序属性(和 YAML 变体)。application.propertiesSpring中文文档

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

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

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

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 中),可以有一个文件,该文件为 提供合理的默认属性值。 在新环境中运行时,可以在 jar 外部提供一个文件,该文件覆盖 . 对于一次性测试,您可以使用特定的命令行开关(例如,)。application.propertiesnameapplication.propertiesnamejava -jar app.jar --name="Spring"Spring中文文档

和 终结点可用于确定属性具有特定值的原因。 可以使用这两个终结点来诊断意外的属性值。 有关详细信息,请参阅“生产就绪功能”部分。envconfigprops
建议为您的整个应用程序坚持使用一种格式。 如果在同一位置具有同时具有 YAML 格式的配置文件,则优先。.properties.properties
如果使用环境变量而不是系统属性,则大多数操作系统不允许使用句点分隔的键名,但您可以改用下划线(例如,代替 )。 有关详细信息,请参阅从环境变量绑定SPRING_CONFIG_NAMEspring.config.name
如果应用程序在 servlet 容器或应用程序服务器中运行,那么可以使用 JNDI 属性(在 中)或 Servlet 上下文初始化参数来代替环境变量或系统属性。java:comp/env
和 终结点可用于确定属性具有特定值的原因。 可以使用这两个终结点来诊断意外的属性值。 有关详细信息,请参阅“生产就绪功能”部分。envconfigprops

访问命令行属性

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

如果不希望将命令行属性添加到 中,可以使用 禁用它们。EnvironmentSpringApplication.setAddCommandLineProperties(false)Spring中文文档

JSON 应用程序属性

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

当应用程序启动时,将分析任何 or 属性并将其添加到 .spring.application.jsonSPRING_APPLICATION_JSONEnvironmentSpring中文文档

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

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

在前面的示例中,您最终会得到 Spring .my.name=testEnvironmentSpring中文文档

也可以将相同的 JSON 作为系统属性提供:Spring中文文档

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

或者,您可以使用命令行参数提供 JSON:Spring中文文档

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

如果要部署到经典 Application Server,那么还可以使用名为 的 JNDI 变量。java:comp/env/spring.application.jsonSpring中文文档

尽管 JSON 中的值将添加到生成的属性源中,但会将属性视为缺失值。 这意味着 JSON 无法使用值覆盖来自低阶属性源的属性。nullPropertySourcesPropertyResolvernullnull
尽管 JSON 中的值将添加到生成的属性源中,但会将属性视为缺失值。 这意味着 JSON 无法使用值覆盖来自低阶属性源的属性。nullPropertySourcesPropertyResolvernullnull

外部应用程序属性

当应用程序启动时,Spring Boot 将自动从以下位置查找和加载文件:application.propertiesapplication.yamlSpring中文文档

  1. 从类路径Spring中文文档

    1. 类路径根Spring中文文档

    2. classpath 包/configSpring中文文档

  2. 从当前目录Spring中文文档

    1. 当前目录Spring中文文档

    2. 当前目录中的子目录config/Spring中文文档

    3. 子目录的直接子目录config/Spring中文文档

该列表按优先级排序(较低项的值将覆盖较早的项)。 加载文件中的文档将添加到 Spring .PropertySourcesEnvironmentSpring中文文档

如果您不喜欢作为配置文件名,可以通过指定环境属性切换到另一个文件名。 例如,若要查找和文件,可以按如下方式运行应用程序:applicationspring.config.namemyproject.propertiesmyproject.yamlSpring中文文档

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

还可以使用 environment 属性引用显式位置。 此属性接受要检查的一个或多个位置的逗号分隔列表。spring.config.locationSpring中文文档

下面的示例演示如何指定两个不同的文件:Spring中文文档

$ 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.namespring.config.locationSpring中文文档

目录和文件位置值也会展开,以检查特定于配置文件的文件。 例如,如果你有一个 ,你也会发现加载了相应的文件。spring.config.locationclasspath:myconfig.propertiesclasspath:myconfig-<profile>.properties

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

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

使用配置的位置将替换默认位置。 例如,如果配置了值 ,则考虑的完整位置集为:spring.config.locationspring.config.locationoptional:classpath:/custom-config/,optional:file:./custom-config/Spring中文文档

  1. optional:classpath:custom-config/Spring中文文档

  2. optional:file:./custom-config/Spring中文文档

如果您希望添加其他位置,而不是替换它们,则可以使用 . 从其他位置加载的属性可以覆盖默认位置中的属性。 例如,如果配置了值 ,则考虑的完整位置集为:spring.config.additional-locationspring.config.additional-locationoptional:classpath:/custom-config/,optional:file:./custom-config/Spring中文文档

  1. optional:classpath:/;optional:classpath:/config/Spring中文文档

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/Spring中文文档

  3. optional:classpath:custom-config/Spring中文文档

  4. optional:file:./custom-config/Spring中文文档

通过此搜索顺序,您可以在一个配置文件中指定默认值,然后有选择地覆盖另一个配置文件中的这些值。 您可以在其中一个默认位置(或您选择的任何其他基名)中为应用程序提供默认值。 然后,可以在运行时使用位于其中一个自定义位置的其他文件重写这些默认值。application.propertiesspring.config.nameSpring中文文档

可选位置

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

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

例如,值 允许应用程序启动,即使缺少文件也是如此。spring.config.importoptional:file:./myconfig.propertiesmyconfig.propertiesSpring中文文档

如果要忽略所有内容并始终继续启动应用程序,则可以使用该属性。 将该值设置为使用系统/环境变量或与系统/环境变量一起使用。ConfigDataLocationNotFoundExceptionsspring.config.on-not-foundignoreSpringApplication.setDefaultProperties(…​)Spring中文文档

通配符位置

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

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

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

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

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

配置文件特定文件

除了属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件。 例如,如果应用程序激活了名为 YAML 文件并使用的配置文件,则将同时考虑两者。applicationapplication-{profile}prodapplication.yamlapplication-prod.yamlSpring中文文档

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

“后赢”策略适用于营业地点组级别。 的 不会有与 相同的覆盖规则。spring.config.locationclasspath:/cfg/,classpath:/ext/classpath:/cfg/;classpath:/ext/Spring中文文档

例如,继续上面的示例,我们可能有以下文件:prod,liveSpring中文文档

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

当我们有一个 我们处理所有文件之前处理所有文件:spring.config.locationclasspath:/cfg/,classpath:/ext//cfg/extSpring中文文档

  1. /cfg/application-live.propertiesSpring中文文档

  2. /ext/application-prod.propertiesSpring中文文档

  3. /ext/application-live.propertiesSpring中文文档

当我们有(使用分隔符)时,我们处理并处于同一级别:classpath:/cfg/;classpath:/ext/;/cfg/extSpring中文文档

  1. /ext/application-prod.propertiesSpring中文文档

  2. /cfg/application-live.propertiesSpring中文文档

  3. /ext/application-live.propertiesSpring中文文档

具有一组默认配置文件(默认为 ),如果未设置活动配置文件,则使用这些配置文件。 换言之,如果未显式激活配置文件,则考虑 from 的属性。Environment[default]application-defaultSpring中文文档

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

导入其他数据

应用程序属性可以使用该属性从其他位置导入更多配置数据。 进口在发现时进行处理,并被视为紧接在申报进口的单据下方插入的附加单据。spring.config.importSpring中文文档

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

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

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

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

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.propertiesSpring中文文档

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

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

Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和“配置树”。Spring中文文档

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

如果要支持自己的位置,请参阅包中的 和 类。ConfigDataLocationResolverConfigDataLoaderorg.springframework.boot.context.configSpring中文文档

导入无扩展名文件

某些云平台无法将文件扩展名添加到卷装载文件。 要导入这些无扩展名文件,您需要给 Spring Boot 一个提示,以便它知道如何加载它们。 您可以通过在方括号中放置扩展提示来执行此操作。Spring中文文档

例如,假设您有一个要导入为 yaml 的文件。 您可以使用以下方法从中导入它:/etc/config/myconfigapplication.propertiesSpring中文文档

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

使用配置树

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

作为环境变量的替代方法,许多云平台现在允许您将配置映射到挂载的数据卷中。 例如,Kubernetes 可以同时进行 ConfigMapSecret 的卷挂载。Spring中文文档

可以使用两种常见的卷装载模式:Spring中文文档

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

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

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

举个例子,假设 Kubernetes 挂载了以下卷:Spring中文文档

etc/
  config/
    myapp/
      username
      password

文件的内容将是配置值,而文件的内容将是机密。usernamepasswordSpring中文文档

若要导入这些属性,可以将以下内容添加到 or 文件中:application.propertiesapplication.yamlSpring中文文档

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

然后,您可以以通常的方式从中访问或注入属性。myapp.usernamemyapp.passwordEnvironmentSpring中文文档

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

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

例如,给定以下体积:Spring中文文档

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

您可以用作导入位置:configtree:/etc/config/*/Spring中文文档

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

这将添加 、 和 属性。db.usernamedb.passwordmq.usernamemq.passwordSpring中文文档

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

配置树也可用于 Docker 机密。 当 Docker 群服务被授予对机密的访问权限时,该机密将挂载到容器中。 例如,如果一个名为 的密钥挂载在 位置 ,则可以使用以下命令对 Spring 环境使用:db.password/run/secrets/db.passwordSpring中文文档

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

属性占位符

中使用 和 中的值时会通过现有值进行筛选,因此您可以回溯以前定义的值(例如,从系统属性或环境变量中引用)。 标准属性占位符语法可以在值内的任何位置使用。 属性占位符还可以使用 a 指定默认值,以将默认值与属性名称分开,例如 。application.propertiesapplication.yamlEnvironment${name}:${name:default}Spring中文文档

以下示例显示了带和不带默认值的占位符的使用:Spring中文文档

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}"

假设该属性尚未在其他地方设置,则将具有 .usernameapp.descriptionMyApp is a Spring Boot application written by UnknownSpring中文文档

应始终使用占位符中的规范形式(仅使用小写字母的 kebab-case)引用属性名称。 这将允许Spring Boot使用与放松绑定时相同的逻辑。@ConfigurationPropertiesSpring中文文档

例如,将从文件以及系统环境中拾取和形成。 如果您改用,则不会被考虑。${demo.item-price}demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE${demo.itemPrice}demo.item-priceDEMO_ITEMPRICESpring中文文档

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

使用多文档文件

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

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

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

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

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

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

激活属性

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

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

可以使用以下激活属性:Spring中文文档

表 1.激活属性
财产 注意

on-profileSpring中文文档

一个配置文件表达式,必须匹配该表达式才能使文档处于活动状态。Spring中文文档

on-cloud-platformSpring中文文档

必须检测到该文档才能处于活动状态。CloudPlatformSpring中文文档

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

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"
如果位置是可选的,并且您不介意它们不存在,请使用前缀。optional:
spring.config.name、 和 很早就用于确定必须加载哪些文件。 它们必须定义为环境属性(通常是操作系统环境变量、系统属性或命令行参数)。spring.config.locationspring.config.additional-location
目录和文件位置值也会展开,以检查特定于配置文件的文件。 例如,如果你有一个 ,你也会发现加载了相应的文件。spring.config.locationclasspath:myconfig.propertiesclasspath:myconfig-<profile>.properties
通配符位置必须只包含一个,并且对于作为目录的搜索位置或作为文件的搜索位置,必须以结尾。 带有通配符的位置根据文件名的绝对路径按字母顺序排序。**/*/<filename>
通配符位置仅适用于外部目录。 不能在某个位置使用通配符。classpath:

“后赢”策略适用于营业地点组级别。 的 不会有与 相同的覆盖规则。spring.config.locationclasspath:/cfg/,classpath:/ext/classpath:/cfg/;classpath:/ext/Spring中文文档

例如,继续上面的示例,我们可能有以下文件:prod,liveSpring中文文档

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

当我们有一个 我们处理所有文件之前处理所有文件:spring.config.locationclasspath:/cfg/,classpath:/ext//cfg/extSpring中文文档

  1. /cfg/application-live.propertiesSpring中文文档

  2. /ext/application-prod.propertiesSpring中文文档

  3. /ext/application-live.propertiesSpring中文文档

当我们有(使用分隔符)时,我们处理并处于同一级别:classpath:/cfg/;classpath:/ext/;/cfg/extSpring中文文档

  1. /ext/application-prod.propertiesSpring中文文档

  2. /cfg/application-live.propertiesSpring中文文档

  3. /ext/application-live.propertiesSpring中文文档

属性文件只加载一次。 如果已直接导入配置文件特定的属性文件,则不会再次导入该文件。
在适当的情况下,还会考虑导入特定于配置文件的变体。 上面的示例将同时导入以及任何变体。my.propertiesmy-<profile>.properties

Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和“配置树”。Spring中文文档

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

如果要支持自己的位置,请参阅包中的 和 类。ConfigDataLocationResolverConfigDataLoaderorg.springframework.boot.context.configSpring中文文档

配置树下的文件夹和文件的名称构成属性名称。 在上面的示例中,要访问属性 as 和 ,可以设置为 。usernamepasswordspring.config.importoptional:configtree:/etc/config/myapp
带有点表示法的文件名也被正确映射。 例如,在上面的示例中,名为 in 的文件将导致 .myapp.username/etc/configmyapp.usernameEnvironment
配置树值可以绑定到字符串和类型,具体取决于预期的内容。Stringbyte[]
使用通配符加载的目录按字母顺序排序。 如果您需要不同的订单,则应将每个位置列为单独的导入

应始终使用占位符中的规范形式(仅使用小写字母的 kebab-case)引用属性名称。 这将允许Spring Boot使用与放松绑定时相同的逻辑。@ConfigurationPropertiesSpring中文文档

例如,将从文件以及系统环境中拾取和形成。 如果您改用,则不会被考虑。${demo.item-price}demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE${demo.itemPrice}demo.item-priceDEMO_ITEMPRICESpring中文文档

您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅使用“短”命令行参数操作方法。
属性文件分隔符不得有任何前导空格,并且必须正好有三个连字符。 分隔符前后的行不得为相同的注释前缀。
多文档属性文件通常与激活属性(如 )结合使用。 有关详细信息,请参阅下一节spring.config.activate.on-profile
无法使用 或 批注加载多文档属性文件。@PropertySource@TestPropertySource
表 1.激活属性
财产 注意

on-profileSpring中文文档

一个配置文件表达式,必须匹配该表达式才能使文档处于活动状态。Spring中文文档

on-cloud-platformSpring中文文档

必须检测到该文档才能处于活动状态。CloudPlatformSpring中文文档

加密属性

Spring Boot 不提供任何对加密属性值的内置支持,但是,它确实提供了修改 Spring 中包含的值所需的挂钩点。 该界面允许您在应用程序启动之前操作。 有关详细信息,请参阅在启动之前自定义环境或 ApplicationContextEnvironmentEnvironmentPostProcessorEnvironmentSpring中文文档

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

使用 YAML

YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。 只要您的类路径上有 SnakeYAML 库,该类就会自动支持 YAML 作为属性的替代项。SpringApplicationSpring中文文档

如果使用 “Starters”,则 SnakeYAML 会自动由 提供。spring-boot-starter

将 YAML 映射到属性

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

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

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

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 列表也需要扁平化。 它们表示为带有取消引用器的属性键。 例如,请考虑以下 YAML:[index]Spring中文文档

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

前面的示例将转换为以下属性:Spring中文文档

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

直接加载 YAML

Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 加载 YAML 作为 ,加载 YAML 作为 .YamlPropertiesFactoryBeanPropertiesYamlMapFactoryBeanMapSpring中文文档

如果要将 YAML 加载为 Spring ,也可以使用该类。YamlPropertySourceLoaderPropertySourceSpring中文文档

如果使用 “Starters”,则 SnakeYAML 会自动由 提供。spring-boot-starter
使用表示法的属性可以绑定到 Java 或使用 Spring Boot 类的对象。 有关详细信息,请参阅下面的“类型安全配置属性”部分。[index]ListSetBinder
无法使用 或 注释加载 YAML 文件。 因此,如果需要以这种方式加载值,则需要使用属性文件。@PropertySource@TestPropertySource

配置随机值

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

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) CLOSEOPEN,CLOSEvalue,maxmaxvaluemaxSpring中文文档

配置系统环境属性

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

例如,如果将前缀设置为 ,则 之类的属性也将像在系统环境中一样进行解析。inputremote.timeoutinput.remote.timeoutSpring中文文档

类型安全配置属性

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

JavaBean 属性绑定

可以绑定声明标准 JavaBean 属性的 Bean,如以下示例所示:Spring中文文档

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中文文档

  • my.service.enabled,默认值为 。falseSpring中文文档

  • my.service.remote-address,具有可以从 中强制执行的类型。StringSpring中文文档

  • my.service.security.username,带有嵌套的“security”对象,其名称由属性的名称确定。 特别是,那里根本没有使用该类型,并且可能是.SecurityPropertiesSpring中文文档

  • my.service.security.password.Spring中文文档

  • my.service.security.roles,其集合默认为 。StringUSERSpring中文文档

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

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

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

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

  • 如果初始化了嵌套的 POJO 属性(如前面示例中的字段),则不需要 setter。 如果希望 binder 使用其默认构造函数动态创建实例,则需要一个 setter。SecuritySpring中文文档

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

最后,只考虑标准的 Java Bean 属性,不支持绑定静态属性。Spring中文文档

构造函数绑定

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

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@Autowiredprivate@ConstructorBindingSpring中文文档

构造函数绑定类的嵌套成员(如上面的示例中所示)也将通过其构造函数进行绑定。SecuritySpring中文文档

可以使用构造函数参数和记录组件指定默认值。 转换服务将应用于将注释的值强制为缺失属性的目标类型。@DefaultValueStringSpring中文文档

参考前面的示例,如果没有绑定到 的属性,则实例将包含 的值。 要使它包含一个非 null 实例,即使没有绑定任何属性(当使用 Kotlin 时,这将需要将 和 参数声明为可为 null,因为它们没有默认值),请使用空注解:SecurityMyPropertiesnullsecuritySecurityusernamepasswordSecurity@DefaultValueSpring中文文档

	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>)

}
若要使用构造函数绑定,必须使用或配置属性扫描来启用类。 不能将构造函数绑定用于由常规 Spring 机制创建的 Bean(例如,Bean、使用方法创建的 Bean 或使用@EnableConfigurationProperties@Component@Bean@Import)
若要使用构造函数绑定,必须使用 编译类。 如果您使用 Spring Boot 的 Gradle 插件,或者使用 Maven 和 .-parametersspring-boot-starter-parent
不建议使用 with,因为它主要用作返回类型。 因此,它不太适合配置属性注入。 为了与其他类型的属性保持一致,如果声明了一个属性并且它没有值,则将绑定一个空。java.util.Optional@ConfigurationPropertiesOptionalnullOptional

启用@ConfigurationProperties批注类型

Spring Boot 提供了绑定类型并将它们注册为 Bean 的基础结构。 您可以逐类启用配置属性,也可以启用与组件扫描类似的配置属性扫描。@ConfigurationPropertiesSpring中文文档

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

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@ConfigurationSpring中文文档

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

当使用配置属性扫描或通过 注册 Bean 时,Bean 具有约定名称: ,其中是在注释中指定的环境键前缀,并且是 Bean 的完全限定名称。 如果注释未提供任何前缀,则仅使用 Bean 的完全限定名称。@ConfigurationProperties@EnableConfigurationProperties<prefix>-<fqn><prefix>@ConfigurationProperties<fqn>Spring中文文档

假设它在包中,上面示例的 bean 名称是 。com.example.appSomePropertiessome.properties-com.example.app.SomePropertiesSpring中文文档

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

使用@ConfigurationProperties批注类型

这种配置方式特别适用于外部 YAML 配置,如以下示例所示:SpringApplicationSpring中文文档

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

要使用 Bean,可以采用与任何其他 Bean 相同的方式注入它们,如以下示例所示:@ConfigurationPropertiesSpring中文文档

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()
		// ...
	}

	// ...

}
使用还允许您生成元数据文件,IDE 可以使用这些文件为您自己的密钥提供自动完成功能。 详见附录@ConfigurationProperties

第三方配置

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

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

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()

}

使用前缀定义的任何 JavaBean 属性都将以类似于前面示例的方式映射到该 Bean。anotherAnotherComponentSomePropertiesSpring中文文档

宽松的绑定

Spring Boot 使用一些宽松的规则将属性绑定到 bean,因此属性名称和 bean 属性名称之间不需要完全匹配。 有用的常见示例包括破折号分隔的环境属性(例如,binds to )和大写的环境属性(例如,binds to )。Environment@ConfigurationPropertiesEnvironmentcontext-pathcontextPathPORTportSpring中文文档

例如,请考虑以下类:@ConfigurationPropertiesSpring中文文档

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中文文档

表 2.宽松的绑定
财产 注意

my.main-project.person.first-nameSpring中文文档

烤肉串大小写,建议在 YAML 文件中使用。.propertiesSpring中文文档

my.main-project.person.firstNameSpring中文文档

标准骆驼大小写语法。Spring中文文档

my.main-project.person.first_nameSpring中文文档

下划线表示法,这是用于 YAML 文件的替代格式。.propertiesSpring中文文档

MY_MAINPROJECT_PERSON_FIRSTNAMESpring中文文档

大写格式,建议在使用系统环境变量时使用。Spring中文文档

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

属性文件Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

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

YAML文件Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

标准 YAML 列表语法或逗号分隔值Spring中文文档

环境变量Spring中文文档

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

用下划线括起来的数值(请参阅从环境变量绑定)Spring中文文档

系统属性Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

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

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

绑定映射

绑定到属性时,可能需要使用特殊的括号表示法,以便保留原始值。 如果键未被 括起来,则任何非字母数字字符或被删除。Mapkey[]-.Spring中文文档

例如,考虑将以下属性绑定到 :Map<String,String>Spring中文文档

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

上面的属性将绑定到 a with 和 作为映射中的键。 斜杠已被删除,因为它没有被方括号括起来。Map/key1/key2key3key3Spring中文文档

绑定到标量值时,包含其中的键不需要用 括起来。 标量值包括枚举和包中除 之外的所有类型。 绑定到将保留 in 键,并返回一个包含条目的 Map。 对于任何其他类型,如果包含 . 例如,绑定到将返回一个包含条目的 Map,而将返回一个包含条目的 Map。.[]java.langObjecta.b=cMap<String, String>.{"a.b"="c"}key.a.b=cMap<String, Object>{"a"={"b"="c"}}[a.b]=c{"a.b"="c"}Spring中文文档

从环境变量绑定

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

Spring Boot 宽松的绑定规则尽可能地与这些命名限制兼容。Spring中文文档

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

例如,配置属性将是名为 的环境变量。spring.main.log-startup-infoSPRING_MAIN_LOGSTARTUPINFOSpring中文文档

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

例如,配置属性将使用名为 的环境变量。my.service[0].otherMY_SERVICE_0_OTHERSpring中文文档

缓存

宽松绑定使用缓存来提高性能。默认情况下,此缓存仅应用于不可变属性源。 若要自定义此行为,例如,为可变属性源启用缓存,请使用 .ConfigurationPropertyCachingSpring中文文档

合并复杂类型

当在多个位置配置列表时,通过替换整个列表来覆盖工作。Spring中文文档

例如,假设一个对象具有默认的 和 属性。 以下示例公开以下对象的列表:MyPojonamedescriptionnullMyPojoMyPropertiesSpring中文文档

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中文文档

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"

如果配置文件未处于活动状态,则包含一个条目,如前所述。 但是,如果启用配置文件,则仍然只包含一个条目(名称为 ,描述为 )。 此配置不会将第二个实例添加到列表中,也不会合并项。devMyProperties.listMyPojodevlistmy another namenullMyPojoSpring中文文档

在多个配置文件中指定 a 时,将使用优先级最高的配置文件(并且仅使用该配置文件)。 请看以下示例:ListSpring中文文档

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"

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

对于属性,可以使用从多个源提取的属性值进行绑定。 但是,对于多个源中的同一属性,将使用优先级最高的属性。 以下示例公开了 from :MapMap<String, MyPojo>MyPropertiesSpring中文文档

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中文文档

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"

如果配置文件未处于活动状态,则包含一个带有键的条目(名称为 和描述为 )。 但是,如果启用了配置文件,则包含两个条目,其键(名称为 和 description 为 )和 (名称为 和 description 为 )。devMyProperties.mapkey1my name 1my description 1devmapkey1dev name 1my description 1key2dev name 2dev description 2Spring中文文档

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

属性转换

Spring Boot 在绑定到 Bean 时会尝试将外部应用程序属性强制为正确的类型。 如果需要自定义类型转换,可以提供 bean(带有名为 的 bean)或自定义属性编辑器(通过 bean)或自定义(bean 定义注释为 )。@ConfigurationPropertiesConversionServiceconversionServiceCustomEditorConfigurerConverters@ConfigurationPropertiesBindingSpring中文文档

由于此 Bean 是在应用程序生命周期的早期请求的,因此请确保限制您正在使用的依赖项。 通常,所需的任何依赖项在创建时可能不会完全初始化。 如果配置键强制不需要自定义,并且仅依赖符合 .ConversionServiceConversionService@ConfigurationPropertiesBinding

转换持续时间

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

请看以下示例:Spring中文文档

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 秒的会话超时,、 和 都是等效的。 500ms 的读取超时可以指定为以下任一形式:和 。30PT30S30s500PT0.5S500msSpring中文文档

您也可以使用任何受支持的设备。 这些是:Spring中文文档

默认单位为毫秒,可以使用上面的示例中所示进行覆盖。@DurationUnitSpring中文文档

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

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 还可以使用类型。 可以在应用程序属性中使用以下格式:java.time.PeriodSpring中文文档

简单格式支持以下单位:Spring中文文档

该类型实际上从不存储周数,它是一种快捷方式,表示“7 天”。java.time.Period

转换数据大小

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

  • 常规表示形式(使用字节作为默认单位,除非已指定 a)long@DataSizeUnitSpring中文文档

  • 一种更具可读性的格式,其中值和单位耦合(表示 10 兆字节)10MBSpring中文文档

请看以下示例:Spring中文文档

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 MB 的缓冲区大小,并且是等效的。 256 字节的大小阈值可以指定为 或 。1010MB256256BSpring中文文档

您也可以使用任何受支持的设备。 这些是:Spring中文文档

默认单位为字节,可以使用上面的示例中所示进行覆盖。@DataSizeUnitSpring中文文档

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

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

@ConfigurationProperties验证

Spring Boot 会尝试在类被 Spring 的注解注解时验证它们。 您可以直接在配置类上使用 JSR-303 约束注释。 为此,请确保类路径上有一个兼容的 JSR-303 实现,然后向字段添加约束注释,如以下示例所示:@ConfigurationProperties@Validatedjakarta.validationSpring中文文档

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

若要确保始终为嵌套属性触发验证,即使未找到任何属性,也必须用 对关联字段进行批注。 以下示例基于上述示例构建:@ValidMyPropertiesSpring中文文档

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

	}

}

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

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

@ConfigurationProperties 与 @Value

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

特征 @ConfigurationProperties @Value

宽松的装订Spring中文文档

是的Spring中文文档

有限(见下面的注释)Spring中文文档

元数据支持Spring中文文档

是的Spring中文文档

Spring中文文档

SpEL评估Spring中文文档

Spring中文文档

是的Spring中文文档

如果确实要使用 ,我们建议您使用属性名称的规范形式(仅使用小写字母的 kebab-case)来引用属性名称。 这将允许Spring Boot使用与放松绑定时相同的逻辑。@Value@ConfigurationPropertiesSpring中文文档

例如,将从文件以及系统环境中拾取和形成。 如果您改用,则不会被考虑。@Value("${demo.item-price}")demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE@Value("${demo.itemPrice}")demo.item-priceDEMO_ITEMPRICESpring中文文档

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

SpEL在分析应用程序属性文件中的表达式并填充环境时,不会处理这些表达式。 但是,可以在 中写入表达式。 如果应用程序属性文件中的属性值是表达式,则在通过 .SpEL@ValueSpEL@ValueSpring中文文档

另请参阅@Value和类型安全配置属性之间的差异
映射到 Spring Boot 中可用类的属性(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。@ConfigurationProperties

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

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

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

  • 如果初始化了嵌套的 POJO 属性(如前面示例中的字段),则不需要 setter。 如果希望 binder 使用其默认构造函数动态创建实例,则需要一个 setter。SecuritySpring中文文档

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

最后,只考虑标准的 Java Bean 属性,不支持绑定静态属性。Spring中文文档

若要使用构造函数绑定,必须使用或配置属性扫描来启用类。 不能将构造函数绑定用于由常规 Spring 机制创建的 Bean(例如,Bean、使用方法创建的 Bean 或使用@EnableConfigurationProperties@Component@Bean@Import)
若要使用构造函数绑定,必须使用 编译类。 如果您使用 Spring Boot 的 Gradle 插件,或者使用 Maven 和 .-parametersspring-boot-starter-parent
不建议使用 with,因为它主要用作返回类型。 因此,它不太适合配置属性注入。 为了与其他类型的属性保持一致,如果声明了一个属性并且它没有值,则将绑定一个空。java.util.Optional@ConfigurationPropertiesOptionalnullOptional

当使用配置属性扫描或通过 注册 Bean 时,Bean 具有约定名称: ,其中是在注释中指定的环境键前缀,并且是 Bean 的完全限定名称。 如果注释未提供任何前缀,则仅使用 Bean 的完全限定名称。@ConfigurationProperties@EnableConfigurationProperties<prefix>-<fqn><prefix>@ConfigurationProperties<fqn>Spring中文文档

假设它在包中,上面示例的 bean 名称是 。com.example.appSomePropertiessome.properties-com.example.app.SomePropertiesSpring中文文档

使用还允许您生成元数据文件,IDE 可以使用这些文件为您自己的密钥提供自动完成功能。 详见附录@ConfigurationProperties
表 2.宽松的绑定
财产 注意

my.main-project.person.first-nameSpring中文文档

烤肉串大小写,建议在 YAML 文件中使用。.propertiesSpring中文文档

my.main-project.person.firstNameSpring中文文档

标准骆驼大小写语法。Spring中文文档

my.main-project.person.first_nameSpring中文文档

下划线表示法,这是用于 YAML 文件的替代格式。.propertiesSpring中文文档

MY_MAINPROJECT_PERSON_FIRSTNAMESpring中文文档

大写格式,建议在使用系统环境变量时使用。Spring中文文档

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

属性文件Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

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

YAML文件Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

标准 YAML 列表语法或逗号分隔值Spring中文文档

环境变量Spring中文文档

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

用下划线括起来的数值(请参阅从环境变量绑定)Spring中文文档

系统属性Spring中文文档

骆驼盒、烤肉串盒或下划线符号Spring中文文档

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

我们建议尽可能以小写的烤肉串格式存储属性,例如 .my.person.first-name=Rod
对于 YAML 文件,括号需要用引号括起来,以便正确解析键。
上述合并规则适用于所有属性源中的属性,而不仅仅是文件。
由于此 Bean 是在应用程序生命周期的早期请求的,因此请确保限制您正在使用的依赖项。 通常,所需的任何依赖项在创建时可能不会完全初始化。 如果配置键强制不需要自定义,并且仅依赖符合 .ConversionServiceConversionService@ConfigurationPropertiesBinding
如果要升级属性,请确保定义单位(使用 ),如果单位不是毫秒。 这样做可以提供透明的升级路径,同时支持更丰富的格式。Long@DurationUnit
该类型实际上从不存储周数,它是一种快捷方式,表示“7 天”。java.time.Period
如果要升级属性,请确保定义单位(使用 ),如果它不是字节。 这样做可以提供透明的升级路径,同时支持更丰富的格式。Long@DataSizeUnit
还可以通过使用 . 对创建配置属性的方法进行批注来触发验证。@Bean@Validated
该模块包括一个公开所有 Bean 的端点。 将 Web 浏览器指向或使用等效的 JMX 端点。 有关详细信息,请参阅“生产就绪功能”部分。spring-boot-actuator@ConfigurationProperties/actuator/configprops
特征 @ConfigurationProperties @Value

宽松的装订Spring中文文档

是的Spring中文文档

有限(见下面的注释)Spring中文文档

元数据支持Spring中文文档

是的Spring中文文档

Spring中文文档

SpEL评估Spring中文文档

Spring中文文档

是的Spring中文文档

如果确实要使用 ,我们建议您使用属性名称的规范形式(仅使用小写字母的 kebab-case)来引用属性名称。 这将允许Spring Boot使用与放松绑定时相同的逻辑。@Value@ConfigurationPropertiesSpring中文文档

例如,将从文件以及系统环境中拾取和形成。 如果您改用,则不会被考虑。@Value("${demo.item-price}")demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE@Value("${demo.itemPrice}")demo.item-priceDEMO_ITEMPRICESpring中文文档