外部化配置
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.*;
@Component
public 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.location
environment属性(目录位置或文件路径的逗号分隔列表)来引用显式位置。以下示例显示如何指定其他文件名:
$ 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/
username
password
该username
文件的内容将是一个配置值,而其中的内容password
将是一个秘密。
要导入这些属性,可以将以下内容添加到您的application.properties
或application.yaml
文件中:
spring:
config:
import: "optional:configtree:/etc/config/"
然后,您可以按照通常的方式从中访问或注入myapp.username
和myapp.password
属性Environment
。
如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。任何configtree:
以结尾结尾的位置/*/
都将所有直接子级导入为配置树。
例如,给定以下卷:
etc/
config/
dbconfig/
db/
username
password
mqconfig/
mq/
username
password
您可以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: kubernetes
spring.application.name: MyCloudApp
对于application.properties
文件,特殊#---
注释用于标记文档拆分:
spring.application.name=MyApp
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.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可以管理和验证应用程序的配置。