此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.1! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.1! |
Spring Boot 允许您将配置外部化,以便您可以在不同的环境中使用相同的应用程序代码。 您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以使用注解直接注入到你的 Bean 中,通过 Spring 的抽象访问,或者通过 .@Value
Environment
@ConfigurationProperties
Spring Boot 使用非常特殊的顺序,旨在允许合理地覆盖值。
较晚的属性源可以覆盖较早属性源中定义的值。
按以下顺序考虑来源:PropertySource
-
默认属性(由设置指定)。
SpringApplication.setDefaultProperties
-
@PropertySource
对类的注释。 请注意,在刷新应用程序上下文之前,不会将此类属性源添加到 中。 配置某些属性(例如在刷新开始之前读取的属性)为时已晚。@Configuration
Environment
logging.*
spring.main.*
-
配置数据(例如文件)。
application.properties
-
仅在 中具有属性的 A 。
RandomValuePropertySource
random.*
-
操作系统环境变量。
-
Java 系统属性 ()。
System.getProperties()
-
JNDI 属性来自 .
java:comp/env
-
ServletContext
init 参数。 -
ServletConfig
init 参数。 -
属性来自(嵌入在环境变量或系统属性中的内联 JSON)。
SPRING_APPLICATION_JSON
-
命令行参数。
-
properties
属性。 在@SpringBootTest
上可用,以及用于测试应用程序特定切片的测试注释。 -
在测试中
@DynamicPropertySource
注释。 -
@TestPropertySource
测试的注释。 -
devtools 处于活动状态时目录中的 Devtools 全局设置属性。
$HOME/.config/spring-boot
按以下顺序考虑配置文件:
-
打包在 jar 中的应用程序属性(和 YAML 变体)。
application.properties
-
打包在 jar 中的特定于配置文件的应用程序属性(和 YAML 变体)。
application-{profile}.properties
-
打包的 jar 之外的应用程序属性(和 YAML 变体)。
application.properties
-
打包的 jar(和 YAML 变体)之外的特定于配置文件的应用程序属性。
application-{profile}.properties
建议为您的整个应用程序坚持使用一种格式。
如果在同一位置具有同时具有 YAML 格式的配置文件,则优先。.properties .properties |
如果使用环境变量而不是系统属性,则大多数操作系统不允许使用句点分隔的键名,但您可以改用下划线(例如,代替 )。
有关详细信息,请参阅从环境变量绑定。SPRING_CONFIG_NAME spring.config.name |
如果应用程序在 servlet 容器或应用程序服务器中运行,那么可以使用 JNDI 属性(在 中)或 Servlet 上下文初始化参数来代替环境变量或系统属性。java:comp/env |
为了提供一个具体示例,假设您开发了一个使用属性的属性,如以下示例所示:@Component
name
-
Java
-
Kotlin
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.properties
name
application.properties
name
java -jar app.jar --name="Spring"
和 终结点可用于确定属性具有特定值的原因。
可以使用这两个终结点来诊断意外的属性值。
有关详细信息,请参阅“生产就绪功能”部分。env configprops |
建议为您的整个应用程序坚持使用一种格式。
如果在同一位置具有同时具有 YAML 格式的配置文件,则优先。.properties .properties |
如果使用环境变量而不是系统属性,则大多数操作系统不允许使用句点分隔的键名,但您可以改用下划线(例如,代替 )。
有关详细信息,请参阅从环境变量绑定。SPRING_CONFIG_NAME spring.config.name |
如果应用程序在 servlet 容器或应用程序服务器中运行,那么可以使用 JNDI 属性(在 中)或 Servlet 上下文初始化参数来代替环境变量或系统属性。java:comp/env |
和 终结点可用于确定属性具有特定值的原因。
可以使用这两个终结点来诊断意外的属性值。
有关详细信息,请参阅“生产就绪功能”部分。env configprops |
访问命令行属性
默认情况下,将任何命令行选项参数(即以 开头的参数,例如 )转换为 a,并将它们添加到 Spring .
如前所述,命令行属性始终优先于基于文件的属性源。SpringApplication
--
--server.port=9000
property
Environment
如果不希望将命令行属性添加到 中,可以使用 禁用它们。Environment
SpringApplication.setAddCommandLineProperties(false)
JSON 应用程序属性
环境变量和系统属性通常具有限制,这意味着某些属性名称不能使用。 为了帮助解决这个问题,Spring Boot 允许您将属性块编码为单个 JSON 结构。
当应用程序启动时,将分析任何 or 属性并将其添加到 .spring.application.json
SPRING_APPLICATION_JSON
Environment
例如,可以在 UN*X shell 的命令行中作为环境变量提供该属性:SPRING_APPLICATION_JSON
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,您最终会得到 Spring .my.name=test
Environment
也可以将相同的 JSON 作为系统属性提供:
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
或者,您可以使用命令行参数提供 JSON:
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
如果要部署到经典 Application Server,那么还可以使用名为 的 JNDI 变量。java:comp/env/spring.application.json
尽管 JSON 中的值将添加到生成的属性源中,但会将属性视为缺失值。
这意味着 JSON 无法使用值覆盖来自低阶属性源的属性。null PropertySourcesPropertyResolver null null |
尽管 JSON 中的值将添加到生成的属性源中,但会将属性视为缺失值。
这意味着 JSON 无法使用值覆盖来自低阶属性源的属性。null PropertySourcesPropertyResolver null null |
外部应用程序属性
当应用程序启动时,Spring Boot 将自动从以下位置查找和加载文件:application.properties
application.yaml
-
从类路径
-
类路径根
-
classpath 包
/config
-
-
从当前目录
-
当前目录
-
当前目录中的子目录
config/
-
子目录的直接子目录
config/
-
该列表按优先级排序(较低项的值将覆盖较早的项)。
加载文件中的文档将添加到 Spring .PropertySources
Environment
如果您不喜欢作为配置文件名,可以通过指定环境属性切换到另一个文件名。
例如,若要查找和文件,可以按如下方式运行应用程序:application
spring.config.name
myproject.properties
myproject.yaml
$ java -jar myproject.jar --spring.config.name=myproject
还可以使用 environment 属性引用显式位置。
此属性接受要检查的一个或多个位置的逗号分隔列表。spring.config.location
下面的示例演示如何指定两个不同的文件:
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
如果位置是可选的,并且您不介意它们不存在,请使用前缀。optional: |
spring.config.name 、 和 很早就用于确定必须加载哪些文件。
它们必须定义为环境属性(通常是操作系统环境变量、系统属性或命令行参数)。spring.config.location spring.config.additional-location |
如果包含目录(而不是文件),则它们应以 结尾。
在运行时,它们将附加加载之前生成的名称。
中指定的文件将直接导入。spring.config.location
/
spring.config.name
spring.config.location
目录和文件位置值也会展开,以检查特定于配置文件的文件。
例如,如果你有一个 ,你也会发现加载了相应的文件。spring.config.location classpath:myconfig.properties classpath:myconfig-<profile>.properties |
在大多数情况下,您添加的每个项目都将引用一个文件或目录。
位置按照定义位置的顺序进行处理,后面的位置可以覆盖前面位置的值。spring.config.location
如果您有一个复杂的位置设置,并且您使用特定于配置文件的配置文件,则可能需要提供进一步的提示,以便 Spring Boot 知道应该如何对它们进行分组。
位置组是所有位置的集合,这些位置都被视为同一级别。
例如,您可能希望对所有类路径位置进行分组,然后对所有外部位置进行分组。
位置组中的项目应用 分隔。
有关详细信息,请参阅“配置文件特定文件”一节中的示例。;
使用配置的位置将替换默认位置。
例如,如果配置了值 ,则考虑的完整位置集为:spring.config.location
spring.config.location
optional:classpath:/custom-config/,optional:file:./custom-config/
-
optional:classpath:custom-config/
-
optional:file:./custom-config/
如果您希望添加其他位置,而不是替换它们,则可以使用 .
从其他位置加载的属性可以覆盖默认位置中的属性。
例如,如果配置了值 ,则考虑的完整位置集为:spring.config.additional-location
spring.config.additional-location
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
如果要指定位置,但不介意它并不总是存在,则可以使用前缀。
您可以将此前缀与 and 属性以及 spring.config.import
声明一起使用。optional:
spring.config.location
spring.config.additional-location
例如,值 允许应用程序启动,即使缺少文件也是如此。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 包含在默认搜索位置中。
这意味着将搜索 jar 之外目录的所有子目录。config/*/
/config
您可以自己将通配符位置与 and 属性一起使用。spring.config.location
spring.config.additional-location
通配符位置必须只包含一个,并且对于作为目录的搜索位置或作为文件的搜索位置,必须以结尾。
带有通配符的位置根据文件名的绝对路径按字母顺序排序。* */ */<filename> |
通配符位置仅适用于外部目录。
不能在某个位置使用通配符。classpath: |
配置文件特定文件
除了属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件。
例如,如果应用程序激活了名为 YAML 文件并使用的配置文件,则将同时考虑两者。application
application-{profile}
prod
application.yaml
application-prod.yaml
特定于配置文件的属性从与标准相同的位置加载,特定于配置文件的文件始终覆盖非特定文件。
如果指定了多个配置文件,则应用“最后获胜”策略。
例如,如果配置文件是由属性指定的,则 中的值可以被 中的值覆盖。application.properties
prod,live
spring.profiles.active
application-prod.properties
application-live.properties
“后赢”策略适用于营业地点组级别。
的 不会有与 相同的覆盖规则。 例如,继续上面的示例,我们可能有以下文件: /cfg application-live.properties /ext application-live.properties application-prod.properties 当我们有一个 我们处理所有文件之前处理所有文件:
当我们有(使用分隔符)时,我们处理并处于同一级别:
|
具有一组默认配置文件(默认为 ),如果未设置活动配置文件,则使用这些配置文件。
换言之,如果未显式激活配置文件,则考虑 from 的属性。Environment
[default]
application-default
属性文件只加载一次。 如果已直接导入配置文件特定的属性文件,则不会再次导入该文件。 |
导入其他数据
应用程序属性可以使用该属性从其他位置导入更多配置数据。
进口在发现时进行处理,并被视为紧接在申报进口的单据下方插入的附加单据。spring.config.import
例如,类路径文件中可能包含以下内容:application.properties
-
Properties
-
YAML
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
无论申报多少次,进口都只会导入一次。 在 properties/yaml 文件的单个文档中定义导入的顺序无关紧要。 例如,下面的两个示例会产生相同的结果:
-
Properties
-
YAML
spring.config.import=my.properties
my.property=value
spring:
config:
import: "my.properties"
my:
property: "value"
-
Properties
-
YAML
my.property=value
spring.config.import=my.properties
my:
property: "value"
spring:
config:
import: "my.properties"
在上述两个示例中,文件中的值将优先于触发其导入的文件。my.properties
可以在单个键下指定多个位置。
位置将按照定义的顺序进行处理,以后的导入优先。spring.config.import
在适当的情况下,还会考虑导入特定于配置文件的变体。
上面的示例将同时导入以及任何变体。my.properties my-<profile>.properties |
Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和“配置树”。 第三方 jar 可以提供对其他技术的支持(不要求文件是本地的)。 例如,您可以想象配置数据来自外部存储,例如 Consul、Apache ZooKeeper 或 Netflix Archaius。 如果要支持自己的位置,请参阅包中的 和 类。 |
导入无扩展名文件
某些云平台无法将文件扩展名添加到卷装载文件。 要导入这些无扩展名文件,您需要给 Spring Boot 一个提示,以便它知道如何加载它们。 您可以通过在方括号中放置扩展提示来执行此操作。
例如,假设您有一个要导入为 yaml 的文件。
您可以使用以下方法从中导入它:/etc/config/myconfig
application.properties
-
Properties
-
YAML
spring.config.import=file:/etc/config/myconfig[.yaml]
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
使用配置树
在云平台(如 Kubernetes)上运行应用程序时,通常需要读取平台提供的配置值。 将环境变量用于此类目的并不少见,但这可能有缺点,尤其是在该值应该保密的情况下。
可以使用两种常见的卷装载模式:
-
单个文件包含一组完整的属性(通常编写为 YAML)。
-
多个文件被写入目录树,文件名成为“键”,内容成为“值”。
对于第一种情况,您可以直接使用上述方法导入 YAML 或 Properties 文件。
对于第二种情况,您需要使用前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。spring.config.import
configtree:
举个例子,假设 Kubernetes 挂载了以下卷:
etc/
config/
myapp/
username
password
文件的内容将是配置值,而文件的内容将是机密。username
password
若要导入这些属性,可以将以下内容添加到 or 文件中:application.properties
application.yaml
-
Properties
-
YAML
spring.config.import=optional:configtree:/etc/config/
spring:
config:
import: "optional:configtree:/etc/config/"
然后,您可以以通常的方式从中访问或注入属性。myapp.username
myapp.password
Environment
配置树下的文件夹和文件的名称构成属性名称。
在上面的示例中,要访问属性 as 和 ,可以设置为 。username password spring.config.import optional:configtree:/etc/config/myapp |
带有点表示法的文件名也被正确映射。
例如,在上面的示例中,名为 in 的文件将导致 .myapp.username /etc/config myapp.username Environment |
配置树值可以绑定到字符串和类型,具体取决于预期的内容。String byte[] |
如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。
任何以 结尾的位置都会将所有直接子项导入为配置树。
与非通配符导入一样,每个配置树下的文件夹和文件的名称构成属性名称。configtree:
/*/
例如,给定以下体积:
etc/
config/
dbconfig/
db/
username
password
mqconfig/
mq/
username
password
您可以用作导入位置:configtree:/etc/config/*/
-
Properties
-
YAML
spring.config.import=optional:configtree:/etc/config/*/
spring:
config:
import: "optional:configtree:/etc/config/*/"
这将添加 、 和 属性。db.username
db.password
mq.username
mq.password
使用通配符加载的目录按字母顺序排序。 如果您需要不同的订单,则应将每个位置列为单独的导入 |
配置树也可用于 Docker 机密。
当 Docker 群服务被授予对机密的访问权限时,该机密将挂载到容器中。
例如,如果一个名为 的密钥挂载在 位置 ,则可以使用以下命令对 Spring 环境使用:db.password
/run/secrets/
db.password
-
Properties
-
YAML
spring.config.import=optional:configtree:/run/secrets/
spring:
config:
import: "optional:configtree:/run/secrets/"
属性占位符
中使用 和 中的值时会通过现有值进行筛选,因此您可以回溯以前定义的值(例如,从系统属性或环境变量中引用)。
标准属性占位符语法可以在值内的任何位置使用。
属性占位符还可以使用 a 指定默认值,以将默认值与属性名称分开,例如 。application.properties
application.yaml
Environment
${name}
:
${name:default}
以下示例显示了带和不带默认值的占位符的使用:
-
Properties
-
YAML
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
应始终使用占位符中的规范形式(仅使用小写字母的 kebab-case)引用属性名称。
这将允许Spring Boot使用与放松绑定时相同的逻辑。 例如,将从文件以及系统环境中拾取和形成。
如果您改用,则不会被考虑。 |
您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅使用“短”命令行参数操作方法。 |
使用多文档文件
Spring Boot 允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档都是独立添加的。 文档按顺序从上到下处理。 后续文档可以覆盖早期文档中定义的属性。
对于文件,使用标准的 YAML 多文档语法。
三个连续的连字符表示一个文档的结束和下一个文档的开始。application.yaml
例如,以下文件有两个逻辑文档:
spring:
application:
name: "MyApp"
---
spring:
application:
name: "MyCloudApp"
config:
activate:
on-cloud-platform: "kubernetes"
对于文件,使用特殊或注释来标记文档拆分:application.properties
#---
!---
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
属性文件分隔符不得有任何前导空格,并且必须正好有三个连字符。 分隔符前后的行不得为相同的注释前缀。 |
多文档属性文件通常与激活属性(如 )结合使用。
有关详细信息,请参阅下一节。spring.config.activate.on-profile |
无法使用 或 批注加载多文档属性文件。@PropertySource @TestPropertySource |
激活属性
有时,仅在满足某些条件时才激活一组给定的属性很有用。 例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用 有条件地激活属性文档。spring.config.activate.*
可以使用以下激活属性:
财产 | 注意 |
---|---|
|
一个配置文件表达式,必须匹配该表达式才能使文档处于活动状态。 |
|
必须检测到该文档才能处于活动状态。 |
例如,以下内容指定第二个文档仅在 Kubernetes 上运行时处于活动状态,并且仅当“prod”或“staging”配置文件处于活动状态时才处于活动状态:
-
Properties
-
YAML
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.location spring.config.additional-location |
目录和文件位置值也会展开,以检查特定于配置文件的文件。
例如,如果你有一个 ,你也会发现加载了相应的文件。spring.config.location classpath:myconfig.properties classpath:myconfig-<profile>.properties |
通配符位置必须只包含一个,并且对于作为目录的搜索位置或作为文件的搜索位置,必须以结尾。
带有通配符的位置根据文件名的绝对路径按字母顺序排序。* */ */<filename> |
通配符位置仅适用于外部目录。
不能在某个位置使用通配符。classpath: |
“后赢”策略适用于营业地点组级别。
的 不会有与 相同的覆盖规则。 例如,继续上面的示例,我们可能有以下文件: /cfg application-live.properties /ext application-live.properties application-prod.properties 当我们有一个 我们处理所有文件之前处理所有文件:
当我们有(使用分隔符)时,我们处理并处于同一级别:
|
属性文件只加载一次。 如果已直接导入配置文件特定的属性文件,则不会再次导入该文件。 |
在适当的情况下,还会考虑导入特定于配置文件的变体。
上面的示例将同时导入以及任何变体。my.properties my-<profile>.properties |
Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和“配置树”。 第三方 jar 可以提供对其他技术的支持(不要求文件是本地的)。 例如,您可以想象配置数据来自外部存储,例如 Consul、Apache ZooKeeper 或 Netflix Archaius。 如果要支持自己的位置,请参阅包中的 和 类。 |
配置树下的文件夹和文件的名称构成属性名称。
在上面的示例中,要访问属性 as 和 ,可以设置为 。username password spring.config.import optional:configtree:/etc/config/myapp |
带有点表示法的文件名也被正确映射。
例如,在上面的示例中,名为 in 的文件将导致 .myapp.username /etc/config myapp.username Environment |
配置树值可以绑定到字符串和类型,具体取决于预期的内容。String byte[] |
使用通配符加载的目录按字母顺序排序。 如果您需要不同的订单,则应将每个位置列为单独的导入 |
应始终使用占位符中的规范形式(仅使用小写字母的 kebab-case)引用属性名称。
这将允许Spring Boot使用与放松绑定时相同的逻辑。 例如,将从文件以及系统环境中拾取和形成。
如果您改用,则不会被考虑。 |
您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅使用“短”命令行参数操作方法。 |
属性文件分隔符不得有任何前导空格,并且必须正好有三个连字符。 分隔符前后的行不得为相同的注释前缀。 |
多文档属性文件通常与激活属性(如 )结合使用。
有关详细信息,请参阅下一节。spring.config.activate.on-profile |
无法使用 或 批注加载多文档属性文件。@PropertySource @TestPropertySource |
财产 | 注意 |
---|---|
|
一个配置文件表达式,必须匹配该表达式才能使文档处于活动状态。 |
|
必须检测到该文档才能处于活动状态。 |
加密属性
Spring Boot 不提供任何对加密属性值的内置支持,但是,它确实提供了修改 Spring 中包含的值所需的挂钩点。
该界面允许您在应用程序启动之前操作。
有关详细信息,请参阅在启动之前自定义环境或 ApplicationContext。Environment
EnvironmentPostProcessor
Environment
如果您需要一种安全的方式来存储凭据和密码,Spring Cloud Vault 项目支持在 HashiCorp Vault 中存储外部化配置。
使用 YAML
如果使用 “Starters”,则 SnakeYAML 会自动由 提供。spring-boot-starter |
将 YAML 映射到属性
YAML 文档需要从其分层格式转换为可与 Spring 一起使用的平面结构。
例如,请考虑以下 YAML 文档:Environment
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
为了从 访问这些属性,它们将被平展,如下所示:Environment
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]
my:
servers:
- "dev.example.com"
- "another.example.com"
前面的示例将转换为以下属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
使用表示法的属性可以绑定到 Java 或使用 Spring Boot 类的对象。
有关详细信息,请参阅下面的“类型安全配置属性”部分。[index] List Set Binder |
无法使用 或 注释加载 YAML 文件。
因此,如果需要以这种方式加载值,则需要使用属性文件。@PropertySource @TestPropertySource |
如果使用 “Starters”,则 SnakeYAML 会自动由 提供。spring-boot-starter |
使用表示法的属性可以绑定到 Java 或使用 Spring Boot 类的对象。
有关详细信息,请参阅下面的“类型安全配置属性”部分。[index] List Set Binder |
无法使用 或 注释加载 YAML 文件。
因此,如果需要以这种方式加载值,则需要使用属性文件。@PropertySource @TestPropertySource |
配置随机值
这对于注入随机值(例如,注入机密或测试用例)很有用。
它可以生成整数、长、uuid 或字符串,如以下示例所示:RandomValuePropertySource
-
Properties
-
YAML
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 Boot 支持为环境属性设置前缀。
如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将非常有用。
系统环境属性的前缀可以直接设置在 上。SpringApplication
例如,如果将前缀设置为 ,则 之类的属性也将像在系统环境中一样进行解析。input
remote.timeout
input.remote.timeout
类型安全配置属性
使用批注注入配置属性有时可能很麻烦,尤其是在使用多个属性或数据本质上是分层的时。
Spring Boot 提供了一种处理属性的替代方法,该方法允许强类型 Bean 管理和验证应用程序的配置。@Value("${property}")
另请参阅@Value 和类型安全配置属性之间的差异。 |
JavaBean 属性绑定
可以绑定声明标准 JavaBean 属性的 Bean,如以下示例所示:
-
Java
-
Kotlin
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 定义了以下属性:
-
my.service.enabled
,默认值为 。false
-
my.service.remote-address
,具有可以从 中强制执行的类型。String
-
my.service.security.username
,带有嵌套的“security”对象,其名称由属性的名称确定。 特别是,那里根本没有使用该类型,并且可能是.SecurityProperties
-
my.service.security.password
. -
my.service.security.roles
,其集合默认为 。String
USER
映射到 Spring Boot 中可用类的属性(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。@ConfigurationProperties |
这种排列依赖于默认的空构造函数,并且 getter 和 setter 通常是必需的,因为绑定是通过标准的 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。 在以下情况下,可以省略二传手:
有些人使用 Project Lombok 自动添加 getter 和 setter。 确保 Lombok 不会为此类类型生成任何特定构造函数,因为容器会自动使用它来实例化对象。 最后,只考虑标准的 Java Bean 属性,不支持绑定静态属性。 |
构造函数绑定
上一节中的示例可以以不可变的方式重写,如以下示例所示:
-
Java
-
Kotlin
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
@Autowired
private
@ConstructorBinding
构造函数绑定类的嵌套成员(如上面的示例中所示)也将通过其构造函数进行绑定。Security
可以使用构造函数参数和记录组件指定默认值。
转换服务将应用于将注释的值强制为缺失属性的目标类型。@DefaultValue
String
参考前面的示例,如果没有绑定到 的属性,则实例将包含 的值。
要使它包含一个非 null 实例,即使没有绑定任何属性(当使用 Kotlin 时,这将需要将 和 参数声明为可为 null,因为它们没有默认值),请使用空注解:Security
MyProperties
null
security
Security
username
password
Security
@DefaultValue
-
Java
-
Kotlin
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 和 .-parameters spring-boot-starter-parent |
不建议使用 with,因为它主要用作返回类型。
因此,它不太适合配置属性注入。
为了与其他类型的属性保持一致,如果声明了一个属性并且它没有值,则将绑定一个空。java.util.Optional @ConfigurationProperties Optional null Optional |
启用@ConfigurationProperties批注类型
Spring Boot 提供了绑定类型并将它们注册为 Bean 的基础结构。
您可以逐类启用配置属性,也可以启用与组件扫描类似的配置属性扫描。@ConfigurationProperties
有时,带注释的类可能不适合扫描,例如,如果您正在开发自己的自动配置,或者想要有条件地启用它们。
在这些情况下,请指定要使用批注处理的类型列表。
这可以在任何类上完成,如以下示例所示:@ConfigurationProperties
@EnableConfigurationProperties
@Configuration
-
Java
-
Kotlin
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
-
Java
-
Kotlin
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
-
Java
-
Kotlin
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 的完全限定名称。 假设它在包中,上面示例的 bean 名称是 。 |
我们建议只处理环境,特别是不要从上下文中注入其他 Bean。
对于极端情况,可以使用 setter 注入或框架提供的任何接口(例如,如果您需要访问 )。
如果仍想使用构造函数注入其他 Bean,则必须使用基于 JavaBean 的属性绑定来注释配置属性 bean。@ConfigurationProperties
*Aware
EnvironmentAware
Environment
@Component
使用@ConfigurationProperties批注类型
这种配置方式特别适用于外部 YAML 配置,如以下示例所示:SpringApplication
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
要使用 Bean,可以采用与任何其他 Bean 相同的方式注入它们,如以下示例所示:@ConfigurationProperties
-
Java
-
Kotlin
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
@Bean
要从属性配置 Bean,请添加到其 Bean 注册中,如以下示例所示:Environment
@ConfigurationProperties
-
Java
-
Kotlin
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。another
AnotherComponent
SomeProperties
宽松的绑定
Spring Boot 使用一些宽松的规则将属性绑定到 bean,因此属性名称和 bean 属性名称之间不需要完全匹配。
有用的常见示例包括破折号分隔的环境属性(例如,binds to )和大写的环境属性(例如,binds to )。Environment
@ConfigurationProperties
Environment
context-path
contextPath
PORT
port
例如,请考虑以下类:@ConfigurationProperties
-
Java
-
Kotlin
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
}
在前面的代码中,可以使用以下属性名称:
财产 | 注意 |
---|---|
|
烤肉串大小写,建议在 YAML 文件中使用。 |
|
标准骆驼大小写语法。 |
|
下划线表示法,这是用于 YAML 文件的替代格式。 |
|
大写格式,建议在使用系统环境变量时使用。 |
注释的值必须采用烤肉串大小写(小写并用 分隔,例如 )。prefix - my.main-project.person |
属性来源 | 简单 | 列表 |
---|---|---|
属性文件 |
骆驼盒、烤肉串盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
YAML文件 |
骆驼盒、烤肉串盒或下划线符号 |
标准 YAML 列表语法或逗号分隔值 |
环境变量 |
大写格式,下划线作为分隔符(请参阅从环境变量绑定)。 |
用下划线括起来的数值(请参阅从环境变量绑定) |
系统属性 |
骆驼盒、烤肉串盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
我们建议尽可能以小写的烤肉串格式存储属性,例如 .my.person.first-name=Rod |
绑定映射
绑定到属性时,可能需要使用特殊的括号表示法,以便保留原始值。
如果键未被 括起来,则任何非字母数字字符或被删除。Map
key
[]
-
.
例如,考虑将以下属性绑定到 :Map<String,String>
-
Properties
-
YAML
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
/key2
key3
key3
绑定到标量值时,包含其中的键不需要用 括起来。
标量值包括枚举和包中除 之外的所有类型。
绑定到将保留 in 键,并返回一个包含条目的 Map。
对于任何其他类型,如果包含 .
例如,绑定到将返回一个包含条目的 Map,而将返回一个包含条目的 Map。.
[]
java.lang
Object
a.b=c
Map<String, String>
.
{"a.b"="c"}
key
.
a.b=c
Map<String, Object>
{"a"={"b"="c"}}
[a.b]=c
{"a.b"="c"}
从环境变量绑定
大多数操作系统对可用于环境变量的名称施加了严格的规则。
例如,Linux shell 变量只能包含字母 ( to 或 to )、数字 ( to ) 或下划线字符 ()。
按照惯例,Unix shell 变量的名称也将为大写。a
z
A
Z
0
9
_
Spring Boot 宽松的绑定规则尽可能地与这些命名限制兼容。
若要将规范形式的属性名称转换为环境变量名称,可以遵循以下规则:
-
将点()替换为下划线()。
.
_
-
删除所有破折号 ()。
-
-
转换为大写。
例如,配置属性将是名为 的环境变量。spring.main.log-startup-info
SPRING_MAIN_LOGSTARTUPINFO
绑定到对象列表时,也可以使用环境变量。
要绑定到 ,元素编号应在变量名称中用下划线括起来。List
例如,配置属性将使用名为 的环境变量。my.service[0].other
MY_SERVICE_0_OTHER
合并复杂类型
当在多个位置配置列表时,通过替换整个列表来覆盖工作。
例如,假设一个对象具有默认的 和 属性。
以下示例公开以下对象的列表:MyPojo
name
description
null
MyPojo
MyProperties
-
Java
-
Kotlin
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()
}
请考虑以下配置:
-
Properties
-
YAML
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
在多个配置文件中指定 a 时,将使用优先级最高的配置文件(并且仅使用该配置文件)。
请看以下示例:List
-
Properties
-
YAML
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 列表都可用于完全覆盖列表的内容。dev
MyProperties.list
MyPojo
my another name
null
对于属性,可以使用从多个源提取的属性值进行绑定。
但是,对于多个源中的同一属性,将使用优先级最高的属性。
以下示例公开了 from :Map
Map<String, MyPojo>
MyProperties
-
Java
-
Kotlin
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()
}
请考虑以下配置:
-
Properties
-
YAML
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 为 )。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 Boot 在绑定到 Bean 时会尝试将外部应用程序属性强制为正确的类型。
如果需要自定义类型转换,可以提供 bean(带有名为 的 bean)或自定义属性编辑器(通过 bean)或自定义(bean 定义注释为 )。@ConfigurationProperties
ConversionService
conversionService
CustomEditorConfigurer
Converters
@ConfigurationPropertiesBinding
由于此 Bean 是在应用程序生命周期的早期请求的,因此请确保限制您正在使用的依赖项。
通常,所需的任何依赖项在创建时可能不会完全初始化。
如果配置键强制不需要自定义,并且仅依赖符合 .ConversionService ConversionService @ConfigurationPropertiesBinding |
转换持续时间
Spring Boot 专门支持表达持续时间。
如果公开属性,则应用程序属性中的以下格式可用:java.time.Duration
-
常规表示(使用毫秒作为默认单位,除非已指定 a)
long
@DurationUnit
-
java.time.Duration
使用的标准 ISO-8601 格式 -
一种更易读的格式,其中值和单位耦合(表示 10 秒)
10s
请看以下示例:
-
Java
-
Kotlin
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 的读取超时可以指定为以下任一形式:和 。30
PT30S
30s
500
PT0.5S
500ms
您也可以使用任何受支持的设备。 这些是:
-
ns
纳秒 -
us
微秒 -
ms
毫秒 -
s
几秒钟 -
m
几分钟 -
h
数小时 -
d
几天
默认单位为毫秒,可以使用上面的示例中所示进行覆盖。@DurationUnit
如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
-
Java
-
Kotlin
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.Period
-
常规表示(除非已指定 a,否则使用天作为默认单位)
int
@PeriodUnit
-
java.time.Period
使用的标准 ISO-8601 格式 -
一种更简单的格式,其中值和单位对耦合(表示 1 年零 3 天)
1y3d
简单格式支持以下单位:
-
y
多年来 -
m
几个月 -
w
数周 -
d
几天
该类型实际上从不存储周数,它是一种快捷方式,表示“7 天”。java.time.Period |
转换数据大小
Spring Framework 具有以字节为单位表示大小的值类型。
如果公开属性,则应用程序属性中的以下格式可用:DataSize
DataSize
-
常规表示形式(使用字节作为默认单位,除非已指定 a)
long
@DataSizeUnit
-
一种更具可读性的格式,其中值和单位耦合(表示 10 兆字节)
10MB
请看以下示例:
-
Java
-
Kotlin
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 字节的大小阈值可以指定为 或 。10
10MB
256
256B
您也可以使用任何受支持的设备。 这些是:
-
B
对于字节 -
KB
千字节 -
MB
兆字节 -
GB
千兆字节 -
TB
TB
默认单位为字节,可以使用上面的示例中所示进行覆盖。@DataSizeUnit
如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
-
Java
-
Kotlin
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
@Validated
jakarta.validation
-
Java
-
Kotlin
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
-
Java
-
Kotlin
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,而无需实例化类。
这样做可以避免早期实例化可能导致的任何问题。Validator
configurationPropertiesValidator
@Bean
static
@Bean
@Configuration
该模块包括一个公开所有 Bean 的端点。
将 Web 浏览器指向或使用等效的 JMX 端点。
有关详细信息,请参阅“生产就绪功能”部分。spring-boot-actuator @ConfigurationProperties /actuator/configprops |
@ConfigurationProperties 与 @Value
批注是核心容器功能,它不提供与类型安全配置属性相同的功能。
下表总结了 和 支持的功能:@Value
@ConfigurationProperties
@Value
特征 | @ConfigurationProperties |
@Value |
---|---|---|
是的 |
有限(见下面的注释) |
|
是的 |
不 |
|
|
不 |
是的 |
如果确实要使用 ,我们建议您使用属性名称的规范形式(仅使用小写字母的 kebab-case)来引用属性名称。
这将允许Spring Boot使用与放松绑定时相同的逻辑。 例如,将从文件以及系统环境中拾取和形成。
如果您改用,则不会被考虑。 |
如果您为自己的组件定义了一组配置键,我们建议您将它们分组到用 注释的 POJO 中。
这样做将为您提供结构化的、类型安全的对象,您可以将其注入到自己的 Bean 中。@ConfigurationProperties
SpEL
在分析应用程序属性文件中的表达式并填充环境时,不会处理这些表达式。
但是,可以在 中写入表达式。
如果应用程序属性文件中的属性值是表达式,则在通过 .SpEL
@Value
SpEL
@Value
另请参阅@Value 和类型安全配置属性之间的差异。 |
映射到 Spring Boot 中可用类的属性(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。@ConfigurationProperties |
这种排列依赖于默认的空构造函数,并且 getter 和 setter 通常是必需的,因为绑定是通过标准的 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。 在以下情况下,可以省略二传手:
有些人使用 Project Lombok 自动添加 getter 和 setter。 确保 Lombok 不会为此类类型生成任何特定构造函数,因为容器会自动使用它来实例化对象。 最后,只考虑标准的 Java Bean 属性,不支持绑定静态属性。 |
若要使用构造函数绑定,必须使用或配置属性扫描来启用类。
不能将构造函数绑定用于由常规 Spring 机制创建的 Bean(例如,Bean、使用方法创建的 Bean 或使用@EnableConfigurationProperties @Component @Bean @Import )
|
若要使用构造函数绑定,必须使用 编译类。
如果您使用 Spring Boot 的 Gradle 插件,或者使用 Maven 和 .-parameters spring-boot-starter-parent |
不建议使用 with,因为它主要用作返回类型。
因此,它不太适合配置属性注入。
为了与其他类型的属性保持一致,如果声明了一个属性并且它没有值,则将绑定一个空。java.util.Optional @ConfigurationProperties Optional null Optional |
当使用配置属性扫描或通过 注册 Bean 时,Bean 具有约定名称: ,其中是在注释中指定的环境键前缀,并且是 Bean 的完全限定名称。
如果注释未提供任何前缀,则仅使用 Bean 的完全限定名称。 假设它在包中,上面示例的 bean 名称是 。 |
使用还允许您生成元数据文件,IDE 可以使用这些文件为您自己的密钥提供自动完成功能。
详见附录。@ConfigurationProperties |
财产 | 注意 |
---|---|
|
烤肉串大小写,建议在 YAML 文件中使用。 |
|
标准骆驼大小写语法。 |
|
下划线表示法,这是用于 YAML 文件的替代格式。 |
|
大写格式,建议在使用系统环境变量时使用。 |
注释的值必须采用烤肉串大小写(小写并用 分隔,例如 )。prefix - my.main-project.person |
属性来源 | 简单 | 列表 |
---|---|---|
属性文件 |
骆驼盒、烤肉串盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
YAML文件 |
骆驼盒、烤肉串盒或下划线符号 |
标准 YAML 列表语法或逗号分隔值 |
环境变量 |
大写格式,下划线作为分隔符(请参阅从环境变量绑定)。 |
用下划线括起来的数值(请参阅从环境变量绑定) |
系统属性 |
骆驼盒、烤肉串盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
我们建议尽可能以小写的烤肉串格式存储属性,例如 .my.person.first-name=Rod |
对于 YAML 文件,括号需要用引号括起来,以便正确解析键。 |
上述合并规则适用于所有属性源中的属性,而不仅仅是文件。 |
由于此 Bean 是在应用程序生命周期的早期请求的,因此请确保限制您正在使用的依赖项。
通常,所需的任何依赖项在创建时可能不会完全初始化。
如果配置键强制不需要自定义,并且仅依赖符合 .ConversionService ConversionService @ConfigurationPropertiesBinding |
如果要升级属性,请确保定义单位(使用 ),如果单位不是毫秒。
这样做可以提供透明的升级路径,同时支持更丰富的格式。Long @DurationUnit |
该类型实际上从不存储周数,它是一种快捷方式,表示“7 天”。java.time.Period |
如果要升级属性,请确保定义单位(使用 ),如果它不是字节。
这样做可以提供透明的升级路径,同时支持更丰富的格式。Long @DataSizeUnit |
还可以通过使用 . 对创建配置属性的方法进行批注来触发验证。@Bean @Validated |
该模块包括一个公开所有 Bean 的端点。
将 Web 浏览器指向或使用等效的 JMX 端点。
有关详细信息,请参阅“生产就绪功能”部分。spring-boot-actuator @ConfigurationProperties /actuator/configprops |
特征 | @ConfigurationProperties |
@Value |
---|---|---|
是的 |
有限(见下面的注释) |
|
是的 |
不 |
|
|
不 |
是的 |
如果确实要使用 ,我们建议您使用属性名称的规范形式(仅使用小写字母的 kebab-case)来引用属性名称。
这将允许Spring Boot使用与放松绑定时相同的逻辑。 例如,将从文件以及系统环境中拾取和形成。
如果您改用,则不会被考虑。 |