|
对于最新稳定版本,请使用Spring Boot 4.0.0! |
外部化配置
Spring Boot 允许你将配置外部化,这样你就能在不同环境中使用相同的应用代码。 您可以使用多种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以通过以下方式直接注入你的豆子@Value注释,可通过Spring的环境抽象,或者通过绑定到结构化对象@ConfigurationProperties.
Spring靴采用了非常特殊的方法地产来源该顺序旨在允许合理覆盖数值。
后期属性源可以覆盖早期定义的值。
资料按以下顺序考虑:
-
默认属性(通过设置指定
SpringApplication.setDefaultProperties(Map)). -
@PropertySource关于你的注释@Configuration类。 请注意,此类属性来源不会被添加到环境直到应用上下文被刷新。 现在配置某些属性已太晚,比如Logging。*和spring.main.*这些数据在刷新开始前阅读。 -
配置数据(例如
application.properties文件)。 -
一个
随机价值属性源仅在 中具有性质随机。*. -
作系统环境变量。
-
Java 系统属性(
System.getProperties()). -
JNDI属性来自
Java:comp/env. -
ServletContext初始化参数。 -
ServletConfig初始化参数。 -
来自的性质
SPRING_APPLICATION_JSON(嵌入环境变量或系统属性中的内联 JSON 文件)。 -
命令行参数。
-
性能在你的测试中写属性。 可于此获得@SpringBootTest以及用于测试应用特定片段的注释。 -
@DynamicPropertySource测试中的注释。 -
@TestPropertySource考试上的注释。 -
Devtools 全局设置属性在
$HOME/.config/spring-boot当DevTools激活时,目录。
配置文件的处理顺序如下:
-
应用属性打包在你的jar里(
application.properties以及YAML变体)。 -
配置档案特定的应用属性打包在你的jar里(
application-{profile}.properties以及YAML变体)。 -
包装罐外的应用属性 (
application.properties以及YAML变体)。 -
在你打包的jar之外的配置文件特定应用属性(
application-{profile}.properties以及YAML变体)。
建议整个申请都坚持使用一种格式。
如果你有包含两个配置文件的话。性能以及同一位置的YAML格式,。性能优先。 |
如果你使用环境变量而非系统属性,大多数作系统不允许使用周期分隔的键名,但你可以用下划线代替(例如,SPRING_CONFIG_NAME而不是spring.config.name).
详情请参见环境变量绑定。 |
如果你的应用运行在servlet容器或应用服务器中,那么JNDI属性(在Java:comp/env可以替代环境变量或系统属性,或同时使用servlet上下文初始化参数。 |
举个具体例子,假设你发展出一个@Component该名称性质,如下例所示:
-
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提供一个合理的默认属性值名称.
在新环境中运行时,一个application.properties可以在你的jar外提供文件,覆盖名称.
对于一次性测试,你可以用特定的命令行开关启动(例如,java -jar app.jar --name=“Spring”).
这环境和配置道具端点对于确定某一属性为何具有特定价值非常有用。
你可以用这两个端点来诊断意外属性值。
详情请参见“生产准备功能”部分。 |
访问命令行属性
默认情况下,SpringApplication转换任意命令行选项参数(即以 开头的参数,例如----server.port=9000)属性并将它们加入泉水环境.
如前所述,命令行属性始终优先于基于文件的属性源。
如果你不想在环境,你可以用以下方式禁用它们SpringApplication.setAddCommandLineProperties(false).
JSON 应用属性
环境变量和系统属性通常有限制,导致某些属性名称无法使用。 为此,Spring Boot 允许你将一组属性编码成一个单一的 JSON 结构。
当你的申请开始时,任何spring.application.json或SPRING_APPLICATION_JSON属性将被解析并添加到环境.
例如,SPRING_APPLICATION_JSON属性可以在 UN*X shell 的命令行中作为环境变量提供:
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
在前面的例子中,你最终得到my.name=test春季环境.
同样的 JSON 也可以作为系统属性提供:
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
或者你可以通过命令行参数提供 JSON:
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
如果你部署到经典应用服务器,也可以使用名为Java:comp/env/spring.application.json.
虽然零JSON 中的值会被添加到生成的属性源中,即PropertySourcesPropertyResolver对待零属性作为缺失值。
这意味着 JSON 不能覆盖来自低阶属性源的属性,且零价值。 |
外部应用属性
Spring Boot 会自动查找并加载application.properties和application.yaml申请开始时,以下地点的文件:
-
从类路径
-
类路径根
-
类路径
/config包
-
-
摘自当前目录
-
现行目录
-
这
配置/当前目录中的子目录 -
该目录的直接子目录
配置/子目录
-
如果你不喜欢应用作为配置文件名,你可以通过指定 a 来切换到另一个文件名spring.config.name环境财产。
例如,寻找myproject.properties和myproject.yaml文件你可以按以下方式运行你的应用程序:
$ java -jar myproject.jar --spring.config.name=myproject
你也可以通过使用spring.config.location环境财产。
该属性接受一个或多个可检查的逗号分隔位置列表。
以下示例展示了如何指定两个不同的文件:
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
使用前缀自选:如果地点是可选的,你也不介意它们不存在。 |
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你的申请不会开始。
如果你想指定一个位置,但不介意它不总是存在,你可以使用自选:前缀。
你可以用这个前缀搭配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财产。
将值设为忽视用SpringApplication.setDefaultProperties(...)或者用系统/环境变量。
外卡位置
如果配置文件位置包含最后路径段的字符,则视为通配符位置。
在加载配置时,万用卡会被展开,这样立即子目录也会被检查。
万用字符位置在像Kubernetes这样有多个配置属性来源的环境中尤其有用。*
例如,如果你有一些 Redis 配置和一些 MySQL 配置,你可能想把这两部分配置分开,同时要求它们都存在于application.properties文件。
这可能导致两份独立的application.properties文件挂载在不同位置,例如/config/redis/application.properties和/config/mysql/application.properties.
在这种情况下,有一个万能字位置配置/*/,将导致两个文件同时被处理。
默认情况下,Spring Boot 包括配置/*/在默认搜索位置。
这意味着所有子目录/config会搜索jar外的目录。
你可以自己用万用卡位置来作spring.config.location和spring.config.additional-location性能。
对于目录或**/*/<文件名>对于作为文件的搜索位置。
带有万用符的位置会根据文件名的绝对路径按字母顺序排序。 |
万用卡位置只能用外部目录。
你不能在Classpath:位置。 |
配置文件专用文件
还有应用属性文件,Spring Boot 还会尝试使用命名规则加载特定配置文件的文件application-{profile}.
例如,如果你的应用程序激活了一个名为刺并且同时使用YAML文件,然后两者兼用application.yaml和application-prod.yaml将被考虑。
配置文件特定的属性从标准位置加载application.properties,且配置文件专用文件总是覆盖非特定文件。
如果指定了多个配置文件,则采用最后获胜策略。
例如,如果制作,直播由春季.档案.活跃属性,值application-prod.properties(应用-生产)属性可以被 以下 覆盖application-live.properties(应用-live.properties).
|
最后赢的策略适用于地点组级。
一个 例如,继续我们的 /cfg application-live.properties /ext application-live.properties application-prod.properties 当我们有
当我们有
|
这环境拥有一组默认配置文件(默认情况下,[默认]如果没有设置活跃配置文件,则会使用。
换句话说,如果没有配置文件被显式激活,那么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换成了不同的数值。
无论申报多少次,进口都会被导入一次。
使用“固定”和“导入亲属”位置
导入可以指定为固定位置或导入相对位置。
固定位置总是解析到相同的底层资源,无论spring.config.import财产被宣告。
导入的相对位置相对于声明spring.config.import财产。
以斜杠()开头的位置或URL风格的前缀(/文件:,Classpath:,等等)被视为固定。
其他所有地点均视为进口相对。
自选:在判断某个地点是否为固定或导入时,不考虑前缀。 |
举个例子,假设我们有/演示包含我们application.jar文件。
我们可以添加一个/demo/application.properties文件内容如下:
spring.config.import=optional:core/core.properties
这是一个导入的相对位置,因此会尝试加载文件/demo/core/core.properties如果它存在的话。
如果/demo/core/core.properties内容如下:
spring.config.import=optional:extra/extra.properties
它会尝试加载/demo/core/extra/extra.properties.
这optional:extra/extra.properties相对于/demo/core/core.properties所以完整的目录是/demo/core/ + extra/extra.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 提示,让它知道如何加载它们。 你可以通过在方括号里加一个扩展提示来实现。
例如,假设你有/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)上运行应用时,你通常需要读取平台提供的配置值。 使用环境变量进行此类用途并不罕见,但这可能存在缺点,尤其是当该值应被保密时。
可以使用两种常见的音量安装模式:
-
单个文件包含完整的属性集合(通常写作 YAML)。
-
多个文件写入目录树,文件名成为“键”,内容作为“值”。
对于第一种情况,你可以直接用 YAML 或属性文件导入spring.config.import如上所述。
对于第二种情况,你需要使用配置树:prefix 让 Spring Boot 知道需要将所有文件作为属性公开。
举个例子,假设Kubernetes已经挂载了以下卷:
etc/
config/
myapp/
username
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来自环境以惯常的方式。
配置文件树下文件夹和文件的名称构成了属性名称。
在上述例子中,要访问性质为用户名和密码,你可以设置spring.config.import自optional:configtree:/etc/config/myapp. |
带有点符号的文件名也会被正确映射。
例如,在上述示例中,一个名为myapp.username在/etc/配置将得到myapp.username财产在环境. |
配置树的值可以绑定到这两个字符串字符串和字节[]类型取决于预期的内容。 |
如果你有多个配置树要从同一个父文件夹导入,可以用通配符快捷方式。
任何配置树:以 结尾的位置将导入所有直接子节点作为配置文件树。
与非万用符导入类似,每个配置文件树下的文件夹和文件名称构成属性名称。/*/
例如,给定以下体积:
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 群服务获得密钥访问权时,该密钥会被挂载到容器中。
例如,如果一个秘密db.password安装在/跑/秘密/,你可以做db.password通过以下方式在Spring环境中提供:
-
Properties
-
YAML
spring.config.import=optional:configtree:/run/secrets/
spring:
config:
import: "optional:configtree:/run/secrets/"
属性占位符
以下数值application.properties和application.yaml通过现有的 进行过滤环境当它们被使用时,你可以回溯到之前定义的值(例如,来自系统属性或环境变量)。
标准${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}"
假设用户名财产未在其他地方设立,应用描述将具有价值MyApp 是由 Unknown 编写的 Spring Boot 应用程序.
|
你应始终用占位符中的属性名称使用规范形式(烤肉大写仅使用小写字母)。
这样Spring Boot就能使用与放松绑定时相同的逻辑 例如 |
| 你也可以用这个技术来创建现有 Spring Boot 属性的“短”变体。 详情请参见“作指南”中“使用”简短命令行参数的部分。 |
处理多文档文件
Spring Boot 允许你将单个物理文件拆分成多个独立添加的逻辑文档。 文件按顺序从上到下处理。 后续文档可以覆盖之前定义的属性。
为application.yaml文件,采用标准的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 上时激活,且仅在“生产”或“准备”配置文件处于激活状态时:
-
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 中值所需的钩点环境.
这环境后处理器接口允许您作环境在申请开始之前。
详情请参见“自定义环境”或“应用上下文”,在它开始之前。
如果您需要安全的方式存储凭证和密码,Spring Cloud Vault 项目支持在 HashiCorp Vault 中存储外部配置。
与YAML合作
YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。
这SpringApplication只要你的类路径上有SnakeYAML库,类会自动支持YAML作为属性的替代方案。
如果你使用起始程序,SnakeYAML会自动由Spring靴Starters. |
将 YAML 映射到 属性
YAML 文档需要从层级格式转换为可与 Spring 配合使用的平面结构环境.
例如,考虑以下 YAML 文档:
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
为了从以下条件访问这些属性环境它们会被压扁如下:
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:
my:
servers:
- "dev.example.com"
- "another.example.com"
上述例子将转化为以下性质:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
YAML 文件无法通过使用@PropertySource或@TestPropertySource附注。
所以,如果你需要用这种方式加载数值,就需要使用属性文件。 |
直接加载 YAML
Spring Framework 提供了两个方便的类,可以用来加载 YAML 文档。
这YamlPropertiesFactoryBean加载 YAML,作为性能以及YamlMapFactoryBean加载 YAML,作为地图.
你也可以使用YamlPropertySourceLoader如果你想把 YAML 加载为 Spring 的话,则 class地产来源.
随机值配置
这随机价值属性源用于注入随机值(例如,注入秘密值或测试用例)。
它可以生成整数、长数、uuids或字符串,如下例所示:
-
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*语法为开盘价(最大值)收盘价其中开,闭是任意字符和价值,最高是整数。
如果麦克斯则值是最小值,麦克斯是最大值(独占值)。
配置系统环境属性
Spring Boot 支持为环境属性设置前缀。
如果系统环境由多个配置要求不同的 Spring Boot 应用程序共享,这非常有用。
系统环境属性的前缀可以直接在SpringApplication通过将setEnvironmentPrefix(...)在应用运行前的方法。
例如,如果你将前缀设置为输入,一个性质,如远程.超时将被解析为INPUT_REMOTE_TIMEOUT在系统环境中。
前缀仅适用于系统环境属性。
上述例子将继续使用远程.超时在阅读其他资料的属性时。 |
类型安全配置属性
使用@Value(“${property}”)注解注入配置属性有时会很繁琐,尤其是当你处理多个属性或数据是层级式的。
Spring Boot 提供了一种处理属性的替代方法,允许强类型 beans 来治理和验证你的应用程序配置。
另见 @Value以及类型安全配置属性。 |
JavaBean 属性绑定
可以绑定一个豆,声明标准JavaBean属性,如下示例所示:
-
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定义了以下性质:
映射到 的性质@ConfigurationPropertiesSpring Boot 中可用的类通过属性文件、YAML 文件、环境变量及其他机制配置,是公开的 API,但该类的访问者(getter/setter)本身并不打算直接使用。 |
|
这种安排依赖于默认的空构造函数,getter和setter通常是必不可少的,因为绑定通过标准Java Beans属性描述符完成,就像Spring MVC一样。 在以下情况下,二传手可能会被省略:
有些人用Project Lombok自动添加采集器和设定。 确保 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或造私人.
Kotlin 开发者可以使用空的主构造函数来选择退出构造器绑定。
例如:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
final MyBean myBean;
private String name;
@Autowired
public MyProperties(MyBean myBean) {
this.myBean = myBean;
}
// getters / setters...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties() {
constructor(name: String) : this() {
this.name = name
}
// vars...
var name: String? = null
}
构造函数装帧可以用于记录。
除非你的记录有多个构造符,否则没必要使用@ConstructorBinding.
构造器界限类的嵌套成员(例如安全在上述示例中,也将被其构造子束缚。
默认值可以通过以下方式指定@DefaultValue关于构造参数和记录组件。
转换服务将被用来强制注释字符串值为缺失属性的目标类型。
参考前述例子,如果没有属性绑定于安全这我的属性实例将包含零值安全.
使其包含非空的实例安全即使没有属性绑定(使用 Kotlin 时,这也需要用户名和密码参数安全声明为可空,因为它们没有默认值),使用@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或配置属性扫描。
你不能用构造者绑定来处理由普通Spring机制产生的豆子(例如)@Component豆子,即通过使用@Bean方法或豆子加载方式为@Import)
|
要使用构造函数绑定,该类必须编译为-参数.
如果你使用 Spring Boot 的 Gradle 插件,或者使用 Maven,这会自动发生Spring靴启动父. |
的使用自选跟@ConfigurationProperties不推荐,因为它主要用于回风类型。
因此,它并不适合用于配置属性注入。
为了与其他类型的性质保持一致,如果你声明自选财产且无价值,零而不是空的自选将被绑定。 |
在物业名称中使用保留关键词,例如my.service.import,使用@Name对构造子参数的注释。 |
启用@ConfigurationProperties注释类型
Spring Boot 提供绑定基础设施@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
|
当 假设它属于 |
我们推荐这样做@ConfigurationProperties只处理环境,特别是不从上下文中注入其他Beans。
对于角点情况,可以使用定位器注入或任何*意识到的框架提供的接口(例如环境感知如果你需要访问环境).
如果你仍想用构造函数注入其他豆子,必须用@Component并使用基于JavaBean的属性绑定。
使用@ConfigurationProperties注释类型
这种配置方式与SpringApplication外部 YAML 配置,如下示例所示:
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
合作方式@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()
// ...
}
// ...
}
用@ConfigurationProperties还允许你生成元数据文件,IDE可以用来自动补全你自己的密钥。
详情请参见附录。 |
第三方配置
以及使用@ConfigurationProperties要注释类,你也可以在公开类中使用@Bean方法。
当你想将属性绑定到不受你控制的第三方组件时,这样做尤其有用。
要配置一个豆子环境性质,添加@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()
}
任何定义为另一个前缀映射到该另一个组件与前述相似的Bean方式某些属性例。
放松绑定
Spring Boot 对绑定规则比较宽松环境性质 到@ConfigurationProperties因此不需要完全匹配环境物业名称和豆子物业名称。
常见的例子包括破折号分离的环境属性(例如,上下文路径绑定为上下文路径),以及大写环境属性(例如,端口绑定为端口).
举个例子,考虑以下情况@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
}
在上述代码中,以下属性名称均可使用:
| 属性 | 注意 |
|---|---|
|
推荐用于烤肉串盒 |
|
标准骆驼箱语法。 |
|
下划线符号,这是一种用于以下用途的替代格式 |
|
使用系统环境变量时推荐使用大写格式。 |
这前缀注释的值必须为烤肉箱大小(小写,并以 分隔,例如-my.main-project.person). |
| 地产来源 | 简单 | 列表 |
|---|---|---|
属性文件 |
骆驼盒、烤肉盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
YAML 文件 |
骆驼盒、烤肉盒或下划线符号 |
标准 YAML 列表语法或逗号分隔值 |
环境变量 |
大写格式,下划线作为分隔符(参见“环境变量绑定”)。 |
数值被下划线包围(参见环境变量绑定) |
系统属性 |
骆驼盒、烤肉盒或下划线符号 |
使用或逗号分隔值的标准列表语法 |
我们建议在可能的情况下,属性以小写的烤肉串格式存储,例如my.person.first-name=Rod. |
绑定地图
当绑定到地图属性,你可能需要使用特殊的括号表示法,以使原始的钥匙价值得以保留。
如果键周围没有,任何非字母数字字符,或[]-.被移除。
例如,考虑将以下属性绑定到地图<字符串,字符串>:
-
Properties
-
YAML
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
my:
map:
"[/key1]": "value1"
"[/key2]": "value2"
"/key3": "value3"
| 对于 YAML 文件,括号外需要用引号包住,这样键的解析才能正确解析。 |
上述性质将绑定为地图跟/key1,/key2和密钥3就像地图上的钥匙一样。
斜杠已被移除密钥3因为它没有被方括号包围。
绑定标量值时,按键为.在它们中,不需要被 包围。
标量值包括枚举以及所有类型[]java.lang包,除了对象.
捆绑a.b=c自映射<字符串,字符串>将保持.在键中返回一个带有元素的映射{“a.b”=“c”}.
对于其他类型,如果你的话,你需要使用括号符号。钥匙包含一个..
例如,绑定a.b=c自Map<String,对象>将返回带有条目的地图{“a”={“b”=“c”}}而[a.b]=c将返回带有条目的地图{“a.b”=“c”}.
环境变量绑定
大多数作系统对可用于环境变量的名称施加严格规则。
例如,Linux shell 变量只能包含字母(一个自z或一个自Z),数字 (0自9)或底划线字符()。
按照惯例,Unix shell 变量的名称也会使用大写字母。_
Spring Boot 宽松的绑定规则尽可能设计以符合这些命名限制。
要将规范形式的属性名称转换为环境变量名称,可以遵循以下规则:
-
替换点(
.)并下划线()。_ -
去除所有破折号()。
- -
转为大写字母。
例如,配置性质spring.main.log-startup-info将是一个环境变量,名为SPRING_MAIN_LOGSTARTUPINFO.
环境变量也可以用于绑定对象列表。
绑定于一个列表元素编号应在变量名中用下划线环绕。
例如,配置性质my.service[0].other将使用一个名为MY_SERVICE_0_OTHER.
对环境变量绑定的支持应用于systemEnvironment属性源,以及任何名称以-systemEnvironment.
从环境变量绑定映射
当 Spring Boot 将环境变量绑定到属性类时,绑定前会把环境变量名小写。
大多数情况下,这个细节并不重要,除非绑定于地图性能。
钥匙在地图总是小写,如下示例所示:
-
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=值这值 地图包含一个{“key”=“value”}进入。
只有环境变量名是小写的,而不是值。
设置时MY_PROPS_VALUES_KEY=值这值 地图包含一个{“key”=“VALUE”}进入。
缓存
宽松绑定使用缓存来提升性能。默认情况下,这种缓存仅应用于不可变属性源。
要自定义此行为,例如启用可变属性源缓存,请使用配置属性缓存.
合并复杂类型
当列表配置在多个地方时,覆盖是通过替换整个列表来实现的。
例如,假设我的Pojo对象名称和描述属性如下:零默认。
以下示例展示了一个列表我的Pojo来自我的属性:
-
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"
如果开发个人资料未激活,MyProperties.list包含一个我的Pojo进入,如前所述。
如果开发配置文件已启用,但列表 仍然只包含一个条目(名称为我的另一个名字以及零).
这种配置不会增加第二个我的Pojo实例映射到列表中,且不会合并这些项目。
当列表在多个配置文件中指定,使用优先级最高的那个(且仅该配置文件)。
请考虑以下例子:
-
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"
在上述例子中,如果开发个人资料已激活,MyProperties.list包含一个 我的Pojo条目(名称为我的另一个名字以及零).
对于 YAML,逗号分隔列表和 YAML 列表都可以用来完全覆盖列表的内容。
为地图属性,你可以绑定来自多个来源的属性值。
然而,对于同一属性在多个来源中,会使用优先级最高的那个。
以下示例揭示了一个Map<String,MyPojo>从我的属性:
-
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"
如果开发个人资料未激活,MyProperties.map包含一个条目,密钥密钥1(其名称为我的名字 1以及我的描述 1).
如果开发不过,配置文件是启用的,地图包含两个带密钥的条目密钥1(其名称为开发者名 1以及我的描述 1)密钥2(其名称为开发者名 2以及开发者简介2).
| 上述合并规则适用于所有属性源的属性,而不仅仅是文件。 |
属性转换
Spring Boot 试图在绑定@ConfigurationProperties豆。
如果你需要自定义类型转换,可以提供转换服务豆子(带有一个名为转换服务)或自定义属性编辑器(通过CustomEditorConfigurer豆)或自定义转换器(豆定义注释为@ConfigurationPropertiesBinding).
|
用于属性转换的豆子会在应用生命周期的早期就被请求,所以一定要限制你所依赖的数量 |
你可能想重新命名你的自定义转换服务如果不需要配置键强制,只依赖符合条件的定制转换器@ConfigurationPropertiesBinding.
当确定 a@Bean方法:@ConfigurationPropertiesBinding,方法应为静态的以避免出现“豆子不符合所有豆后处理商处理资格”的警告。 |
转换时长
Spring Boot 有专门的时长表达支持。
如果你暴露了期间在应用属性中,可以使用以下格式:
-
常客
长表示法(除非@DurationUnit已被指定) -
一种更易读的格式,将值与单位耦合(
10分意为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和30多岁它们都是等价的。
500毫秒的读取超时可用以下任一形式指定:500,PT0.5S和500毫秒.
你也可以使用任何支持的单位。 这些包括:
-
NS纳秒级 -
我们仅限于微秒级 -
女士毫秒级 -
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)
如果你正在升级长性质,确保定义单位(使用@DurationUnit如果不是毫秒级。
这样做既能提供透明的升级路径,又支持更丰富的格式。 |
换算时期
除了持续时间,Spring Boot 还可以使用时期类型。
应用属性中可以使用以下格式:
-
常驻
智力表示(除非@PeriodUnit已被指定) -
一种更简单的格式,其中值和单位对耦合(
1y3d意为1年零3天)
以下单元采用简单格式支持:
-
y多年来 -
m几个月了 -
w好几个星期 -
d好几天
这时期Type其实从来不会存储周数,它只是一个快捷方式,意思是“7天”。 |
数据大小转换
-
常客
长表示法(除非@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兆字节,10和10MB是等价的。
256字节的大小阈值可以指定为256或256B.
你也可以使用任何支持的单位。 这些包括:
-
B对于字节 -
KB对于千字节 -
MB对于兆字节 -
GB对于吉字节 -
结核病对于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)
如果你正在升级长性质,确保定义单位(使用@DataSizeUnit如果不是字节,则
这样做既能提供透明的升级路径,又支持更丰富的格式。 |
@ConfigurationProperties 验证
Spring Boot 尝试验证@ConfigurationProperties当类被注注为Spring的@Validated注解。
你可以用JSR-303雅加达.验证直接在你的配置类上做约束注释。
为此,确保你的类路径上有一个符合规范的 JSR-303 实现,然后在字段中添加约束注释,如下示例所示:
-
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.
以下示例基于前述内容我的属性例:
-
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
}
}
你也可以添加自定义Spring验证器通过创建一个名为configurationPropertiesValidator.
这@Bean方法应声明静态的.
配置属性验证器是在应用程序生命周期的早期创建的,并声明@Bean静态方法允许生成豆子而无需实例化@Configuration类。
这样做可以避免早期实例化可能带来的问题。
这Spring-启动-执行器模块包含一个端点,可以暴露所有@ConfigurationProperties豆。
你的网页浏览器指向/actuator/configprops或使用等效的JMX端点。
详情请参见“生产准备功能”部分。 |
@ConfigurationProperties vs. @Value
这@Value注释是核心容器功能,但它不提供与类型安全配置属性相同的功能。
下表总结了支持的特征@ConfigurationProperties和@Value:
| 特征 | @ConfigurationProperties |
@Value |
|---|---|---|
是的 |
有限(见下文注释)) |
|
是的 |
不 |
|
|
不 |
是的 |
|
如果你真的想使用 例如 |
如果你为自己的组件定义一组配置键,建议将它们分组到带有注释的POJO中@ConfigurationProperties.
这样做会为你提供结构化、类型安全的对象,你可以把它注入到自己的豆子里。