外部化配置

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

属性值可以通过直接注射到你的bean@Value注释,通过Spring的访问Environment抽象,或者通过@ConfigurationProperties绑定到Bean对象。
Spring Boot使用一个非常特殊的PropertySource顺序,该顺序旨在允许合理地覆盖值。按以下顺序考虑属性(较低项的值覆盖较早项的值):

  1. 默认属性(通过设置指定SpringApplication.setDefaultProperties)。
  2. @PropertySource@Configuration类上的注释。请注意,Environment在刷新应用程序上下文之前,不会将此类属性源添加到中。现在配置某些属性(如logging.*spring.main.*在刷新开始之前先读取)为时已晚。
  3. 配置数据(例如application.properties文件)
  4. RandomValuePropertySource,只有在拥有性能random.*
  5. 操作系统环境变量。
  6. Java系统属性(System.getProperties())。
  7. 的JNDI属性java:comp/env
  8. ServletContext 初始化参数。
  9. ServletConfig 初始化参数。
  10. 来自的属性SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的嵌入式JSON)。
  11. 命令行参数。
  12. properties测试中的属性。可用于测试应用程序的特定部分@SpringBootTest测试注释注释
  13. @TestPropertySource 测试中的注释。
  14. $HOME/.config/spring-boot当devtools处于活动状态时,目录中的Devtools全局设置属性

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

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

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

  1. import org.springframework.stereotype.*;
  2. import org.springframework.beans.factory.annotation.*;
  3. @Component
  4. public class MyBean {
  5. @Value("${name}")
  6. private String name;
  7. // ...
  8. }

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

外部应用程序属性

春天开机就会自动查找和加载application.propertiesapplication.yaml应用程序启动时的文件从以下位置:

  1. 类路径根
  2. 类路径/config
  3. 当前目录
  4. /config当前目录中的子目录
  5. 的的直接子目录/config的子目录

该列表按优先级排序(较低项的值覆盖较早项的值)。来自已加载文件的文档将添加PropertySources到Spring中Environment
如果您不喜欢application配置文件名,则可以通过指定spring.config.name环境属性来切换到另一个文件名。您还可以通过使用spring.config.locationenvironment属性(目录位置或文件路径的逗号分隔列表)来引用显式位置。以下示例显示如何指定其他文件名:
$ java -jar myproject.jar —spring.config.name = myproject
下面的示例演示如何指定两个位置:
$ java -jar myproject.jar —spring.config.location =可选:classpath:/default.properties,可选:classpath:/override.properties
如果spring.config.location包含目录(而不是文件),则应以目录结尾/(在运行时,将在目录后附加从生成spring.config.name之前生成的名称)。指定的文件spring.config.location按原样使用。无论是直接指定还是包含在目录中,配置文件都必须在名称中包含文件扩展名。所支持外的开箱典型的扩展是.properties.yaml.yml
如果指定了多个位置,则后面的位置可以覆盖前面的位置。
通过使用配置的位置spring.config.location替换默认位置。例如,如果spring.config.location配置为value optional:classpath:/custom-config/,optional:file:./custom-config/,则考虑的位置的完整集合为:

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

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

  1. optional:classpath:/
  2. optional:classpath:/config/
  3. optional:file:./
  4. optional:file:./config/
  5. optional:file:./config/*/
  6. optional:classpath:custom-config/
  7. optional:file:./custom-config/

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

可选位置

默认情况下,当指定的配置数据位置不存在时,Spring Boot将抛出,ConfigDataLocationNotFoundException并且您的应用程序将不会启动。
如果要指定位置,但不介意它并不总是存在,则可以使用optional:前缀。您可以将此前缀与spring.config.locationspring.config.additional-location属性以及spring.config.import声明一起使用。
例如,spring.config.import值为optional:file:./myconfig.properties,即使myconfig.properties文件丢失,也允许您的应用程序启动。
如果要忽略所有内容ConfigDataLocationNotFoundExceptions并始终继续启动应用程序,则可以使用该spring.config.on-not-found属性。将值设置为ignore使用SpringApplication.setDefaultProperties(…)或与系统/环境变量一起使用。

通配符位置

如果配置文件位置包含*最后一个路径段的字符,则将其视为通配符位置。加载配置时,通配符会展开,以便也检查直接子目录。当存在多个配置属性源时,通配符位置在诸如Kubernetes之类的环境中特别有用。
例如,如果您具有一些Redis配置和某些MySQL配置,则可能需要将这两个配置分开,同时要求这两个配置都存在于application.properties文件中。这可能会导致两个不同的application.properties文件安装在诸如不同的位置/config/redis/application.properties/config/mysql/application.properties。在这种情况下,通配符位置为config/*/,将导致两个文件都被处理。
默认情况下,Spring Boot包含config/*/在默认搜索位置。这意味着/config将搜索jar外部目录的所有子目录。
您可以自己通过spring.config.locationspring.config.additional-location属性使用通配符位置。

配置文件专用文件

除了application属性文件,Spring Boot还将尝试使用命名约定来加载特定于配置文件的文件application-{profile}。例如,如果你的应用程序启动了一个名为轮廓prod,并使用YAML文件,然后双方application.ymlapplication-prod.yml会予以考虑。
特定于配置文件的属性是从与standard相同的位置加载的application.properties,特定于配置文件的文件始终会覆盖非特定文件。如果指定了多个配置文件,则采用后赢策略。例如,如果属性prod,live指定了配置文件spring.profiles.active,则中的值application-prod.properties可以被中的值覆盖application-live.properties
Environment具有一组默认的配置文件(默认[default])如果没有活动的简档设置中使用。换句话说,如果未明确激活任何配置文件,则将application-default考虑来自的属性。

入其他数据

应用程序属性可以使用该spring.config.import属性从其他位置导入其他配置数据。导入时将对其进行处理,并将其视为在声明该导入的文件正下方插入的其他文档。
例如,您的类路径application.properties文件中可能包含以下内容:

  1. spring:
  2. application:
  3. name: "myapp"
  4. config:
  5. import: "optional:file:./dev.properties"

这将触发dev.properties当前目录中文件的导入(如果存在这样的文件)。来自导入的值dev.properties将优先于触发导入的文件。在上面的示例中,dev.properties可以重新定义spring.application.name为其他值。不论声明多少次,导入都只会导入一次。在properties / yaml文件中的单个文档中定义导入的顺序无关紧要

导入无扩展名文件

某些云平台无法将文件扩展名添加到已装入卷的文件中。要导入这些无扩展名的文件,您需要给Spring Boot一个提示,以便它知道如何加载它们。您可以通过在方括号中添加扩展提示来做到这一点。
例如,假设您有一个/etc/config/myconfig要导入为yaml的文件。您可以application.properties使用以下方法从中导入它:

  1. spring:
  2. config:
  3. import: "file:/etc/config/myconfig[.yaml]"

使用配置树

在云平台上运行应用程序(例如Kubernetes)时,您通常需要读取平台提供的配置值。为此目的使用环境变量并不罕见,但是这样做可能会有弊端,特别是如果该值应该保密的话。
作为环境变量的替代方法,许多云平台现在允许您将配置映射到装入的数据卷中。例如,Kubernetes可以批量挂载ConfigMapsSecrets
可以使用两种常见的卷安装模式:

  1. 单个文件包含完整的属性集(通常写为YAML)。
  2. 多个文件被写入目录树,文件名成为“键”,内容成为“值”。

对于第一种情况,你可以直接导入使用YAML或属性文件中spring.config.import所描述的以上。对于第二种情况,您需要使用configtree:前缀,以便Spring Boot知道它需要将所有文件公开为属性。
作为示例,让我们想象一下Kubernetes已经安装了以下卷:

  1. etc/
  2. config/
  3. myapp/
  4. username
  5. password

username文件的内容将是一个配置值,而其中的内容password将是一个秘密。
要导入这些属性,可以将以下内容添加到您的application.propertiesapplication.yaml文件中:

  1. spring:
  2. config:
  3. import: "optional:configtree:/etc/config/"

然后,您可以按照通常的方式从中访问或注入myapp.usernamemyapp.password属性Environment
如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。任何configtree:以结尾结尾的位置/*/都将所有直接子级导入为配置树。
例如,给定以下卷:

  1. etc/
  2. config/
  3. dbconfig/
  4. db/
  5. username
  6. password
  7. mqconfig/
  8. mq/
  9. username
  10. password

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

  1. spring:
  2. config:
  3. import: "optional:configtree:/etc/config/*/"

