外部化配置
Spring Boot可以外部化配置,以便可以在不同环境中使用相同的应用程序代码。
您可以使用各种外部配置源,包括Java属性文件,YAML文件,环境变量和命令行参数。
属性值可以通过直接注射到你的bean@Value注释,通过Spring的访问Environment抽象,或者通过@ConfigurationProperties绑定到Bean对象。
Spring Boot使用一个非常特殊的PropertySource顺序,该顺序旨在允许合理地覆盖值。按以下顺序考虑属性(较低项的值覆盖较早项的值):
- 默认属性(通过设置指定
SpringApplication.setDefaultProperties)。 @PropertySource@Configuration类上的注释。请注意,Environment在刷新应用程序上下文之前,不会将此类属性源添加到中。现在配置某些属性(如logging.*和spring.main.*在刷新开始之前先读取)为时已晚。- 配置数据(例如
application.properties文件) - 一
RandomValuePropertySource,只有在拥有性能random.*。 - 操作系统环境变量。
- Java系统属性(
System.getProperties())。 - 的JNDI属性
java:comp/env。 ServletContext初始化参数。ServletConfig初始化参数。- 来自的属性
SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的嵌入式JSON)。 - 命令行参数。
properties测试中的属性。可用于测试应用程序的特定部分@SpringBootTest的测试注释和注释。@TestPropertySource测试中的注释。$HOME/.config/spring-boot当devtools处于活动状态时,目录中的Devtools全局设置属性。
配置数据文件按以下顺序考虑:
- 打包在jar中的应用程序属性(
application.properties和YAML变体)。 - 打包在jar中的特定于配置文件的应用程序属性(
application-{profile}.properties和YAML变体)。 - 打包的jar(
application.properties和YAML变体)之外的应用程序属性。 - 打包的jar(
application-{profile}.properties和YAML变体)之外的特定于配置文件的应用程序属性。
为了提供一个具体的示例,假设您开发了一个@Component使用name属性的,如以下示例所示:
import org.springframework.stereotype.*;import org.springframework.beans.factory.annotation.*;@Componentpublic class MyBean {@Value("${name}")private String name;// ...}
在您的应用程序类路径上(例如,在jar内),您可以使用一个application.properties文件,该文件为提供合理的默认属性值name。在新环境中运行时,application.properties可以在jar外部提供一个文件,该文件将覆盖name。对于一次性测试,可以使用特定的命令行开关(例如,java -jar app.jar --name="Spring")启动。
外部应用程序属性
春天开机就会自动查找和加载application.properties和application.yaml应用程序启动时的文件从以下位置:
- 类路径根
- 类路径
/config包 - 当前目录
/config当前目录中的子目录- 的的直接子目录
/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/,则考虑的位置的完整集合为:
optional:classpath:custom-config/optional:file:./custom-config/
如果您希望添加其他位置,而不是替换它们,则可以使用spring.config.additional-location。从其他位置加载的属性可以覆盖默认位置的属性。例如,如果spring.config.additional-location使用value进行配置,则所optional:classpath:/custom-config/,optional:file:./custom-config/考虑的位置的完整集合为:
optional:classpath:/optional:classpath:/config/optional:file:./optional:file:./config/optional:file:./config/*/optional:classpath:custom-config/optional:file:./custom-config/
通过此搜索顺序,您可以在一个配置文件中指定默认值,然后在另一个配置文件中有选择地覆盖这些值。您可以在以下默认位置之一为您的应用程序提供默认值application.properties(或您选择的任何其他基本名称spring.config.name)。然后,可以在运行时使用自定义位置之一中的其他文件覆盖这些默认值。
可选位置
默认情况下,当指定的配置数据位置不存在时,Spring Boot将抛出,ConfigDataLocationNotFoundException并且您的应用程序将不会启动。
如果要指定位置,但不介意它并不总是存在,则可以使用optional:前缀。您可以将此前缀与spring.config.location和spring.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.location和spring.config.additional-location属性使用通配符位置。
配置文件专用文件
除了application属性文件,Spring Boot还将尝试使用命名约定来加载特定于配置文件的文件application-{profile}。例如,如果你的应用程序启动了一个名为轮廓prod,并使用YAML文件,然后双方application.yml并application-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文件中可能包含以下内容:
spring:application:name: "myapp"config:import: "optional:file:./dev.properties"
这将触发dev.properties当前目录中文件的导入(如果存在这样的文件)。来自导入的值dev.properties将优先于触发导入的文件。在上面的示例中,dev.properties可以重新定义spring.application.name为其他值。不论声明多少次,导入都只会导入一次。在properties / yaml文件中的单个文档中定义导入的顺序无关紧要
导入无扩展名文件
某些云平台无法将文件扩展名添加到已装入卷的文件中。要导入这些无扩展名的文件,您需要给Spring Boot一个提示,以便它知道如何加载它们。您可以通过在方括号中添加扩展提示来做到这一点。
例如,假设您有一个/etc/config/myconfig要导入为yaml的文件。您可以application.properties使用以下方法从中导入它:
spring:config:import: "file:/etc/config/myconfig[.yaml]"
使用配置树
在云平台上运行应用程序(例如Kubernetes)时,您通常需要读取平台提供的配置值。为此目的使用环境变量并不罕见,但是这样做可能会有弊端,特别是如果该值应该保密的话。
作为环境变量的替代方法,许多云平台现在允许您将配置映射到装入的数据卷中。例如,Kubernetes可以批量挂载ConfigMaps和Secrets。
可以使用两种常见的卷安装模式:
- 单个文件包含完整的属性集(通常写为YAML)。
- 多个文件被写入目录树,文件名成为“键”,内容成为“值”。
对于第一种情况,你可以直接导入使用YAML或属性文件中spring.config.import所描述的以上。对于第二种情况,您需要使用configtree:前缀,以便Spring Boot知道它需要将所有文件公开为属性。
作为示例,让我们想象一下Kubernetes已经安装了以下卷:
etc/config/myapp/usernamepassword
该username文件的内容将是一个配置值,而其中的内容password将是一个秘密。
要导入这些属性,可以将以下内容添加到您的application.properties或application.yaml文件中:
spring:config:import: "optional:configtree:/etc/config/"
然后,您可以按照通常的方式从中访问或注入myapp.username和myapp.password属性Environment。
如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。任何configtree:以结尾结尾的位置/*/都将所有直接子级导入为配置树。
例如,给定以下卷:
etc/config/dbconfig/db/usernamepasswordmqconfig/mq/usernamepassword
您可以configtree:/etc/config/*/用作导入位置:
spring:config:import: "optional:configtree:/etc/config/*/"
财产占位符
使用中的application.properties和时,它们中的值application.yml会通过现有过滤器过滤Environment,因此您可以参考以前定义的值(例如,从“系统”属性中)。标准的${name}property-placeholder语法可以在值中的任何位置使用。
例如,以下文件将设置app.description为“ MyApp是Spring Boot应用程序”:
app:name: "MyApp"description: "${app.name} is a Spring Boot application"
处理多文档文件
Spring Boot允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档独立添加。从上到下按顺序处理文档。以后的文档可以覆盖以前的文档中定义的属性。
对于application.yml文件,使用标准的YAML多文档语法。三个连续的连字符代表一个文档的末尾,以及下一个文档的开始。
例如,以下文件具有两个逻辑文档:
spring.application.name: MyApp---spring.config.activate.on-cloud-platform: kubernetesspring.application.name: MyCloudApp
对于application.properties文件,特殊#---注释用于标记文档拆分:
spring.application.name=MyApp#---spring.config.activate.on-cloud-platform=kubernetesspring.application.name=MyCloudApp
激活属性
有时仅在满足某些条件时才激活给定的属性获取,这很有用。例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用来有条件地激活属性文档spring.config.activate.*。
可以使用以下激活属性:
表2.激活属性
| 属性 | 注意 |
|---|---|
on-profile |
必须匹配才能使文档处于活动状态的配置文件表达式。 |
on-cloud-platform |
在CloudPlatform必须对文件进行检测活跃。 |
例如,以下内容指定仅当在Kubernetes上运行时并且仅当“ prod”或“ staging”配置文件处于活动状态时,第二个文档才处于活动状态:
myprop:always-set---spring:config:activate:on-cloud-platform: "kubernetes"on-profile: "prod | staging"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或字符串,如以下示例所示:
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]}"
类型安全的配置属性
使用@Value("${property}")注释注入配置属性有时会很麻烦,尤其是当您使用多个属性或数据本质上是分层的时。Spring Boot提供了一种使用属性的替代方法,该方法使强类型的Bean可以管理和验证应用程序的配置。
