On this page
24. Externalized Configuration
Spring Boot 使您可以外部化配置,以便可以在不同环境中使用相同的应用程序代码。您可以使用属性文件,YAML 文件,环境变量和命令行参数来外部化配置。属性值可以使用@Value
注解直接注入到您的 bean 中,可以通过 Spring 的Environment
抽象访问,也可以是绑定到结构化对象到@ConfigurationProperties
。
Spring Boot 使用一个非常特殊的PropertySource
Sequences,该 Sequences 被设计为允许明智地覆盖值。按以下 Sequences 考虑属性:
您的主目录上的Devtools 全局设置属性(在 devtools 处于 Active 状态时为
~/.spring-boot-devtools.properties
)。@TestPropertySource您的测试 Comments。
测试中的
properties
属性。在@SpringBootTest和测试 Comments 以测试应用程序的特定部分上可用。命令行参数。
SPRING_APPLICATION_JSON
中的属性(嵌入在环境变量或系统属性中的内联 JSON)。ServletConfig
个初始化参数。ServletContext
个初始化参数。来自
java:comp/env
的 JNDI 属性。Java 系统属性(
System.getProperties()
)。os 环境变量。
仅在
random.*
中具有属性的RandomValuePropertySource
。特定于配置文件的应用程序属性在打包的 jar 之外(
application-{profile}.properties
和 YAML 变体)。特定于配置文件的应用程序属性包装在 jar 中(
application-{profile}.properties
和 YAML 变体)。打包的 jar 之外的应用程序属性(
application.properties
和 YAML 变体)。打包在 jar 中的应用程序属性(
application.properties
和 YAML 变体)。@Configuration
个类上的@PropertySource条 Comments。默认属性(通过设置
SpringApplication.setDefaultProperties
指定)。
为了提供一个具体的示例,假设您开发一个使用name
属性的@Component
,如以下示例所示:
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
在您的应用程序 Classpath 上(例如,在 jar 内),您可以拥有一个application.properties
文件,该文件为name
提供了合理的默认属性值。在新环境中运行时,可以在 jar 外部提供application.properties
文件,该文件将覆盖name
。对于一次性测试,可以使用特定的命令行开关(例如java -jar app.jar --name="Spring"
)启动。
Tip
SPRING_APPLICATION_JSON
属性可以在命令行中提供环境变量。例如,您可以在 UN * X shell 中使用以下行:
$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,您在 SpringEnvironment
中以acme.name=test
结尾。您还可以在 System 属性中以spring.application.json
的形式提供 JSON,如以下示例所示:
$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
您还可以使用命令行参数来提供 JSON,如以下示例所示:
$ java -jar myapp.jar --spring.application.json='{"name":"test"}'
您还可以将 JSON 作为 JNDI 变量提供,如下所示:java:comp/env/spring.application.json
。
24.1 配置随机值
RandomValuePropertySource
可用于注入随机值(例如,Importing 到机密或测试用例中)。它可以产生整数,longs,uuid 或字符串,如以下示例所示:
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]}
random.int*
语法为OPEN value (,max) CLOSE
,其中OPEN,CLOSE
是任何字符,而value,max
是整数。如果提供max
,则value
是最小值,而max
是最大值(不包括)。
24.2 访问命令行属性
默认情况下,SpringApplication
将任何命令行选项参数(即以--
开头的参数,例如--server.port=9000
)转换为property
并将其添加到 Spring Environment
。如前所述,命令行属性始终优先于其他属性源。
如果您不想将命令行属性添加到Environment
,则可以使用SpringApplication.setAddCommandLineProperties(false)
禁用它们。
24.3 应用程序属性文件
SpringApplication
从以下位置的application.properties
文件中加载属性,并将它们添加到 Spring Environment
中:
当前目录的
/config
子目录当前目录
Classpath
/config
包Classpath 根
该列表按优先级排序(在列表较高位置定义的属性会覆盖在较低位置定义的属性)。
Note
您也可以使用 YAML('.yml')文件替代“ .properties”。
如果您不喜欢application.properties
作为配置文件名,则可以通过指定spring.config.name
环境属性来切换到另一个文件名。您还可以使用spring.config.location
环境属性(这是目录位置或文件路径的逗号分隔列表)来引用显式位置。下面的示例演示如何指定其他文件名:
$ java -jar myproject.jar --spring.config.name=myproject
下面的示例演示如何指定两个位置:
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Warning
spring.config.name
和spring.config.location
很早就用于确定必须加载哪些文件,因此必须将它们定义为环境属性(通常是 OS 环境变量,系统属性或命令行参数)。
如果spring.config.location
包含目录(而不是文件),则它们应以/
结尾(并且在运行时,应在加载之前附加从spring.config.name
生成的名称,包括特定于配置文件的文件名)。 spring.config.location
中指定的文件按原样使用,不支持特定于配置文件的变体,并且被任何特定于配置文件的属性覆盖。
配置位置以相反的 Sequences 搜索。默认情况下,配置的位置是classpath:/,classpath:/config/,file:./,file:./config/
。结果搜索 Sequences 如下:
file:./config/
file:./
classpath:/config/
classpath:/
使用spring.config.location
配置自定义配置位置后,它们将替换默认位置。例如,如果将spring.config.location
配置为值classpath:/custom-config/,file:./custom-config/
,则搜索 Sequences 如下:
file:./custom-config/
classpath:custom-config/
或者,当使用spring.config.additional-location
配置自定义配置位置时,除默认位置外还使用它们。在默认位置之前搜索其他位置。例如,如果配置了classpath:/custom-config/,file:./custom-config/
的其他位置,则搜索 Sequences 如下:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/
通过此搜索 Sequences,您可以在一个配置文件中指定默认值,然后在另一个配置文件中有选择地覆盖这些值。您可以在默认位置之一的application.properties
(或使用spring.config.name
选择的其他任何基本名称)中为应用程序提供默认值。然后,可以在运行时使用自定义位置之一中的其他文件覆盖这些默认值。
Note
如果使用环境变量而不是系统属性,则大多数 os 都不允许使用句点分隔的键名,但可以使用下划线代替(例如,SPRING_CONFIG_NAME
代替spring.config.name
)。
Note
如果您的应用程序在容器中运行,则可以使用 JNDI 属性(在java:comp/env
中)或 servlet 上下文初始化参数来代替环境变量或系统属性,也可以使用它们。
24.4 特定于配置文件的属性
除了application.properties
个文件之外,还可以使用以下命名约定来定义特定于配置文件的属性:application-{profile}.properties
。 Environment
具有一组默认配置文件(默认情况下为[default]
),如果未设置任何 Active 配置文件,则使用这些配置文件。换句话说,如果未显式激活任何配置文件,则将加载application-default.properties
中的属性。
特定于配置文件的属性是从与标准application.properties
相同的位置加载的,特定于配置文件的文件总是会覆盖非特定文件,无论特定于配置文件的文件是在打包 jar 的内部还是外部。
如果指定了多个配置文件,则采用后赢策略。例如,由spring.profiles.active
属性指定的配置文件将添加到通过SpringApplication
API 配置的配置文件之后,因此具有优先权。
Note
如果您在spring.config.location
中指定了任何文件,则不会考虑这些文件的特定于配置文件的变体。如果您还想使用特定于配置文件的属性,请使用spring.config.location
中的目录。
24.5 属性中的占位符
application.properties
中的值在使用时会通过现有的Environment
进行过滤,因此您可以参考以前定义的值(例如,从“系统”属性中)。
app.name=MyApp
app.description=${app.name} is a Spring Boot application
Tip
您还可以使用此技术来创建现有 Spring Boot 属性的“简短”变体。有关详细信息,请参见* 第 77.4 节“使用'短'命令行参数” *操作方法。
24.6 加密属性
Spring Boot 不提供对加密属性值的任何内置支持,但是,它确实提供了修改 Spring Environment
中包含的值所必需的钩子点。 EnvironmentPostProcessor
界面允许您在应用程序启动之前操纵Environment
。有关详情,请参见第 76.3 节“在启动前自定义环境或 ApplicationContext”。
如果您正在寻找一种安全的方式来存储凭据和密码,则Spring Cloud Vault项目提供了对将外部化配置存储在HashiCorp Vault中的支持。
24.7 使用 YAML 代替属性
YAML是 JSON 的超集,因此是一种用于指定层次结构配置数据的便捷格式。只要在 Classpath 上具有SnakeYAML库,SpringApplication
类就会自动支持 YAML 作为属性的替代方法。
Note
如果您使用“Starter”,则spring-boot-starter
自动提供 SnakeYAML。
24.7.1 加载 YAML
Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 YamlPropertiesFactoryBean
将 YAML 加载为Properties
,而YamlMapFactoryBean
将 YAML 加载为Map
。
例如,考虑以下 YAML 文档:
environments:
dev:
url: http://dev.example.com
name: Developer Setup
prod:
url: http://another.example.com
name: My Cool App
前面的示例将转换为以下属性:
environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App
YAML 列表表示为带有[index]
解引用器的属性键。例如,考虑以下 YAML:
my:
servers:
- dev.example.com
- another.example.com
前面的示例将转换为以下属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
要使用 Spring Boot 的Binder
Util(即@ConfigurationProperties
所做的)绑定到类似的属性,您需要在java.util.List
(或Set
)类型的目标 bean 中具有一个属性,并且需要提供 setter 或使用 a 初始化它。可变值。例如,以下示例绑定到前面显示的属性:
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
24.7.2 在 Spring 环境中将 YAML 公开为属性
YamlPropertySourceLoader
类可用于在 Spring Environment
中将 YAML 公开为PropertySource
。这样做使您可以将@Value
Comments 与占位符语法一起使用以访问 YAML 属性。
24.7.3 多配置文件 YAML 文档
您可以使用spring.profiles
键在一个文件中指定多个特定于配置文件的 YAML 文档,以指示何时应用该文档,如以下示例所示:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production & eu-central
server:
address: 192.168.1.120
在前面的示例中,如果development
配置文件处于 Active 状态,则server.address
属性为127.0.0.1
。同样,如果production
和eu-central
配置文件处于 Active 状态,则server.address
属性为192.168.1.120
。如果development
,production
和eu-central
配置文件未启用,则该属性的值为192.168.1.100
。
Note
因此spring.profiles
可以包含一个简单的配置文件名称(例如production
)或一个配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑,例如production & (eu-central | eu-west)
。查看reference guide以获取更多详细信息。
如果在启动应用程序上下文时未明确激活任何 Active,则会激活默认配置文件。因此,在以下 YAML 中,我们为spring.security.user.password
设置了一个值,该值在"default"配置文件中仅**可用:
server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak
而在以下示例中,始终设置密码是因为该密码未附加到任何配置文件,并且必须根据需要在所有其他配置文件中将其显式重置:
server:
port: 8000
spring:
security:
user:
password: weak
通过使用spring.profiles
元素指定的 Spring 轮廓可以选择通过使用!
字符来否定。如果为单个文档同时指定了否定的配置文件和否定的配置文件,则至少一个非否定的配置文件必须匹配,并且否定的配置文件不能匹配。
24.7.4 YAML 缺点
无法使用@PropertySource
Comments 加载 YAML 文件。因此,在需要以这种方式加载值的情况下,需要使用属性文件。
24.8 类型安全的配置属性
使用@Value("${property}")
注解注入配置属性有时会很麻烦,尤其是当您使用多个属性或数据本质上是分层的时。 Spring Boot 提供了一种使用属性的替代方法,该方法使强类型的 Bean 可以 Management 和验证应用程序的配置,如以下示例所示:
package com.example;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("acme")
public class AcmeProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() { ... }
public void setEnabled(boolean enabled) { ... }
public InetAddress getRemoteAddress() { ... }
public void setRemoteAddress(InetAddress remoteAddress) { ... }
public Security getSecurity() { ... }
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() { ... }
public void setUsername(String username) { ... }
public String getPassword() { ... }
public void setPassword(String password) { ... }
public List<String> getRoles() { ... }
public void setRoles(List<String> roles) { ... }
}
}
前面的 POJO 定义了以下属性:
acme.enabled
,默认值为false
。acme.remote-address
,其类型可以从String
强制转换。acme.security.username
,带有嵌套的“安全”对象,其名称由属性名称确定。特别是,返回类型在那里根本不使用,可能是SecurityProperties
。acme.security.password
.acme.security.roles
,集合为String
。
Note
Getter 和 Setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性 Descriptors 进行的,就像在 Spring MVC 中一样。在以下情况下,可以忽略二传手:
只要将 Map 初始化,它们就需要使用吸气剂,但不一定需要使用 setter,因为它们可以被 Binder 改变。
可以通过索引(通常使用 YAML)或使用单个逗号分隔的值(属性)来访问集合和数组。在后一种情况下,必须使用二传手。我们建议始终为此类类型添加设置器。如果初始化集合,请确保它不是不可变的(如上例所示)。
如果初始化嵌套的 POJO 属性(如上例中的
Security
字段),则不需要设置器。如果希望 Binder 通过使用其默认构造函数动态创建实例,则需要一个 setter。
有些人使用 Lombok 项目自动添加获取器和设置器。确保 Lombok 不会为这种类型生成任何特定的构造函数,因为容器会自动使用它来实例化该对象。
最后,仅考虑标准 Java Bean 属性,不支持对静态属性的绑定。
您还需要列出要在@EnableConfigurationProperties
注解中注册的属性类,如以下示例所示:
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
Note
以这种方式注册@ConfigurationProperties
bean 时,该 bean 具有常规名称:<prefix>-<fqn>
,其中<prefix>
是@ConfigurationProperties
注解中指定的环境密钥前缀,而<fqn>
是 bean 的全限定名。如果 Comments 不提供任何前缀,则仅使用 Bean 的完全限定名称。
上例中的 bean 名称是acme-com.example.AcmeProperties
。
即使前面的配置为AcmeProperties
创建了一个常规 bean,我们也建议@ConfigurationProperties
只处理环境,尤其不要从上下文中注入其他 bean。话虽如此,@EnableConfigurationProperties
注解也会自动应用到您的项目中,从而可以从Environment
配置任何以@ConfigurationProperties
注解的现有 bean。您可以通过确保AcmeProperties
已经是 Bean 来快捷方式MyConfiguration
,如以下示例所示:
@Component
@ConfigurationProperties(prefix="acme")
public class AcmeProperties {
// ... see the preceding example
}
这种配置风格特别适用于SpringApplication
外部 YAML 配置,如以下示例所示:
# application.yml
acme:
remote-address: 192.168.1.1
security:
username: admin
roles:
- USER
- ADMIN
# additional configuration as required
要使用@ConfigurationProperties
bean,可以像使用其他任何 bean 一样注入它们,如以下示例所示:
@Service
public class MyService {
private final AcmeProperties properties;
@Autowired
public MyService(AcmeProperties properties) {
this.properties = properties;
}
//...
@PostConstruct
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
// ...
}
}
Tip
使用@ConfigurationProperties
还可让您生成元数据文件,IDE 可以使用这些元数据文件为您自己的键提供自动完成功能。有关详细信息,请参见附录 B,配置元数据附录。
24.8.1 第三方配置
除了使用@ConfigurationProperties
Comments 类,您还可以在公共@Bean
方法上使用它。当您要将属性绑定到控件之外的第三方组件时,这样做特别有用。
要通过Environment
属性配置 bean,请将@ConfigurationProperties
添加到其 bean 注册中,如以下示例所示:
@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
...
}
用another
前缀定义的任何属性都以类似于前面AcmeProperties
示例的方式 Map 到该AnotherComponent
bean。
24.8.2 轻松绑定
Spring Boot 使用一些宽松的规则将Environment
属性绑定到@ConfigurationProperties
bean,因此Environment
属性名称和 bean 属性名称之间不需要完全匹配。有用的常见示例包括破折号分隔的环境属性(例如context-path
绑定到contextPath
)和大写的环境属性(例如PORT
绑定到port
)。
例如,考虑以下@ConfigurationProperties
类:
@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
在前面的示例中,可以全部使用以下属性名称:
表 24.1. 轻松绑定
Property | Note |
---|---|
acme.my-project.person.first-name |
Kebab 情况,建议在.properties 和.yml 文件中使用。 |
acme.myProject.person.firstName |
标准驼峰式语法。 |
acme.my_project.person.first_name |
下划线表示法,是在.properties 和.yml 文件中使用的另一种格式。 |
ACME_MYPROJECT_PERSON_FIRSTNAME |
大写格式,使用系统环境变量时建议使用。 |
Note
Comments*的prefix
值必须为 kebab(小写并由-
分隔,例如acme.my-project.person
)。
表 24.2. 每个资源来源的宽松绑定规则
Property Source | Simple | List |
---|---|---|
Properties Files | 骆驼案,烤肉串案或下划线 | 使用[ ] 或逗号分隔值的标准列表语法 |
YAML Files | 骆驼案,烤肉串案或下划线 | 标准 YAML 列表语法或逗号分隔的值 |
Environment Variables | 以下划线作为定界符的大写格式。 _ 不应在属性名称中使用 |
带有下划线的数字值,例如MY_ACME_1_OTHER = my.acme[1].other |
System properties | 骆驼案,烤肉串案或下划线 | 使用[ ] 或逗号分隔值的标准列表语法 |
Tip
我们建议,如果可能的话,属性以小写的 kebab 格式存储,例如my.property-name=acme
。
绑定到Map
属性时,如果key
包含小写字母数字字符或-
以外的任何内容,则需要使用方括号表示法,以便保留原始值。如果键没有被[]
包围,则所有非字母数字或-
的字符都将被删除。例如,考虑将以下属性绑定到Map
:
acme:
map:
"[/key1]": value1
"[/key2]": value2
/key3: value3
上面的属性将绑定到Map
,其中/key1
,/key2
和key3
作为 Map 中的键。
24.8.3 合并复杂类型
如果在多个位置配置了列表,则通过替换整个列表来进行覆盖。
例如,假设一个MyPojo
对象的name
和description
属性默认为null
。以下示例公开了AcmeProperties
中的MyPojo
个对象的列表:
@ConfigurationProperties("acme")
public class AcmeProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
考虑以下配置:
acme:
list:
- name: my name
description: my description
---
spring:
profiles: dev
acme:
list:
- name: my another name
如果dev
配置文件无效,则AcmeProperties.list
包含一个MyPojo
条目,如先前所定义。但是,如果启用了dev
配置文件,则list
仍然仅包含一个条目(名称为my another name
和描述为null
)。此配置不会将第二个MyPojo
实例添加到列表中,并且不会合并项目。
在多个配置文件中指定List
时,将使用优先级最高的(并且只有该优先级)。考虑以下示例:
acme:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
acme:
list:
- name: my another name
在前面的示例中,如果dev
配置文件处于 Active 状态,则AcmeProperties.list
包含* one * MyPojo
条目(名称为my another name
且描述为null
)。对于 YAML,可以使用逗号分隔的列表和 YAML 列表来完全覆盖列表的内容。
对于Map
属性,您可以绑定从多个来源获取的属性值。但是,对于多个源中的同一属性,将使用优先级最高的属性。以下示例从AcmeProperties
公开Map<String, MyPojo>
:
@ConfigurationProperties("acme")
public class AcmeProperties {
private final Map<String, MyPojo> map = new HashMap<>();
public Map<String, MyPojo> getMap() {
return this.map;
}
}
考虑以下配置:
acme:
map:
key1:
name: my name 1
description: my description 1
---
spring:
profiles: dev
acme:
map:
key1:
name: dev name 1
key2:
name: dev name 2
description: dev description 2
如果dev
配置文件未激活,则AcmeProperties.map
包含一个键为key1
的条目(名称为my name 1
和描述为my description 1
)。但是,如果启用了dev
配置文件,则map
包含两个条目,其中包含键key1
(名称为dev name 1
和my description 1
的描述)和key2
(名称为dev name 2
和dev description 2
的描述)。
Note
前述合并规则不仅适用于 YAML 文件,而且适用于所有属性源中的属性。
24.8.4 属性转换
当 Spring Boot 绑定到@ConfigurationProperties
bean 时,它尝试将外部应用程序属性强制为正确的类型。如果需要自定义类型转换,则可以提供ConversionService
bean(使用名为conversionService
的 bean)或自定义属性编辑器(通过CustomEditorConfigurer
bean)或自定义Converters
(将 bean 定义标注为@ConfigurationPropertiesBinding
)。
Note
由于在应用程序生命周期中非常早就请求了此 bean,因此请确保限制您的ConversionService
使用的依赖项。通常,您需要的任何依赖项可能在创建时未完全初始化。如果配置键强制不需要自定义ConversionService
,而只依赖于具有@ConfigurationPropertiesBinding
限定的自定义转换器,则可能要重命名。
Converting durations
Spring Boot 为表达持续时间提供了专门的支持。如果公开java.time.Duration
属性,则应用程序属性中的以下格式可用:
常规
long
表示形式(使用毫秒作为默认单位,除非已指定@DurationUnit
)标准 ISO-8601 格式由 java.util.Duration 使用
值和单位相结合的更易读的格式(例如
10s
表示 10 秒)
考虑以下示例:
@ConfigurationProperties("app.system")
public class AppSystemProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
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;
}
}
要指定 30 秒的会话超时,30
,PT30S
和30s
都是等效的。可以采用以下任何形式指定 500ms 的读取超时:500
,PT0.5S
和500ms
。
您也可以使用任何受支持的单位。这些是:
ns
纳秒us
微秒ms
毫秒s
秒m
分钟h
小时d
天
默认单位是毫秒,可以使用@DurationUnit
覆盖,如上面的示例所示。
Tip
如果要从仅使用Long
表示持续时间的先前版本进行升级,请确保在切换到Duration
的时间不是毫秒的情况下(使用@DurationUnit
)定义单位。这样做可以提供透明的升级路径,同时支持更丰富的格式。
转换数据大小
Spring Framework 的DataSize
值类型允许以字节表示大小。如果公开DataSize
属性,则应用程序属性中的以下格式可用:
常规的
long
表示形式(除非已指定@DataSizeUnit
,否则使用字节作为默认单位)值和单位耦合在一起的更具可读性的格式(例如
10MB
表示 10 兆字节)
考虑以下示例:
@ConfigurationProperties("app.io")
public class AppIoProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
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;
}
}
要指定 10 MB 的缓冲区大小,10
和10MB
是等效的。可以将 256 个字节的大小阈值指定为256
或256B
。
您也可以使用任何受支持的单位。这些是:
B
个字节KB
千字节MB
代表兆字节GB
代表千兆字节TB
代表兆兆字节
默认单位是字节,可以使用@DataSizeUnit
覆盖,如上面的示例所示。
Tip
如果要从仅使用Long
表示大小的先前版本进行升级,请确保在切换到DataSize
的旁边不是字节的情况下定义单位(使用@DataSizeUnit
)。这样做可以提供透明的升级路径,同时支持更丰富的格式。
24.8.5 @ConfigurationProperties 验证
每当使用 Spring 的@Validated
Comments 进行 Comments 时,Spring Boot 就会尝试验证@ConfigurationProperties
类。您可以在配置类上直接使用 JSR-303 javax.validation
约束 Comments。为此,请确保在 Classpath 上有兼容的 JSR-303 实现,然后将约束 Comments 添加到字段中,如以下示例所示:
@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
Tip
您还可以通过使用@Validated
Comments 创建配置属性的@Bean
方法来触发验证。
尽管嵌套属性在绑定时也会被验证,但是最好将关联的字段 Comments 为@Valid
。这样可以确保即使没有嵌套属性也可以触发验证。以下示例基于前面的AcmeProperties
示例:
@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// ... getters and setters
public static class Security {
@NotEmpty
public String username;
// ... getters and setters
}
}
您还可以通过创建名为configurationPropertiesValidator
的 bean 定义来添加自定义 Spring Validator
。 @Bean
方法应声明为static
。配置属性验证器是在应用程序生命周期的早期创建的,并且将@Bean
方法声明为静态方法可以使 Bean 得以创建而不必实例化@Configuration
类。这样做可以避免因早期实例化而引起的任何问题。有一个属性验证 samples显示了如何进行设置。
Tip
spring-boot-actuator
模块包含一个公开所有@ConfigurationProperties
bean 的端点。将您的 Web 浏览器指向/actuator/configprops
或使用等效的 JMX 端点。有关详细信息,请参见“ 生产就绪功能”部分。
24.8.6 @ConfigurationProperties 与@Value
@Value
注解是核心容器功能,它没有提供与类型安全的配置属性相同的功能。下表总结了@ConfigurationProperties
和@Value
支持的功能:
Feature | @ConfigurationProperties |
@Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
SpEL 评估 |
No | Yes |
如果您为自己的组件定义了一组配置键,我们建议您将它们组合在以@ConfigurationProperties
Comments 的 POJO 中。您还应该意识到,由于@Value
不支持宽松的绑定,因此如果您需要使用环境变量来提供值,则它不是很好的选择。
最后,尽管您可以在@Value
中编写SpEL
表达式,但不会从应用程序属性文件处理此类表达式。