财产占位符

使用中的application.properties和时,它们中的值application.yml会通过现有过滤器过滤Environment,因此您可以参考以前定义的值(例如,从“系统”属性中)。标准的${name}property-placeholder语法可以在值中的任何位置使用。
例如,以下文件将设置app.description为“ MyApp是Spring Boot应用程序”:

  1. app:
  2. name: "MyApp"
  3. description: "${app.name} is a Spring Boot application"

处理多文档文件

Spring Boot允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档独立添加。从上到下按顺序处理文档。以后的文档可以覆盖以前的文档中定义的属性。
对于application.yml文件,使用标准的YAML多文档语法。三个连续的连字符代表一个文档的末尾,以及下一个文档的开始。
例如,以下文件具有两个逻辑文档:

  1. spring.application.name: MyApp
  2. ---
  3. spring.config.activate.on-cloud-platform: kubernetes
  4. spring.application.name: MyCloudApp

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

  1. spring.application.name=MyApp
  2. #---
  3. spring.config.activate.on-cloud-platform=kubernetes
  4. spring.application.name=MyCloudApp

激活属性

有时仅在满足某些条件时才激活给定的属性获取,这很有用。例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用来有条件地激活属性文档spring.config.activate.*
可以使用以下激活属性:
表2.激活属性

属性 注意
on-profile 必须匹配才能使文档处于活动状态的配置文件表达式。
on-cloud-platform CloudPlatform必须对文件进行检测活跃。

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

  1. myprop:
  2. always-set
  3. ---
  4. spring:
  5. config:
  6. activate:
  7. on-cloud-platform: "kubernetes"
  8. on-profile: "prod | staging"
  9. myotherprop: sometimes-set

加密属性

Spring Boot不提供对加密属性值的任何内置支持,但是,它确实提供了修改Spring包含的值所必需的挂钩点Environment。该EnvironmentPostProcessor界面允许您Environment在应用程序启动之前进行操作。有关详细信息,请参见howto.html
如果您正在寻找一种安全的方式来存储凭据和密码,则Spring Cloud Vault项目提供了对在HashiCorp Vault中存储外部化配置的支持。

使用YAML

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

配置随机值

RandomValuePropertySource是用于注射的随机值(例如,进入机密或试验例)是有用的。它可以产生整数,longs,uuid或字符串,如以下示例所示:

  1. my:
  2. secret: "${random.value}"
  3. number: "${random.int}"
  4. bignumber: "${random.long}"
  5. uuid: "${random.uuid}"
  6. number-less-than-ten: "${random.int(10)}"
  7. number-in-range: "${random.int[1024,65536]}"

类型安全的配置属性

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