On this page
24. Externalized Configuration
Spring Boot 使您可以外部化配置,以便可以在不同环境中使用相同的应用程序代码。您可以使用属性文件,YAML 文件,环境变量和命令行参数来外部化配置。属性值可以使用@Value注解直接注入到您的 bean 中,可以通过 Spring 的Environment抽象访问,也可以是绑定到结构化对象到@ConfigurationProperties。
Spring Boot 使用一个非常特殊的PropertySourceSequences,该 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 的BinderUtil(即@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。这样做使您可以将@ValueComments 与占位符语法一起使用以访问 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 缺点
无法使用@PropertySourceComments 加载 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 第三方配置
除了使用@ConfigurationPropertiesComments 类,您还可以在公共@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 的@ValidatedComments 进行 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
您还可以通过使用@ValidatedComments 创建配置属性的@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 |
如果您为自己的组件定义了一组配置键,我们建议您将它们组合在以@ConfigurationPropertiesComments 的 POJO 中。您还应该意识到,由于@Value不支持宽松的绑定,因此如果您需要使用环境变量来提供值,则它不是很好的选择。
最后,尽管您可以在@Value中编写SpEL表达式,但不会从应用程序属性文件处理此类表达式。