对于最新的稳定版本,请使用 Spring Boot 3.4.0! |
外部化配置
Spring Boot 允许您外部化配置,以便您可以在不同环境中使用相同的应用程序代码。 您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以通过使用@Value
注解,通过 Spring 的Environment
抽象,或通过@ConfigurationProperties
.
Spring Boot 使用非常特殊的PropertySource
order 的 ORDER 允许合理地覆盖值。
后面的属性源可以覆盖前面的属性源中定义的值。
按以下顺序考虑源:
-
默认属性(通过设置
SpringApplication.setDefaultProperties(Map)
). -
@PropertySource
annotations@Configuration
类。 请注意,此类属性源不会添加到Environment
直到刷新应用程序上下文。 现在配置某些属性(例如logging.*
和spring.main.*
,这些 API 将在刷新开始之前读取。 -
配置数据(例如
application.properties
文件)。 -
一个
RandomValuePropertySource
仅在random.*
. -
OS 环境变量。
-
Java 系统属性 (
System.getProperties()
). -
JNDI 属性来自
java:comp/env
. -
ServletContext
init 参数。 -
ServletConfig
init 参数。 -
属性来自
SPRING_APPLICATION_JSON
(嵌入在环境变量或系统属性中的内联 JSON)。 -
命令行参数。
-
properties
属性。 适用于@SpringBootTest
以及用于测试应用程序的特定切片的 test annotations。 -
@TestPropertySource
Comments 的 Comments。 -
Devtools 全局设置属性
$HOME/.config/spring-boot
目录(当 DevTools 处于活动状态时)。
配置数据文件按以下顺序考虑:
-
打包在 jar 中的 Application 属性 (
application.properties
和 YAML 变体)。 -
打包在 jar 中的 Profile 特定应用程序属性 (
application-{profile}.properties
和 YAML 变体)。 -
打包的 jar 之外的应用程序属性 (
application.properties
和 YAML 变体)。 -
打包的 jar 之外特定于配置文件的应用程序属性 (
application-{profile}.properties
和 YAML 变体)。
建议整个应用程序坚持使用一种格式。
如果您的配置文件同时包含.properties 和 YAML 格式,则.properties 优先。 |
如果使用环境变量而不是系统属性,则大多数作系统不允许使用句点分隔的键名称,但您可以使用下划线代替(例如SPRING_CONFIG_NAME 而不是spring.config.name ).
有关详细信息,请参阅从环境变量绑定。 |
如果您的应用程序在 servlet 容器或应用程序服务器中运行,则 JNDI 属性(在java:comp/env ) 或 Servlet 上下文初始化参数来代替环境变量或系统属性。 |
为了提供一个具体的例子,假设您开发了一个@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 中),您可以有一个application.properties
文件,该文件为name
.
在新环境中运行时,application.properties
文件可以在 jar 外部提供,该文件会覆盖name
.
对于一次性测试,您可以使用特定的命令行开关(例如java -jar app.jar --name="Spring"
).
这env 和configprops endpoints 可用于确定属性具有特定值的原因。
您可以使用这两个终端节点来诊断意外的属性值。
有关详细信息,请参阅 生产就绪功能 部分。 |
访问命令行属性
默认情况下,SpringApplication
转换任何命令行选项参数(即以 开头的参数,例如--
--server.port=9000
) 转换为property
并将它们添加到 Spring 中Environment
.
如前所述,命令行属性始终优先于基于文件的属性源。
如果您不希望将命令行属性添加到Environment
中,您可以使用SpringApplication.setAddCommandLineProperties(false)
.
JSON 应用程序属性
环境变量和系统属性通常具有限制,这意味着无法使用某些属性名称。 为了帮助解决这个问题, Spring Boot 允许您将一个属性块编码为单个 JSON 结构。
当您的应用程序启动时,任何spring.application.json
或SPRING_APPLICATION_JSON
properties 将被解析并添加到Environment
.
例如,SPRING_APPLICATION_JSON
property 可以作为环境变量在 UN*X shell 的命令行中提供:
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,您最终会得到my.name=test
在SpringEnvironment
.
相同的 JSON 也可以作为系统属性提供:
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
或者,您可以使用命令行参数提供 JSON:
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
如果要部署到经典 Application Server,还可以使用名为java:comp/env/spring.application.json
.
虽然null JSON 中的值将添加到生成的属性源中,PropertySourcesPropertyResolver 对待null properties 作为缺失值。
这意味着 JSON 无法使用null 价值。 |
外部应用程序属性
Spring Boot 将自动查找并加载application.properties
和application.yaml
应用程序启动时从以下位置获取的文件:
-
从 classpath
-
类路径根
-
类路径
/config
包
-
-
从当前目录
-
当前目录
-
这
config/
子目录 -
的直接子目录
config/
子目录
-
该列表按优先级排序(较低项中的值将覆盖较早项的值)。
加载文件中的文档将添加为PropertySource
实例添加到 SpringEnvironment
.
如果您不喜欢application
作为配置文件名称,您可以通过指定spring.config.name
environment 属性。
例如,要查找myproject.properties
和myproject.yaml
文件,您可以按如下方式运行应用程序:
$ java -jar myproject.jar --spring.config.name=myproject
您还可以使用spring.config.location
environment 属性。
此属性接受要检查的一个或多个位置的逗号分隔列表。
以下示例显示如何指定两个不同的文件:
$ 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 很早就用于确定必须加载哪些文件。
它们必须定义为环境属性(通常是 OS 环境变量、系统属性或命令行参数)。 |
如果spring.config.location
包含目录(而不是文件),它们应以 .
在运行时,它们将附加从/
spring.config.name
在加载之前。
在spring.config.location
直接导入。
目录和文件位置值也都进行了扩展,以检查特定于配置文件的文件。
例如,如果你有一个spring.config.location 之classpath:myconfig.properties ,您也会找到合适的classpath:myconfig-<profile>.properties 文件。 |
在大多数情况下,每个spring.config.location
项将引用单个文件或目录。
位置按其定义顺序进行处理,较晚的位置可以覆盖较早的位置的值。
如果你有一个复杂的位置设置,并且你使用特定于配置文件的配置文件,你可能需要提供进一步的提示,以便 Spring Boot 知道应该如何对它们进行分组。
位置组是所有位置都被视为同一级别的位置的集合。
例如,您可能希望对所有 Classpath 位置进行分组,然后对所有外部位置进行分组。
位置组中的项目应以 分隔。
有关更多详细信息,请参阅 Profile Specific Files 部分中的示例。;
使用 配置 Locationspring.config.location
替换 Default Locations。
例如,如果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
(或您选择的任何其他 basenamespring.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
文件丢失。
如果要忽略所有ConfigDataLocationNotFoundException
错误并始终继续启动应用程序,您可以使用spring.config.on-not-found
财产。
将值设置为ignore
用SpringApplication.setDefaultProperties(…)
或使用 system/environment 变量。
通配符位置
如果配置文件位置包含最后一个路径段的字符,则将其视为通配符位置。
加载配置时,通配符会展开,以便同时检查直接子目录。
通配符位置在 Kubernetes 等环境中,当有多个 config 属性来源时特别有用。*
例如,如果您有一些 Redis 配置和一些 MySQL 配置,您可能希望将这两个配置分开,同时要求这两个配置都存在于application.properties
文件。
这可能会导致两个单独的application.properties
文件挂载在不同位置,例如/config/redis/application.properties
和/config/mysql/application.properties
.
在这种情况下,将通配符位置设置为config/*/
)将导致两个文件都被处理。
默认情况下,Spring Boot 包括config/*/
在默认搜索位置。
这意味着/config
目录中。
您可以自己将通配符位置与spring.config.location
和spring.config.additional-location
性能。
通配符位置必须仅包含一个通配符位置,并且对于目录或* */ */<filename> 对于作为文件的搜索位置。
带有通配符的位置根据文件名的绝对路径按字母顺序排序。 |
通配符位置仅适用于外部目录。
您不能在classpath: 位置。 |
配置文件特定
以及application
property 文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}
.
例如,如果您的应用程序激活了名为prod
并使用 YAML 文件,那么两者application.yaml
和application-prod.yaml
将被考虑。
特定于配置文件的属性从与标准相同的位置加载application.properties
,特定于配置文件的文件始终覆盖非特定文件。
如果指定了多个配置文件,则适用 last-wins 策略。
例如,如果配置文件prod,live
由spring.profiles.active
属性, 值application-prod.properties
可以被application-live.properties
.
“最后获胜”策略适用于营业地点组级别。
一个 例如,继续我们的 /cfg application-live.properties /ext application-live.properties application-prod.properties 当我们有一个
当我们有
|
这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
file 将优先于触发其导入的文件。
可以在单个spring.config.import
钥匙。
位置将按照定义的顺序进行处理,以后的导入优先。
在适当时,还会考虑导入特定于 Profile 的变体。
上面的示例将导入my.properties 以及任何my-<profile>.properties 变种。 |
Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和配置树。 第三方 jar 可以提供对其他技术的支持(不要求文件是本地的)。 例如,您可以想象配置数据来自 Consul、Apache ZooKeeper 或 Netflix Archaius 等外部存储。 如果要支持自己的位置,请参阅 |
导入无扩展名文件
某些云平台无法向卷挂载的文件添加文件扩展名。 要导入这些无扩展名文件,你需要给 Spring Boot 一个提示,以便它知道如何加载它们。 您可以通过在方括号中放置扩展提示来执行此作。
例如,假设您有一个/etc/config/myconfig
要作为 YAML 导入的文件。
您可以从application.properties
使用以下内容:
-
Properties
-
YAML
spring.config.import=file:/etc/config/myconfig[.yaml]
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
使用配置树
在云平台(如 Kubernetes)上运行应用程序时,您通常需要读取平台提供的配置值。 将环境变量用于此类目的并不少见,但这可能有缺点,尤其是在值应该保密的情况下。
作为环境变量的替代方案,许多云平台现在允许您将配置映射到挂载的数据卷。
例如,Kubernetes 可以同时对ConfigMaps
和Secrets
.
可以使用两种常见的卷挂载模式:
-
单个文件包含一组完整的属性(通常写为 YAML)。
-
多个文件被写入目录树,文件名成为 'key',内容成为 'value'。
对于第一种情况,您可以直接使用spring.config.import
如上所述。
对于第二种情况,您需要使用configtree:
前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。
例如,假设 Kubernetes 挂载了以下卷:
etc/
config/
myapp/
username
password
的username
file 将是一个 config 值,而password
将是一个秘密。
要导入这些属性,您可以将以下内容添加到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
以通常的方式。
配置树下的文件夹和文件的名称构成属性名称。
在上面的示例中,要将属性作为username 和password 中,您可以设置spring.config.import 自optional:configtree:/etc/config/myapp . |
带有点表示法的文件名也会正确映射。
例如,在上面的示例中,名为myapp.username 在/etc/config 将导致myapp.username 属性在Environment . |
配置树值可以绑定到两个字符串String 和byte[] 类型。 |
如果要从同一个父文件夹导入多个配置树,则可以使用通配符快捷方式。
任何configtree:
location 结尾的 Location 会将所有直接子项作为配置树导入。
与非通配符导入一样,每个配置树下的文件夹和文件的名称构成属性名称。/*/
例如,给定以下卷:
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 Swarm 服务被授予对 secret 的访问权限时,secret 将被挂载到容器中。
例如,如果名为db.password
安装在/run/secrets/
,您可以使db.password
可用于 Spring 环境:
-
Properties
-
YAML
spring.config.import=optional:configtree:/run/secrets/
spring:
config:
import: "optional:configtree:/run/secrets/"
属性占位符
中的 valueapplication.properties
和application.yaml
通过现有的Environment
,以便您可以参考以前定义的值(例如,从 System properties 或 environment variables)。
标准${name}
property-placeholder 语法可以在值中的任何位置使用。
属性占位符还可以使用:
将默认值与属性名称分开,例如${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
property 没有在其他位置设置,app.description
将具有值MyApp is a Spring Boot application written by Unknown
.
您应该始终使用其规范形式(kebab-case 仅使用小写字母)在占位符中引用属性名称。
这将允许 Spring Boot 使用与松散绑定时相同的逻辑 例如 |
您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅 “How-to Guides” 中的 Use 'short' Command Line Arguments 部分。 |
使用多文档文件
Spring Boot 允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档都是独立添加的。 文档按从上到下的顺序处理。 后面的文档可以覆盖前面文档中定义的属性。
为application.yaml
文件,则使用标准的 YAML 多文档语法。
三个连续的连字符表示一个文档的结尾和下一个文档的开头。
例如,以下文件有两个逻辑文档:
spring:
application:
name: "MyApp"
---
spring:
application:
name: "MyCloudApp"
config:
activate:
on-cloud-platform: "kubernetes"
为application.properties
文件,一个特殊的或#---
!---
comment 用于标记文档拆分:
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
属性文件分隔符不得有任何前导空格,并且必须恰好包含三个连字符。 紧接在分隔符之前和之后的行不能是相同的注释前缀。 |
多文档属性文件通常与激活属性结合使用,例如spring.config.activate.on-profile .
有关详细信息,请参阅下一节。 |
激活属性
有时,仅在满足某些条件时激活一组给定的属性很有用。 例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用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"
加密属性
Spring Boot 不提供对加密属性值的任何内置支持,但是,它确实提供了修改 Spring 中包含的值所需的钩子点Environment
.
这EnvironmentPostProcessor
界面允许您作Environment
在应用程序启动之前。
有关详细信息,请参见Customize the Environment 或 ApplicationContext Before It Started。
如果你需要一种安全的方式来存储凭证和密码,Spring Cloud Vault 项目提供了在 HashiCorp Vault 中存储外部化配置的支持。
使用 YAML
YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。
这SpringApplication
每当 Classpath 上有 SnakeYAML 库时,class 都会自动支持 YAML 作为属性的替代方案。
如果您使用Starters,则 SnakeYAML 由spring-boot-starter . |
将 YAML 映射到属性
YAML 文档需要从它们的分层格式转换为可以与 Spring 一起使用的平面结构Environment
.
例如,请考虑以下 YAML 文档:
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 列表也需要扁平化。
它们表示为属性键,其中[index]
dereferencers 的 dereferencers。
例如,请考虑以下 YAML:
my:
servers:
- "dev.example.com"
- "another.example.com"
前面的示例将转换为以下属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
无法使用@PropertySource 或@TestPropertySource 附注。
因此,如果需要以这种方式加载值,则需要使用属性文件。 |
直接加载 YAML
Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。
这YamlPropertiesFactoryBean
将 YAML 加载为Properties
和YamlMapFactoryBean
将 YAML 加载为Map
.
您还可以使用YamlPropertySourceLoader
class (如果要将 YAML 加载为 Spring)PropertySource
.
配置随机值
这RandomValuePropertySource
对于注入随机值(例如,注入 secret 或测试用例)非常有用。
它可以生成整数、长整型、uuid 或字符串,如以下示例所示:
-
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*
syntax 为OPEN value (,max) CLOSE
其中,OPEN,CLOSE
是任何字符,并且value,max
是整数。
如果max
,则value
是最小值,而max
是最大值 (不包括)。
配置系统环境属性
Spring Boot 支持为环境属性设置前缀。
如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将非常有用。
系统环境属性的前缀可以直接在SpringApplication
.
例如,如果将前缀设置为input
,则remote.timeout
也将解析为input.remote.timeout
在系统环境中。
类型安全的配置属性
使用@Value("${property}")
Annotation 来注入配置属性有时会很麻烦,特别是当你正在使用多个属性或者你的数据本质上是分层的。
Spring Boot 提供了一种使用属性的替代方法,该方法允许强类型 bean 管理和验证应用程序的配置。
另请参阅 @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
.
映射到@ConfigurationProperties Spring Boot 中可用的类(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共 API,但类本身的访问器(getter/setter)不能直接使用。 |
这种安排依赖于默认的空构造函数,并且 getter 和 setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。 在以下情况下,可以省略 setter:
有些人使用 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>)
}
在此设置中,存在单个参数化构造函数意味着应使用构造函数绑定。
这意味着 Binder 将找到一个构造函数,其中包含您希望绑定的参数。
如果您的类有多个构造函数,则@ConstructorBinding
annotation 可用于指定要用于构造函数绑定的构造函数。
要选择退出具有单个参数化构造函数的类的构造函数绑定,必须为构造函数添加@Autowired
或制造private
.
构造函数绑定可以与记录一起使用。
除非您的记录具有多个构造函数,否则无需使用@ConstructorBinding
.
构造函数绑定类的嵌套成员(例如Security
在上面的示例中)也将通过其构造函数进行绑定。
默认值可以使用@DefaultValue
on constructor parameters 和 record components.
转换服务将用于强制注释的String
value 设置为缺失属性的目标类型。
参考前面的示例,如果没有属性绑定到Security
这MyProperties
实例将包含一个null
的值security
.
要使其包含Security
即使没有绑定到任何属性(使用 Kotlin 时,这也需要username
和password
参数Security
要声明为可为 null,因为它们没有默认值),请使用空的@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>)
}
要使用构造函数绑定,必须使用@EnableConfigurationProperties 或配置属性 scanning。
你不能将构造函数绑定与由常规 Spring 机制创建的 bean 一起使用(例如@Component bean, 使用 创建的 bean@Bean 方法或 bean@Import )
|
要使用构造函数绑定,必须使用-parameters .
如果您使用 Spring Boot 的 Gradle 插件,或者如果您使用 Maven 和spring-boot-starter-parent . |
的使用Optional 跟@ConfigurationProperties 不建议使用,因为它主要用作返回类型。
因此,它不太适合 configuration property injection。
为了与其他类型的属性保持一致,如果您确实声明了Optional property 并且它没有值,null 而不是空的Optional 将被绑定。 |
要在属性名称中使用 reserved 关键字,例如my.service.import ,请使用@Name annotation 的 Constructor 参数。 |
启用 @ConfigurationProperties 注释类型
Spring Boot 提供了用于绑定的基础设施@ConfigurationProperties
类型并将它们注册为 Bean。
您可以逐个类启用配置属性,也可以启用配置属性扫描,其工作方式与组件扫描类似。
有时,用@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
类。
默认情况下,将从声明 Comments 的类的包中进行扫描。
如果要定义要扫描的特定包,可以按以下示例所示执行此作:
-
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
当 假设它在 |
我们建议@ConfigurationProperties
仅处理环境,特别是,不从上下文中注入其他 bean。
对于极端情况,可以使用 setter 注入或任何*Aware
框架提供的接口(例如EnvironmentAware
如果您需要访问Environment
).
如果您仍然希望使用构造函数注入其他 bean,则必须使用@Component
并使用基于 JavaBean 的属性绑定。
使用 @ConfigurationProperties 注释的类型
这种配置样式特别适用于SpringApplication
external YAML 配置,如以下示例所示:
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
使用@ConfigurationProperties
beans 中,你可以像注入任何其他 bean 一样注入它们,如以下示例所示:
-
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()
// ...
}
// ...
}
用@ConfigurationProperties 还允许您生成元数据文件,IDE 可以使用这些文件为您自己的键提供自动完成功能。
有关详细信息,请参阅附录。 |
第三方配置
除了使用@ConfigurationProperties
要对类进行注释,您还可以在 public 上使用它@Bean
方法。
当您希望将属性绑定到不受控制的第三方组件时,这样做可能特别有用。
要从Environment
properties (属性),添加@ConfigurationProperties
添加到其 bean 注册中,如以下示例所示:
-
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()
}
使用another
prefix 映射到该AnotherComponent
bean 以类似于前面的方式SomeProperties
例。
松散绑定
Spring Boot 使用一些宽松的规则进行绑定Environment
properties 设置为@ConfigurationProperties
beans,因此Environment
property name 和 bean property name 的 bean 属性名称。
这有用的常见示例包括以破折号分隔的环境属性(例如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
}
使用上述代码,可以使用以下属性名称:
财产 | 注意 |
---|---|
|
烤肉盒,推荐用于 |
|
标准 Camel 大小写语法。 |
|
下划线表示法,这是 |
|
大写格式,使用系统环境变量时推荐使用。 |
这prefix 值必须采用 kebab 大小写(小写,并用 、 等- my.main-project.person ). |
Property Source | 简单 | 列表 |
---|---|---|
属性文件 |
驼峰式大小写、kebab 大小写或下划线表示法 |
使用 或 逗号分隔值的标准列表语法 |
YAML 文件 |
驼峰式大小写、kebab 大小写或下划线表示法 |
标准 YAML 列表语法或逗号分隔值 |
环境变量 |
大写格式,下划线作为分隔符(请参阅从环境变量绑定)。 |
用下划线括起来的数值(请参见从环境变量绑定) |
系统属性 |
驼峰式大小写、kebab 大小写或下划线表示法 |
使用 或 逗号分隔值的标准列表语法 |
我们建议尽可能以小写 kebab 格式存储属性,例如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 文件,括号需要用引号括起来,以便正确解析键。 |
上面的属性将绑定到Map
跟/key1
,/key2
和key3
作为映射中的键。
斜杠已从key3
因为它没有被方括号包围。
当绑定到标量值时,带有.
在它们中不需要被 .
标量值包括 enum 和[]
java.lang
包(除Object
.
捆绑a.b=c
自Map<String, String>
将保留.
并返回一个 Map,并返回一个 Map,其中包含{"a.b"="c"}
.
对于任何其他类型,如果你的key
包含一个.
.
例如,将a.b=c
自Map<String, Object>
将返回一个 Map,其中包含{"a"={"b"="c"}}
而[a.b]=c
将返回一个 Map,其中包含{"a.b"="c"}
.
从环境变量绑定
大多数作系统对可用于环境变量的名称施加了严格的规则。
例如,Linux shell 变量只能包含字母 (a
自z
或A
自Z
)、数字 (0
自9
) 或下划线字符 ()。
按照惯例,Unix shell 变量的名称也将采用 UPPERCASE。_
Spring Boot 的宽松绑定规则尽可能地设计为与这些命名限制兼容。
要将 canonical-form 中的属性名称转换为环境变量名称,您可以遵循以下规则:
-
替换点 (
.
) 并带有下划线 ()。_
-
删除所有破折号 ()。
-
-
转换为大写。
例如,configuration 属性spring.main.log-startup-info
将是名为SPRING_MAIN_LOGSTARTUPINFO
.
绑定到对象列表时,也可以使用环境变量。
要绑定到List
,元素编号应在变量名称中用下划线括起来。
例如,configuration 属性my.service[0].other
将使用名为MY_SERVICE_0_OTHER
.
对从环境变量进行绑定的支持应用于systemEnvironment
property source 以及名称以-systemEnvironment
.
从环境变量绑定映射
当 Spring Boot 将环境变量绑定到属性类时,它会在绑定之前将环境变量名称小写。
大多数情况下,这个细节并不重要,除非绑定到Map
性能。
S 中的 keyMap
始终为小写,如以下示例所示:
-
Java
-
Kotlin
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.props")
public class MyMapsProperties {
private final Map<String, String> values = new HashMap<>();
public Map<String, String> getValues() {
return this.values;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties(prefix = "my.props")
class MyMapsProperties {
val values: Map<String, String> = HashMap()
}
设置MY_PROPS_VALUES_KEY=value
这values
Map
包含一个{"key"="value"}
进入。
只有环境变量名称是小写的,而不是值。
设置MY_PROPS_VALUES_KEY=VALUE
这values
Map
包含一个{"key"="VALUE"}
进入。
缓存
松散绑定使用缓存来提高性能。默认情况下,此缓存仅应用于不可变属性源。
要自定义此行为,例如为可变属性源启用缓存,请使用ConfigurationPropertyCaching
.
合并复杂类型
在多个位置配置列表时,覆盖的工作原理是替换整个列表。
例如,假设MyPojo
object 替换为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
profile 未激活,MyProperties.list
包含一个MyPojo
条目。
如果dev
配置文件,但是,list
仍然只包含一个条目(名称为my another name
以及null
).
此配置不会添加第二个MyPojo
实例添加到列表中,并且不会合并项。
当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"
在前面的示例中,如果dev
profile 处于活动状态,MyProperties.list
包含一个 MyPojo
条目(名称为my another name
以及null
).
对于 YAML,逗号分隔列表和 YAML 列表都可用于完全覆盖列表的内容。
为Map
properties 中,您可以与从多个来源提取的属性值绑定。
但是,对于多个来源中的同一属性,将使用优先级最高的属性。
以下示例公开了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"
如果dev
profile 未激活,MyProperties.map
包含一个带键的条目key1
(名称为my name 1
以及my description 1
).
如果dev
profile 已启用,但是,map
包含两个带键的条目key1
(名称为dev name 1
以及my description 1
) 和key2
(名称为dev name 2
以及dev description 2
).
上述合并规则适用于所有属性源中的属性,而不仅仅是文件。 |
属性转换
Spring Boot 在绑定到@ConfigurationProperties
豆。
如果需要自定义类型转换,可以提供ConversionService
bean(带有一个名为conversionService
) 或自定义属性编辑器(通过CustomEditorConfigurer
bean)或自定义转换器(bean 定义注解为@ConfigurationPropertiesBinding
).
由于此 bean 是在应用程序生命周期的早期请求,因此请确保限制ConversionService 正在使用。
通常,您需要的任何依赖项在创建时可能未完全初始化。
您可能希望重命名您的自定义ConversionService 如果不需要配置键 强制,并且只依赖限定为@ConfigurationPropertiesBinding . |
转换持续时间
Spring Boot 专门支持表示持续时间。
如果您公开了Duration
属性,则应用程序属性中的以下格式可用:
-
常规
long
表示形式(使用毫秒作为默认单位,除非@DurationUnit
已指定) -
值和单位耦合 (
10s
表示 10 秒)
请考虑以下示例:
-
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 秒的会话超时,30
,PT30S
和30s
都是等效的。
可以采用以下任何形式指定 500 毫秒的读取超时: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 还可以使用Period
类型。
应用程序属性中可以使用以下格式:
-
常规
int
表示形式(使用天数作为默认单位,除非@PeriodUnit
已指定) -
一种更简单的格式,其中值和单位对耦合 (
1y3d
指 1 年零 3 天)
简单格式支持以下单位:
-
y
多年来 -
m
几个月 -
w
几周 -
d
几天
这Period type 实际上从未存储过周数,它是一个表示“7 天”的快捷方式。 |
转换数据大小
-
常规
long
表示形式(使用字节作为默认单位,除非@DataSizeUnit
已指定) -
值和单位耦合 (
10MB
表示 10 兆字节)
请考虑以下示例:
-
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 的缓冲区大小,10
和10MB
是等效的。
256 字节的大小阈值可以指定为256
或256B
.
您还可以使用任何受支持的单位。 这些是:
-
B
对于字节 -
KB
对于 KB -
MB
兆字节 -
GB
对于 GB -
TB
对于 TB
默认单位为 bytes,可以使用@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 ) 如果不是 bytes。
这样做提供了透明的升级路径,同时支持更丰富的格式。 |
@ConfigurationProperties验证
Spring Boot 尝试验证@ConfigurationProperties
类,只要它们用 Spring 的@Validated
注解。
您可以使用 JSR-303jakarta.validation
constraint 注解。
为此,请确保 Classpath 上具有兼容的 JSR-303 实现,然后将约束 Comments 添加到字段中,如以下示例所示:
-
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
}
}
您还可以添加自定义 SpringValidator
通过创建一个名为configurationPropertiesValidator
.
这@Bean
method 应该声明static
.
配置属性验证器是在应用程序生命周期的早期创建的,并声明@Bean
方法作为 static,则无需实例化@Configuration
类。
这样做可以避免早期实例化可能导致的任何问题。
这spring-boot-actuator module 包含一个端点,该端点公开所有@ConfigurationProperties 豆。
将 Web 浏览器指向/actuator/configprops 或使用等效的 JMX 终端节点。
有关详细信息,请参阅 生产就绪功能 部分。 |
@ConfigurationProperties vs. @Value
这@Value
Annotation 是容器的核心功能,它不提供与类型安全配置属性相同的功能。
下表总结了 支持 的功能@ConfigurationProperties
和@Value
:
特征 | @ConfigurationProperties |
@Value |
---|---|---|
是的 |
受限(请参阅下面的注释) |
|
是的 |
不 |
|
|
不 |
是的 |
如果您确实想使用 例如 |
如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个 POJO 中,并带有@ConfigurationProperties
.
这样做将为您提供结构化的、类型安全的对象,您可以将其注入到自己的 bean 中。
SpEL
在解析 Application 属性文件和填充环境时,不会处理这些文件中的表达式。
但是,可以编写SpEL
表达式@Value
.
如果应用程序属性文件中的属性值是SpEL
expression 时,它将在 通过@Value
.