本节深入探讨 Spring Boot 的细节。在这里,您可以了解您可能想要使用和自定义的主要功能。如果您还没有这样做,您可能需要阅读“ getting-started.html ”和“ using.html ”部分,这样您就有了良好的基础知识。
1. SpringApplication
该类SpringApplication
提供了一种方便的方法来引导从main()
方法启动的 Spring 应用程序。在许多情况下,您可以委托给静态SpringApplication.run
方法,如下例所示:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
当您的应用程序启动时,您应该会看到类似于以下输出的内容:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_||)))))
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|===============|___/=/_/_/_/
:: Spring Boot :: (v2.7.5)
2022-10-20 12:40:17.841 INFO 16284 --- [main] osbdfsMyApplication:在 PID 16284 的 myhost 上使用 Java 1.8.0_345 启动 MyApplication(/opt/apps/myapp.jar 由 myuser 在 /opt/apps/ 中启动)
2022-10-20 12:40:17.849 INFO 16284 --- [main] osbdfsMyApplication:未设置活动配置文件,回退到 1 个默认配置文件:“默认”
2022-10-20 12:40:20.443 INFO 16284 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 使用端口初始化:8080 (http)
2022-10-20 12:40:20.455 INFO 16284 --- [main] o.apache.catalina.core.StandardService:启动服务 [Tomcat]
2022-10-20 12:40:20.455 INFO 16284 --- [main] org.apache.catalina.core.StandardEngine:启动 Servlet 引擎:[Apache Tomcat/9.0.68]
2022-10-20 12:40:20.716 INFO 16284 --- [main] oaccC[Tomcat].[localhost].[/]:初始化 Spring 嵌入式 WebApplicationContext
2022-10-20 12:40:20.716 INFO 16284 --- [main] wscServletWebServerApplicationContext:Root WebApplicationContext:初始化在 2566 毫秒内完成
2022-10-20 12:40:22.045 INFO 16284 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 在端口上启动:8080 (http),上下文路径为“”
2022-10-20 12:40:22.073 INFO 16284 --- [main] osbdfsMyApplication:MyApplication 在 4.937 秒内启动(JVM 运行 6.049)
默认情况下,INFO
会显示日志消息,包括一些相关的启动详细信息,例如启动应用程序的用户。如果您需要除 之外的日志级别INFO
,您可以设置它,如日志级别中所述。应用程序版本是使用主应用程序类包中的实现版本确定的。spring.main.log-startup-info
设置为可以关闭启动信息记录false
。这也将关闭应用程序活动配置文件的日志记录。
1.1启动失败
如果您的应用程序无法启动,注册FailureAnalyzers
者将有机会提供专门的错误消息和解决问题的具体措施。例如,如果您在端口上启动 Web 应用程序8080
并且该端口已在使用中,您应该会看到类似于以下消息的内容:
******************************
应用程序无法启动
******************************
描述:
嵌入式 servlet 容器无法启动。端口 8080 已被使用。
行动:
如果没有故障分析器能够处理异常,您仍然可以显示完整的条件报告以更好地了解问题所在。为此,您需要启用该debug属性或启用DEBUG日志记录org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
。
例如,如果您使用 运行应用程序,则可以按如下java -jar
方式启用该属性:debug
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
1.2. 延迟初始化
SpringApplication
允许延迟初始化应用程序。当启用延迟初始化时,bean 会在需要时创建,而不是在应用程序启动期间创建。因此,启用延迟初始化可以减少应用程序启动所需的时间。在 Web 应用程序中,启用延迟初始化将导致许多与 Web 相关的 bean 在收到 HTTP 请求之前不会被初始化。
延迟初始化的一个缺点是它会延迟应用程序问题的发现。如果配置错误的 bean 被延迟初始化,则在启动期间将不再发生故障,并且只有在 bean 初始化时问题才会变得明显。还必须注意确保 JVM 有足够的内存来容纳应用程序的所有 bean,而不仅仅是那些在启动期间初始化的 bean。由于这些原因,默认情况下不启用延迟初始化,建议在启用延迟初始化之前对 JVM 的堆大小进行微调。
lazyInitialization
可以使用方法 onSpringApplicationBuilder
或setLazyInitialization
方法 on以编程方式启用延迟初始化SpringApplication
。或者,可以使用spring.main.lazy-initialization
以下示例中所示的属性启用它:
特性
spring.main.lazy-initialization=true
1.3. 自定义横幅
banner.txt
可以通过将文件添加到类路径或将spring.banner.location
属性设置为此类文件的位置来更改启动时打印的横幅。如果文件的编码不是 UTF-8,您可以设置spring.banner.charset
. 除了文本文件之外,您还可以将banner.gif
、banner.jpg
或banner.png
图像文件添加到类路径或设置spring.banner.image.location
属性。图像被转换为 ASCII 艺术表示并打印在任何文本横幅上方。
在您的banner.txt
文件中,您可以使用任何可用的键Environment
以及以下任何占位符:
表 1. 横幅变量
多变的 | 描述 |
| 应用程序的版本号,如 |
| 应用程序的版本号,在中声明 |
| 您正在使用的 Spring Boot 版本。例如 |
| 您正在使用的 Spring Boot 版本,已格式化以供显示(用括号括起来并以 为前缀 |
| |
| 应用程序的标题,如 |
您还可以使用该spring.main.banner-mode
属性来确定是否必须在System.out
( console
) 上打印横幅、发送到配置的记录器 ( log
) 或根本不生成 ( off
)。
打印的横幅以以下名称注册为单例 bean springBootBanner
:.
1.4. 自定义 SpringApplication
如果SpringApplication
默认值不符合您的口味,您可以改为创建本地实例并对其进行自定义。例如,要关闭横幅,您可以编写:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
也可以SpringApplication
使用application.properties
文件进行配置。有关详细信息,请参阅外部化配置。
有关配置选项的完整列表,请参阅SpringApplicationJavadoc。
1.5流畅的构建器 API
如果您需要构建ApplicationContext
层次结构(具有父/子关系的多个上下文),或者如果您更喜欢使用“流利的”构建器 API,则可以使用SpringApplicationBuilder
.
允许您将SpringApplicationBuilder
多个方法调用和包含parent
以及child
允许您创建层次结构的方法链接在一起,如以下示例所示:
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
1.6. 应用程序可用性
当部署在平台上时,应用程序可以使用Kubernetes Probes等基础设施向平台提供有关其可用性的信息。Spring Boot 包括对常用“liveness”和“readiness”可用性状态的开箱即用支持。如果您使用 Spring Boot 的“执行器”支持,那么这些状态将作为健康端点组公开。
此外,您还可以通过将ApplicationAvailability
接口注入到自己的 bean 中来获取可用性状态。
1.6.1. 活跃状态
应用程序的“活跃度”状态表明其内部状态是否允许其正常工作,或者如果当前失败则自行恢复。损坏的“活动”状态意味着应用程序处于无法恢复的状态,基础设施应重新启动应用程序。
Spring Boot 应用程序的内部状态主要由 Spring 表示ApplicationContext
。如果应用程序上下文已成功启动,Spring Boot 假定应用程序处于有效状态。一旦上下文被刷新,应用程序就被认为是活动的,请参阅Spring Boot 应用程序生命周期和相关的应用程序事件。
1.6.2. 准备状态
应用程序的“就绪”状态表明应用程序是否已准备好处理流量。失败的“就绪”状态告诉平台它现在不应该将流量路由到应用程序。这通常发生在启动期间、CommandLineRunner
处理ApplicationRunner
组件时,或者在应用程序决定它太忙而无法获得额外流量的任何时候。
一旦调用了应用程序和命令行运行器,就认为应用程序已准备就绪,请参阅Spring Boot 应用程序生命周期和相关的应用程序事件。
1.6.3. 管理应用程序可用性状态
应用程序组件可以随时检索当前的可用性状态,方法是注入ApplicationAvailability
接口并在其上调用方法。更多时候,应用程序会想要监听状态更新或更新应用程序的状态。
例如,我们可以将应用程序的“Readiness”状态导出到一个文件中,以便 Kubernetes “exec Probe”可以查看这个文件:
@Component
public class MyReadinessStateExporter {
@EventListener
public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
switch (event.getState()) {
case ACCEPTING_TRAFFIC:
// create file /tmp/healthy
break;
case REFUSING_TRAFFIC:
// remove file /tmp/healthy
break;
}
}
}
我们还可以在应用中断且无法恢复时更新应用的状态:
@Component
public class MyLocalCacheVerifier {
private final ApplicationEventPublisher eventPublisher;
public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void checkLocalCache() {
try {
// ...
}
catch (CacheCompletelyBrokenException ex) {
AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
}
}
}
Spring Boot通过 Actuator Health Endpoints 为“Liveness”和“Readiness”提供 Kubernetes HTTP 探测。您可以在专用部分中获得有关在 Kubernetes 上部署 Spring Boot 应用程序的更多指导。
1.7. 应用程序事件和监听器
除了常见的 Spring Framework 事件,例如ContextRefreshedEvent, aSpringApplication
发送一些额外的应用程序事件。
当您的应用程序运行时,应用程序事件按以下顺序发送:
- An
ApplicationStartingEvent
在运行开始时但在任何处理之前发送,除了侦听器和初始化程序的注册。 -
ApplicationEnvironmentPreparedEvent
当Environment
在上下文中使用的 已知但在创建上下文之前发送一个。 -
ApplicationContextInitializedEvent
当ApplicationContext
准备好并调用 ApplicationContextInitializers 但在加载任何 bean 定义之前发送一个。 -
ApplicationPreparedEvent
在刷新开始之前但在加载 bean 定义之后发送一个。 - An
ApplicationStartedEvent
在上下文刷新之后但在调用任何应用程序和命令行运行程序之前发送。 -
AvailabilityChangeEvent
在 with 之后立即发送一个LivenessState.CORRECT
,表明应用程序被认为是活动的。 -
ApplicationReadyEvent
在调用任何应用程序和命令行运行程序后发送一个。 -
AvailabilityChangeEvent
在 with 之后立即发送一个ReadinessState.ACCEPTING_TRAFFIC
,表示应用程序已准备好为请求提供服务。 - 如果
ApplicationFailedEvent
启动时出现异常,则发送一个。
上面的列表仅包括SpringApplicationEvent
与 a 绑定的 s SpringApplication
。除此之外,还发布了以下事件 afterApplicationPreparedEvent
和 before ApplicationStartedEvent
:
- A在准备好
WebServerInitializedEvent
后发送。和分别是 servlet 和响应式变体。WebServer
ServletWebServerInitializedEvent
ReactiveWebServerInitializedEvent
- A在刷新
ContextRefreshedEvent
时发送。ApplicationContext
应用程序事件是使用 Spring Framework 的事件发布机制发送的。该机制的一部分确保在子上下文中发布给侦听器的事件也发布给任何祖先上下文中的侦听器。因此,如果您的应用程序使用SpringApplication
实例层次结构,则侦听器可能会接收到相同类型的应用程序事件的多个实例。
为了让您的侦听器区分其上下文的事件和后代上下文的事件,它应该请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现来注入上下文,ApplicationContextAware
或者,如果侦听器是 bean,则可以使用@Autowired
.
1.8. 网络环境
ASpringApplication
尝试ApplicationContext
代表您创建正确的类型。用于确定 a 的算法WebApplicationType
如下:
- 如果存在 Spring MVC,
AnnotationConfigServletWebServerApplicationContext
则使用an - 如果 Spring MVC 不存在而 Spring WebFlux 存在,
AnnotationConfigReactiveWebServerApplicationContext
则使用an - 否则,
AnnotationConfigApplicationContext
使用
这意味着如果您WebClient
在同一个应用程序中使用 Spring MVC 和来自 Spring WebFlux 的 new,则默认情况下将使用 Spring MVC。您可以通过调用轻松覆盖它setWebApplicationType(WebApplicationType)
。
也可以ApplicationContext
通过调用来完全控制使用的类型setApplicationContextClass(…)
。
1.9访问应用程序参数
如果您需要访问传递给 的应用程序参数SpringApplication.run(…)
,您可以注入一个org.springframework.boot.ApplicationArguments
bean。该ApplicationArguments
接口提供对原始String[]
参数以及解析option
和non-option
参数的访问,如以下示例所示:
@Component
public class MyBean {
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
if (debug) {
System.out.println(files);
}
// if run with "--debug logfile.txt" prints ["logfile.txt"]
}
}
1.10使用 ApplicationRunner 或 CommandLineRunner
如果您需要在启动后运行某些特定代码SpringApplication
,您可以实现ApplicationRunner
或CommandLineRunner
接口。两个接口以相同的方式工作并提供一个run
方法,该方法在完成之前调用SpringApplication.run(…)
。
接口以字符串数组的CommandLineRunner
形式提供对应用程序参数的访问,而ApplicationRunner
使用ApplicationArguments
前面讨论的接口。以下示例显示了一个CommandLineRunner
带有方法的run
方法:
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// Do something...
}
}
如果定义了必须按特定顺序调用的多个CommandLineRunner
or bean,则可以另外实现接口或使用注解。ApplicationRunner
org.springframework.core.Ordered
org.springframework.core.annotation.Order
1.11应用程序退出
每个都SpringApplication
向 JVM 注册一个关闭钩子,以确保ApplicationContext
在退出时优雅地关闭。可以使用所有标准的 Spring 生命周期回调(例如DisposableBean
接口或@PreDestroy
注解)。
此外,如果 bean希望在被调用org.springframework.boot.ExitCodeGenerator
时返回特定的退出代码,它们可以实现该接口。SpringApplication.exit()
然后可以将此退出代码传递给以将System.exit()
其作为状态代码返回,如以下示例所示:
@SpringBootApplication
public class MyApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
}
}
此外,ExitCodeGenerator
接口可能由异常实现。当遇到这样的异常时,Spring Boot 返回实现的getExitCode()
方法提供的退出代码。
如果超过ExitCodeGenerator
,则使用生成的第一个非零退出代码。要控制调用生成器的顺序,请另外实现org.springframework.core.Ordered
接口或使用org.springframework.core.annotation.Order
注释。
1.12管理员功能
可以通过指定spring.application.admin.enabled
属性为应用程序启用与管理相关的功能。这暴露了SpringApplicationAdminMXBean平台上的MBeanServer
. 您可以使用此功能远程管理您的 Spring Boot 应用程序。此功能也可用于任何服务包装器实现。
1.13应用程序启动跟踪
在应用程序启动期间,SpringApplication
执行ApplicationContext
许多与应用程序生命周期、bean 生命周期甚至处理应用程序事件相关的任务。有了它ApplicationStartup,Spring Framework允许您使用StartupStep对象跟踪应用程序的启动顺序。可以出于分析目的收集这些数据,或者只是为了更好地了解应用程序启动过程。
您可以ApplicationStartup
在设置SpringApplication
实例时选择实现。例如,要使用BufferingApplicationStartup
,您可以编写:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
}
}
第一个可用的实现FlightRecorderApplicationStartup
由 Spring Framework 提供。它将 Spring 特定的启动事件添加到 Java Flight Recorder 会话中,用于分析应用程序并将它们的 Spring 上下文生命周期与 JVM 事件(例如分配、GC、类加载……)相关联。配置完成后,您可以通过运行启用了 Flight Recorder 的应用程序来记录数据:
$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar
Spring Boot 附带该BufferingApplicationStartup
变体;此实现旨在缓冲启动步骤并将它们排入外部度量系统。BufferingApplicationStartup
应用程序可以在任何组件中请求类型的 bean 。
Spring Boot 也可以配置为公开一个以 JSON 文档形式提供此信息的startup端点。
2. 外化配置
Spring Boot 允许您将配置外部化,以便您可以在不同的环境中使用相同的应用程序代码。您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以通过使用注解直接注入到你的 bean 中@Value
,通过 Spring 的抽象Environment
访问,或者通过.@ConfigurationProperties
Spring Boot 使用一种非常特殊的PropertySource
顺序,旨在允许明智地覆盖值。之后的属性源可以覆盖之前定义的值。来源按以下顺序考虑:
- 默认属性(由设置指定
SpringApplication.setDefaultProperties
)。 - @PropertySource
@Configuration
您的课程上的注释。请注意,Environment
在刷新应用程序上下文之前,不会将此类属性源添加到 中。配置某些属性(例如在刷新开始之前读取的logging.*
和)为时已晚。spring.main.*
- 配置数据(例如
application.properties
文件)。 - 仅在中
RandomValuePropertySource
具有属性的 A。random.*
- 操作系统环境变量。
- Java 系统属性 (
System.getProperties()
)。 - JNDI 属性来自
java:comp/env
. -
ServletContext
初始化参数。 -
ServletConfig
初始化参数。 - 来自
SPRING_APPLICATION_JSON
(嵌入在环境变量或系统属性中的内联 JSON)的属性。 - 命令行参数。
-
properties
属性在你的测试。可用于测试应用程序的特定部分@SpringBootTest的测试注释。 - @TestPropertySource测试上的注释。
$HOME/.config/spring-boot
当 devtools 处于活动状态时,目录中的Devtools 全局设置属性。
配置数据文件按以下顺序考虑:
- 打包在 jar 中的应用程序属性
application.properties
(和 YAML 变体)。 - 打包在您的 jar(
application-{profile}.properties
和 YAML 变体)中的特定于配置文件的应用程序属性。 - 打包 jar(
application.properties
和 YAML 变体)之外的应用程序属性。 - 打包的 jar(
application-{profile}.properties
和 YAML 变体)之外的特定于配置文件的应用程序属性。
举一个具体的例子,假设你开发了一个@Component
使用name
属性的,如下例所示:
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
在您的应用程序类路径(例如,在您的 jar 中)上,您可以有一个application.properties
文件,该文件为name
. 在新环境中运行时,application.properties
可以在 jar 之外提供一个文件,该文件覆盖name
. 对于一次性测试,您可以使用特定的命令行开关(例如,java -jar app.jar --name="Spring"
)启动。
2.1访问命令行属性
默认情况下,SpringApplication
将任何命令行选项参数(即以 开头的参数--
,例如--server.port=9000
)转换为 aproperty
并将它们添加到 Spring Environment
。如前所述,命令行属性始终优先于基于文件的属性源。
如果您不想将命令行属性添加到 中Environment
,可以使用 禁用它们SpringApplication.setAddCommandLineProperties(false)
。
2.2. JSON 应用程序属性
环境变量和系统属性通常有限制,这意味着某些属性名称不能使用。为了解决这个问题,Spring Boot 允许您将属性块编码为单个 JSON 结构。
当您的应用程序启动时,任何spring.application.json
或SPRING_APPLICATION_JSON
属性都将被解析并添加到Environment
.
例如,SPRING_APPLICATION_JSON
可以在 UN*X shell 的命令行中将属性作为环境变量提供:
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,您最终my.name=test
在 Spring 中Environment
。
同样的 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
.
2.3. 外部应用程序属性
当您的应用程序启动时,Spring Boot 将自动从以下位置查找并加载文件application.properties
:application.yaml
- 从类路径
- 类路径根
- 类路径
/config
包
- 从当前目录
- 当前目录
- 当前目录中的
config/
子目录 - 子目录的
config/
直接子目录
该列表按优先级排序(较低项目的值覆盖较早的项目)。加载文件中的文档被添加PropertySources
到 SpringEnvironment
中。
如果您不喜欢application
作为配置文件名,您可以通过指定spring.config.name
环境属性来切换到另一个文件名。例如,要查找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
如果spring.config.location
包含目录(而不是文件),它们应该以/
. 在运行时,它们将附加spring.config.name
在加载之前生成的名称。中指定的文件spring.config.location
直接导入。
在大多数情况下,spring.config.location
您添加的每个项目都将引用单个文件或目录。位置按照定义的顺序进行处理,后面的位置可以覆盖早期位置的值。
如果您有一个复杂的位置设置,并且您使用特定于配置文件的配置文件,您可能需要提供进一步的提示,以便 Spring Boot 知道应该如何对它们进行分组。位置组是所有被视为同一级别的位置的集合。例如,您可能希望对所有类路径位置进行分组,然后对所有外部位置进行分组。位置组中的项目应使用 . 分隔;
。有关详细信息,请参阅“配置文件特定文件”部分中的示例。
使用spring.config.location
替换默认位置配置的位置。例如,如果spring.config.location
配置了 value optional:classpath:/custom-config/,optional:file:./custom-config/
,则考虑的完整位置集是:
-
optional:classpath:custom-config/
-
optional:file:./custom-config/
如果您喜欢添加其他位置,而不是替换它们,您可以使用spring.config.additional-location
. 从其他位置加载的属性可以覆盖默认位置中的属性。例如,如果spring.config.additional-location
配置了 value 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
然后可以在运行时使用位于自定义位置之一的不同文件覆盖这些默认值。
2.3.1可选位置
默认情况下,当指定的配置数据位置不存在时,Spring Boot 会抛出一个ConfigDataLocationNotFoundException
并且你的应用程序不会启动。
如果你想指定一个位置,但你不介意它不总是存在,你可以使用optional:
前缀。您可以将此前缀与spring.config.location
andspring.config.additional-location
属性以及spring.config.import声明一起使用。
例如,spring.config.import
值optional:file:./myconfig.properties
允许您的应用程序启动,即使myconfig.properties
文件丢失。
如果您想忽略所有ConfigDataLocationNotFoundExceptions
并始终继续启动您的应用程序,您可以使用该spring.config.on-not-found
属性。将值设置为ignore
使用SpringApplication.setDefaultProperties(…)
或与系统/环境变量一起使用。
2.3.2. 通配符位置
如果配置文件位置包含*
最后一个路径段的字符,则将其视为通配符位置。加载配置时会扩展通配符,以便同时检查直接子目录。当有多个配置属性来源时,通配符位置在 Kubernetes 等环境中特别有用。
例如,如果您有一些 Redis 配置和一些 MySQL 配置,您可能希望将这两个配置分开,同时要求它们都存在于一个application.properties
文件中。这可能会导致两个单独的application.properties
文件安装在不同的位置,例如/config/redis/application.properties
和/config/mysql/application.properties
. 在这种情况下,通配符位置config/*/
, 将导致两个文件都被处理。
默认情况下,Spring Boot 包含config/*/
在默认搜索位置中。这意味着/config
将搜索 jar 之外的目录的所有子目录。
您可以自己将通配符位置与spring.config.location
andspring.config.additional-location
属性一起使用。
2.3.3配置文件特定文件
除了application
属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}
。例如,如果您的应用程序激活了一个名为prod
并使用 YAML 文件的配置文件,那么两者application.yml
都会application-prod.yml
被考虑。
特定于配置文件的属性从与标准相同的位置加载,application.properties
特定于配置文件的文件总是覆盖非特定文件。如果指定了多个配置文件,则应用最后获胜策略。例如,如果配置文件prod,live
由spring.profiles.active
属性指定,则 中的值application-prod.properties
可以被 中的值覆盖application-live.properties
。
有Environment
一组默认配置文件(默认情况下,[default]
),如果没有设置活动配置文件,则使用这些配置文件。换句话说,如果没有显式激活配置文件,则application-default
考虑来自的属性。
2.3.4导入附加数据
应用程序属性可以使用该属性从其他位置导入更多配置数据spring.config.import
。进口在发现时就被处理,并被视为紧接在声明进口的文件下方插入的附加文件。
例如,您的类路径application.properties
文件中可能包含以下内容:
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
这将触发dev.properties
当前目录中文件的导入(如果存在这样的文件)。导入的值dev.properties
将优先于触发导入的文件。在上面的示例中,dev.properties
可以重新定义spring.application.name
为不同的值。
无论声明多少次,导入都只会导入一次。在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。例如,下面的两个示例产生相同的结果:
spring.config.import=my.properties
my.property=value
my.property=value
spring.config.import=my.properties
在上述两个示例中,my.properties
文件中的值将优先于触发其导入的文件。
可以在一个spring.config.import
键下指定多个位置。位置将按照定义的顺序进行处理,以后的导入优先。
2.3.5导入无扩展名文件
某些云平台无法为卷挂载文件添加文件扩展名。要导入这些无扩展名文件,您需要给 Spring Boot 一个提示,以便它知道如何加载它们。您可以通过将扩展提示放在方括号中来做到这一点。
例如,假设您有一个/etc/config/myconfig
文件要导入为 yaml。您可以application.properties
使用以下命令从您的导入它:
特性
yaml
spring.config.import=file:/etc/config/myconfig[.yaml]
2.3.6使用配置树
在云平台(例如 Kubernetes)上运行应用程序时,您通常需要读取平台提供的配置值。将环境变量用于此类目的并不少见,但这可能有缺点,尤其是在值应该保密的情况下。
作为环境变量的替代方案,许多云平台现在允许您将配置映射到挂载的数据卷。例如,Kubernetes 可以同时卷挂载ConfigMaps和Secrets.
可以使用两种常见的卷挂载模式:
- 单个文件包含一组完整的属性(通常写为 YAML)。
- 多个文件被写入目录树,文件名成为“键”,内容成为“值”。
对于第一种情况,您可以使用上述spring.config.import
方法直接导入 YAML 或属性文件。对于第二种情况,您需要使用前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。configtree:
例如,假设 Kubernetes 挂载了以下卷:
ETC/
配置/
我的应用程序/
用户名
密码
该username
文件的内容将是一个配置值,其内容password
将是一个秘密。
要导入这些属性,您可以将以下内容添加到您的application.properties
orapplication.yaml
文件中:
spring.config.import=optional:configtree:/etc/config/
然后,您可以以通常的方式访问或注入myapp.username
和myapp.password
属性。Environment
如果您要从同一个父文件夹导入多个配置树,则可以使用通配符快捷方式。任何configtree:
以结尾的位置/*/
都会将所有直接子项导入为配置树。
例如,给定以下卷:
ETC/
配置/
数据库配置/
D b/
用户名
密码
MQ配置/
MQ/
用户名
密码
您可以configtree:/etc/config/*/
用作导入位置:
特性
spring.config.import=optional:configtree:/etc/config/*/
这将添加db.username
、db.password
和mq.username
属性mq.password
。
配置树也可用于 Docker 机密。当 Docker swarm 服务被授予对密钥的访问权限时,该密钥将被挂载到容器中。例如,如果一个名为的 secretdb.password
挂载在 location /run/secrets/
,您可以db.password
使用以下命令将其提供给 Spring 环境:
特性
spring.config.import=optional:configtree:/run/secrets/
2.3.7属性占位符
application.properties
和中的值在使用时会application.yml
通过现有值进行过滤Environment
,因此您可以参考以前定义的值(例如,来自系统属性或环境变量)。标准的${name}
属性占位符语法可以在值内的任何地方使用。属性占位符还可以使用 a:
来指定默认值,以将默认值与属性名称分开,例如${name:default}
。
以下示例显示了使用带和不带默认值的占位符:
特性
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
假设该username
属性尚未在其他地方设置,app.description
则值为MyApp is a Spring Boot application written by Unknown
。
2.3.8使用多文档文件
Spring Boot 允许您将单个物理文件拆分为多个独立添加的逻辑文档。文档从上到下按顺序处理。后面的文档可以覆盖早期文档中定义的属性。
对于application.yml
文件,使用标准的 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
2.3.9激活属性
有时仅在满足某些条件时才激活给定的一组属性很有用。例如,您可能拥有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用 有条件地激活属性文档spring.config.activate.*
。
可以使用以下激活属性:
表 2. 激活属性
财产 | 笔记 |
| 要使文档处于活动状态,必须匹配的配置文件表达式。 |
| |
例如,以下内容指定第二个文档仅在 Kubernetes 上运行时才处于活动状态,并且仅当“prod”或“staging”配置文件处于活动状态时:
特性
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
2.4. 加密属性
Spring Boot 不提供对加密属性值的任何内置支持,但是,它确实提供了修改 Spring 中包含的值所需的挂钩点Environment
。该EnvironmentPostProcessor
界面允许您Environment
在应用程序启动之前进行操作。有关详细信息,请参阅howto.html。
如果您需要一种安全的方式来存储凭据和密码,Spring Cloud Vault项目支持在HashiCorp Vault中存储外部化配置。
2.5. 使用 YAML
YAML是 JSON 的超集,因此是一种用于指定分层配置数据的便捷格式。只要您的类路径中有SnakeYAML库,SpringApplication
该类就会自动支持 YAML 作为属性的替代方案。
2.5.1将 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]
解引用器的属性键。例如,考虑以下 YAML:
my:
servers:
- "dev.example.com"
- "another.example.com"
前面的示例将转换为以下属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
2.5.2. 直接加载 YAML
Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。将YamlPropertiesFactoryBean
YAML 加载为Properties
并将YamlMapFactoryBean
YAML 加载为Map
.
YamlPropertySourceLoader
如果您想将 YAML 作为 Spring 加载,也可以使用该类PropertySource
。
2.6. 配置随机值
这RandomValuePropertySource
对于注入随机值很有用(例如,注入秘密或测试用例)。它可以生成整数、长整数、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
2.7. 配置系统环境属性
Spring Boot 支持为环境属性设置前缀。如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将很有用。系统环境属性的前缀可以直接设置在SpringApplication
.
例如,如果您将前缀设置为,则诸如在系统环境中input
的属性remote.timeout
也将被解析。input.remote.timeout
2.8. 类型安全的配置属性
使用@Value("${property}")
注解来注入配置属性有时会很麻烦,尤其是当您使用多个属性或者您的数据本质上是分层的时。Spring Boot 提供了一种使用属性的替代方法,可以让强类型 bean 管理和验证应用程序的配置。
2.8.1. JavaBean 属性绑定
可以绑定声明标准 JavaBean 属性的 bean,如下例所示:
@ConfigurationProperties("my.service")
public class MyProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
// getters / setters...
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
// getters / setters...
}
}
前面的 POJO 定义了以下属性:
-
my.service.enabled
,默认值为false
。 -
my.service.remote-address
, 具有可以从 强制转换的类型String
。 -
my.service.security.username
,具有嵌套的“安全”对象,其名称由属性的名称确定。特别是,那里根本没有使用该类型,并且可能已经使用了SecurityProperties
. -
my.service.security.password
. -
my.service.security.roles
, 集合String
默认为USER
.
2.8.2. 构造函数绑定
上一节中的示例可以以不可变的方式重写,如下例所示:
爪哇
科特林
@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {
// fields...
public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
// getters...
public static class Security {
// fields...
public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
this.username = username;
this.password = password;
this.roles = roles;
}
// getters...
}
}
在此设置中,@ConstructorBinding
注释用于指示应使用构造函数绑定。这意味着绑定器将期望找到具有您希望绑定的参数的构造函数。如果您使用的是 Java 16 或更高版本,则可以将构造函数绑定与记录一起使用。在这种情况下,除非您的记录有多个构造函数,否则无需使用@ConstructorBinding
.
类的嵌套成员@ConstructorBinding
(Security
例如上面的示例)也将通过其构造函数进行绑定。
可以使用@DefaultValue
构造函数参数指定默认值,或者在使用 Java 16 或更高版本时,使用记录组件指定默认值。将应用转换服务将String
值强制为缺失属性的目标类型。
参考前面的示例,如果没有属性绑定到Security
,则MyProperties
实例将包含 的null
值security
。要使其包含一个非空实例,Security
即使没有绑定任何属性(使用 Kotlin 时,这将要求 的username
和password
参数Security
声明为可空,因为它们没有默认值),请使用空@DefaultValue
注释:
public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
2.8.3. 启用 @ConfigurationProperties 注释的类型
Spring Boot 提供了绑定@ConfigurationProperties
类型并将它们注册为 bean 的基础设施。
@ConfigurationProperties
在这些情况下,请使用@EnableConfigurationProperties
注释指定要处理的类型列表。这可以在任何@Configuration
类上完成,如下例所示:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {
}
要使用配置属性扫描,请将@ConfigurationPropertiesScan
注释添加到您的应用程序。通常,它被添加到带有注释的主应用程序类中,@SpringBootApplication
但它可以添加到任何@Configuration
类中。默认情况下,扫描将从声明注解的类的包中进行。如果要定义要扫描的特定包,可以按照以下示例进行操作:
@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {
}
我们建议@ConfigurationProperties
只处理环境,特别是不要从上下文中注入其他 bean。对于极端情况,可以使用 setter 注入或*Aware
框架提供的任何接口(例如,EnvironmentAware
如果您需要访问Environment
. 如果您仍想使用构造函数注入其他 bean,则必须使用配置属性 bean 进行注释@Component
并使用基于 JavaBean 的属性绑定。
2.8.4使用 @ConfigurationProperties 注释的类型
这种配置风格特别适用于SpringApplication
外部 YAML 配置,如下例所示:
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
要使用@ConfigurationProperties
bean,您可以像注入任何其他 bean 一样注入它们,如以下示例所示:
@Service
public class MyService {
private final SomeProperties properties;
public MyService(SomeProperties properties) {
this.properties = properties;
}
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
server.start();
// ...
}
// ...
}
2.8.5第三方配置
除了@ConfigurationProperties
用于注释类之外,您还可以在公共@Bean
方法上使用它。当您想要将属性绑定到您无法控制的第三方组件时,这样做会特别有用。
要从Environment
属性配置 bean,请添加@ConfigurationProperties
到其 bean 注册,如以下示例所示:
@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {
@Bean
@ConfigurationProperties(prefix = "another")
public AnotherComponent anotherComponent() {
return new AnotherComponent();
}
}
使用前缀定义的任何 JavaBean 属性都以类似于前面示例的方式another
映射到该bean。AnotherComponent
SomeProperties
2.8.6轻松绑定
Spring Boot 使用一些宽松的规则将Environment
属性绑定到bean,因此属性名称和 bean 属性名称@ConfigurationProperties
之间不需要完全匹配。Environment
这很有用的常见示例包括用破折号分隔的环境属性(例如,context-path
绑定到contextPath
)和大写的环境属性(例如,PORT
绑定到port
)。
例如,考虑以下@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;
}
}
使用上述代码,可以使用以下属性名称:
表 3. 宽松的绑定
财产 | 笔记 |
| 烤肉盒,推荐用于 |
| 标准驼峰式语法。 |
| 下划线表示法,这是在文件中使用的另一种 |
| 大写格式,在使用系统环境变量时推荐使用。 |
表 4. 每个属性源的宽松绑定规则
属性来源 | 简单的 | 列表 |
属性文件 | Camel case、kebab case 或下划线表示法 | |
YAML 文件 | Camel case、kebab case 或下划线表示法 | 标准 YAML 列表语法或逗号分隔值 |
环境变量 | 下划线作为分隔符的大写格式(请参阅从环境变量绑定)。 | 下划线包围的数值(请参阅从环境变量绑定) |
系统属性 | Camel case、kebab case 或下划线表示法 | |
绑定地图
绑定到Map
属性时,您可能需要使用特殊的括号表示法,以便key
保留原始值。如果键没有被 包围[]
,则任何不是字母数字的字符都将-
被.
删除。
例如,考虑将以下属性绑定到 a Map<String,String>
:
my.map.[/key1]=value1
my.map.[/key2]=value2
my.map./key3=value3
上面的属性将绑定到一个Map
with /key1
,/key2
并key3
作为映射中的键。斜线已被删除,key3
因为它没有被方括号包围。
当绑定到标量值时,.
其中的键不需要用[]
. 标量值包括枚举和java.lang
包中除Object
. 绑定a.b=c
到Map<String, String>
将保留.
键中的 并返回带有条目的 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
toz
或A
to Z
)、数字(0
to 9
)或下划线字符(_
)。按照惯例,Unix shell 变量的名称也将大写。
Spring Boot 宽松的绑定规则尽可能地与这些命名限制兼容。
要将规范形式的属性名称转换为环境变量名称,您可以遵循以下规则:
- 将点 (
.
) 替换为下划线 (_
)。 - 删除所有破折号 (
-
)。 - 转换为大写。
例如,配置属性spring.main.log-startup-info
将是一个名为SPRING_MAIN_LOGSTARTUPINFO
.
绑定到对象列表时也可以使用环境变量。要绑定到 a List
,元素编号应在变量名中用下划线括起来。
例如,配置属性my.service[0].other
将使用名为MY_SERVICE_0_OTHER
.
2.8.7。合并复杂类型
当列表配置在多个位置时,覆盖通过替换整个列表来工作。
例如,假设一个MyPojo
对象具有默认的name
和description
属性。null
以下示例公开了MyPojo
来自的对象列表MyProperties
:
@ConfigurationProperties("my")
public class MyProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
考虑以下配置:
特性
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
如果dev
配置文件未激活,则MyProperties.list
包含一个MyPojo
条目,如先前定义的那样。但是,如果dev
启用了配置文件,则list
仍然只包含一个条目(名称为my another name
,描述为null
)。此配置不会将第二个MyPojo
实例添加到列表中,并且不会合并项目。
当List
在多个配置文件中指定 a 时,使用具有最高优先级的一个(并且仅使用那个)。考虑以下示例:
特性
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
在前面的示例中,如果dev
配置文件处于活动状态,则MyProperties.list
包含一个 MyPojo
条目(名称为my another name
,描述为null
)。对于 YAML,逗号分隔的列表和 YAML 列表都可用于完全覆盖列表的内容。
对于Map
属性,您可以绑定从多个来源提取的属性值。但是,对于多个源中的相同属性,将使用具有最高优先级的属性。以下示例公开了Map<String, MyPojo>
from MyProperties
:
@ConfigurationProperties("my")
public class MyProperties {
private final Map<String, MyPojo> map = new LinkedHashMap<>();
public Map<String, MyPojo> getMap() {
return this.map;
}
}
考虑以下配置:
特性
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
如果dev
配置文件未激活,则MyProperties.map
包含一个带有键的条目key1
(名称为my name 1
,描述为my description 1
)。但是,如果dev
启用了配置文件,则map
包含两个带有键的条目key1
(名称为dev name 1
,描述为my description 1
)和key2
(名称为dev name 2
,描述为dev description 2
)。
2.8.8属性转换
@ConfigurationProperties
Spring Boot 在绑定到bean时尝试将外部应用程序属性强制转换为正确的类型。如果您需要自定义类型转换,您可以提供一个ConversionService
bean(带有一个名为 的 bean conversionService
)或自定义属性编辑器(通过一个CustomEditorConfigurer
bean)或自定义Converters
(带有注释为 的 bean 定义@ConfigurationPropertiesBinding
)。
转换持续时间
Spring Boot 专门支持表达持续时间。如果公开java.time.Duration
属性,则应用程序属性中的以下格式可用:
- 常规
long
表示(使用毫秒作为默认单位,除非@DurationUnit
已指定 a) - 使用的标准 ISO-8601 格式java.time.Duration
- 一种更易读的格式,其中值和单位耦合(
10s
意味着 10 秒)
考虑以下示例:
@ConfigurationProperties("my")
public class MyProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
// getters / setters...
}
要指定 30 秒的会话超时30
,PT30S
和30s
都是等效的。500ms 的读取超时可以用以下任何一种形式指定500
:PT0.5S
和500ms
。
您还可以使用任何受支持的单位。这些是:
-
ns
纳秒 -
us
微秒 -
ms
毫秒 -
s
几秒钟 -
m
for minutes -
h
for hours -
d
for days
The default unit is milliseconds and can be overridden using @DurationUnit
as illustrated in the sample above.
If you prefer to use constructor binding, the same properties can be exposed, as shown in the following example:
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
// fields...
public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
@DefaultValue("1000ms") Duration readTimeout) {
this.sessionTimeout = sessionTimeout;
this.readTimeout = readTimeout;
}
// getters...
}
转换期间
除了持续时间,Spring Boot 还可以使用java.time.Period
类型。以下格式可用于应用程序属性:
- 常规
int
表示(使用天作为默认单位,除非@PeriodUnit
已指定 a) - 使用的标准 ISO-8601 格式java.time.Period
- 一种更简单的格式,其中值和单位对耦合(
1y3d
表示 1 年和 3 天)
简单格式支持以下单位:
-
y
多年 -
m
几个月 -
w
数周 -
d
好几天
转换数据大小
Spring Framework 有一个DataSize
值类型,它以字节为单位表示大小。如果公开DataSize
属性,则应用程序属性中的以下格式可用:
- 常规
long
表示(使用字节作为默认单位,除非@DataSizeUnit
已指定 a) - 一种更易读的格式,其中值和单位是耦合的(
10MB
意味着 10 兆字节)
考虑以下示例:
@ConfigurationProperties("my")
public class MyProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
// getters/setters...
}
指定缓冲区大小为 10 兆字节,10
并且10MB
是等价的。可以将 256 字节的大小阈值指定为256
或256B
。
您还可以使用任何受支持的单位。这些是:
-
B
对于字节 -
KB
千字节 -
MB
兆字节 -
GB
千兆字节 -
TB
太字节
默认单位是字节,可以使用@DataSizeUnit
上面示例中的说明进行覆盖。
如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如下例所示:
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
// fields...
public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
@DefaultValue("512B") DataSize sizeThreshold) {
this.bufferSize = bufferSize;
this.sizeThreshold = sizeThreshold;
}
// getters...
}
2.8.9@ConfigurationProperties 验证
@ConfigurationProperties
每当使用 Spring 的注解进行注解时,Spring Boot 都会尝试验证类@Validated
。javax.validation
您可以直接在配置类上使用 JSR-303约束注释。为此,请确保您的类路径中存在兼容的 JSR-303 实现,然后将约束注释添加到您的字段,如以下示例所示:
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
// getters/setters...
}
为确保始终为嵌套属性触发验证,即使未找到任何属性,关联字段也必须使用 注释@Valid
。以下示例基于前面的示例构建MyProperties
:
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// getters/setters...
public static class Security {
@NotEmpty
private String username;
// getters/setters...
}
}
您还可以Validator
通过创建一个名为configurationPropertiesValidator
. @Bean
应该声明该方法static
。配置属性验证器是在应用程序生命周期的早期创建的,将@Bean
方法声明为静态允许创建 bean 而无需实例化@Configuration
类。这样做可以避免早期实例化可能导致的任何问题。
2.8.10。@ConfigurationProperties 与 @Value
@Value
注解是一个核心容器特性,它不提供与类型安全配置属性相同的特性。下表总结了@ConfigurationProperties
和支持的功能@Value
:
特征 | | |
轻松绑定 | 是的 | 有限(见下文注释) |
元数据支持 | 是的 | 不 |
| 不 | 是的 |
如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个 POJO 中,并用@ConfigurationProperties
. 这样做将为您提供结构化的、类型安全的对象,您可以将其注入到您自己的 bean 中。
SpEL
在解析这些文件和填充环境时,不会处理来自应用程序属性文件的表达式。但是,可以在 中编写SpEL
表达式@Value
。如果应用程序属性文件中的属性值是一个SpEL
表达式,则在通过@Value
.