0
点赞
收藏
分享

微信扫一扫

Spring Boot核心功能

本节深入探讨 Spring Boot 的细节。在这里,您可以了解您可能想要使用和自定义的主要功能。如果您还没有这样做,您可能需要阅读“ getting-started.html ”和“ using.html ”部分,这样您就有了良好的基础知识。

Spring Boot核心功能_spring

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​​可以使用方法 on​​SpringApplicationBuilder​​或​​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. 横幅变量

多变的

描述

​${application.version}​

应用程序的版本号,如​​MANIFEST.MF​​​. 例如,​​Implementation-Version: 1.0​​​打印为​​1.0​​.

​${application.formatted-version}​

应用程序的版本号,在中声明​​MANIFEST.MF​​​并格式化为显示(用括号括起来并以 为前缀​​v​​​)。例如​​(v1.0)​​.

​${spring-boot.version}​

您正在使用的 Spring Boot 版本。例如​​2.7.5​​.

​${spring-boot.formatted-version}​

您正在使用的 Spring Boot 版本,已格式化以供显示(用括号括起来并以 为前缀​​v​​​)。例如​​(v2.7.5)​​.

​${Ansi.NAME}​​​(或​​${AnsiColor.NAME}​​​, ​​${AnsiBackground.NAME}​​​, ​​${AnsiStyle.NAME}​​)

​NAME​​​ANSI 转义码的名称在哪里。详情请参阅AnsiPropertySource。

​${application.title}​

应用程序的标题,如​​MANIFEST.MF​​​. 例如​​Implementation-Title: MyApp​​​打印为​​MyApp​​.

您还可以使用该​​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, a​​SpringApplication​​发送一些额外的应用程序事件。

当您的应用程序运行时,应用程序事件按以下顺序发送:

  1. AnApplicationStartingEvent在运行开始时但在任何处理之前发送,除了侦听器和初始化程序的注册。
  2. ​ApplicationEnvironmentPreparedEvent​​当Environment在上下文中使用的 已知但在创建上下文之前发送一个。
  3. ​ApplicationContextInitializedEvent​​当ApplicationContext准备好并调用 ApplicationContextInitializers 但在加载任何 bean 定义之前发送一个。
  4. ​ApplicationPreparedEvent​​在刷新开始之前但在加载 bean 定义之后发送一个。
  5. AnApplicationStartedEvent在上下文刷新之后但在调用任何应用程序和命令行运行程序之前发送。
  6. ​AvailabilityChangeEvent​​在 with 之后立即发送一个LivenessState.CORRECT,表明应用程序被认为是活动的。
  7. ​ApplicationReadyEvent​​在调用任何应用程序和命令行运行程序后发送一个。
  8. ​AvailabilityChangeEvent​​在 with 之后立即发送一个ReadinessState.ACCEPTING_TRAFFIC,表示应用程序已准备好为请求提供服务。
  9. 如果ApplicationFailedEvent启动时出现异常,则发送一个。

上面的列表仅包括​​SpringApplicationEvent​​与 a 绑定的 s ​​SpringApplication​​。除此之外,还发布了以下事件 after​​ApplicationPreparedEvent​​和 before ​​ApplicationStartedEvent​​:

  • A在准备好 WebServerInitializedEvent后发送。和分别是 servlet 和响应式变体。WebServerServletWebServerInitializedEventReactiveWebServerInitializedEvent
  • A在刷新​​ContextRefreshedEvent​​时发送。​​ApplicationContext​

应用程序事件是使用 Spring Framework 的事件发布机制发送的。该机制的一部分确保在子上下文中发布给侦听器的事件也发布给任何祖先上下文中的侦听器。因此,如果您的应用程序使用​​SpringApplication​​实例层次结构,则侦听器可能会接收到相同类型的应用程序事件的多个实例。

为了让您的侦听器区分其上下文的事件和后代上下文的事件,它应该请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现来注入上下文,​​ApplicationContextAware​​或者,如果侦听器是 bean,则可以使用​​@Autowired​​.

1.8. 网络环境

A​​SpringApplication​​尝试​​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​​顺序,旨在允许明智地覆盖值。之后的属性源可以覆盖之前定义的值。来源按以下顺序考虑:

  1. 默认属性(由设置指定SpringApplication.setDefaultProperties)。
  2. @PropertySource@Configuration您的课程上的注释。请注意,Environment在刷新应用程序上下文之前,不会将此类属性源添加到 中。配置某些属性(例如在刷新开始之前读取的logging.*和)为时已晚。spring.main.*
  3. 配置数据(例如application.properties文件)。
  4. 仅在中RandomValuePropertySource具有属性的 A。random.*
  5. 操作系统环境变量。
  6. Java 系统属性 ( System.getProperties())。
  7. JNDI 属性来自java:comp/env.
  8. ​ServletContext​​初始化参数。
  9. ​ServletConfig​​初始化参数。
  10. 来自SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联 JSON)的属性。
  11. 命令行参数。
  12. ​properties​​属性在你的测试。可用于测试应用程序的特定部分@SpringBootTest的测试注释。
  13. @TestPropertySource测试上的注释。
  14. $HOME/.config/spring-boot当 devtools 处于活动状态时,目录中的Devtools 全局设置属性。

配置数据文件按以下顺序考虑:

  1. 打包在 jar 中的应用程序属性application.properties(和 YAML 变体)。
  2. 打包在您的 jar(application-{profile}.properties和 YAML 变体)中的特定于配置文件的应用程序属性。
  3. 打包 jar(application.properties和 YAML 变体)之外的应用程序属性。
  4. 打包的 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​​)转换为 a​​property​​并将它们添加到 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​

  1. 从类路径
  1. 类路径根
  2. 类路径/config
  1. 从当前目录
  1. 当前目录
  2. 当前目录中的config/子目录
  3. 子目录的config/直接子目录

该列表按优先级排序(较低项目的值覆盖较早的项目)。加载文件中的文档被添加​​PropertySources​​到 Spring​​Environment​​中。

如果您不喜欢​​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/​​,则考虑的完整位置集是:

  1. ​optional:classpath:custom-config/​
  2. ​optional:file:./custom-config/​

如果您喜欢添加其他位置,而不是替换它们,您可以使用​​spring.config.additional-location​​. 从其他位置加载的属性可以覆盖默认位置中的属性。例如,如果​​spring.config.additional-location​​配置了 value ​​optional:classpath:/custom-config/,optional:file:./custom-config/​​,则考虑的完整位置集是:

  1. ​optional:classpath:/;optional:classpath:/config/​
  2. ​optional:file:./;optional:file:./config/;optional:file:./config/*/​
  3. ​optional:classpath:custom-config/​
  4. ​optional:file:./custom-config/​

这种搜索顺序允许您在一个配置文件中指定默认值,然后在另一个配置文件中选择性地覆盖这些值。您可以在默认位置之一​​application.properties​​​(或您选择的任何其他基本名称)中为您的应用程序提供默认值。​​spring.config.name​​然后可以在运行时使用位于自定义位置之一的不同文件覆盖这些默认值。

2.3.1可选位置

默认情况下,当指定的配置数据位置不存在时,Spring Boot 会抛出一个​​ConfigDataLocationNotFoundException​​并且你的应用程序不会启动。

如果你想指定一个位置,但你不介意它不总是存在,你可以使用​​optional:​​前缀。您可以将此前缀与​​spring.config.location​​and​​spring.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​​​and​​spring.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.

可以使用两种常见的卷挂载模式:

  1. 单个文件包含一组完整的属性(通常写为 YAML)。
  2. 多个文件被写入目录树,文件名成为“键”,内容成为“值”。

对于第一种情况,您可以使用上述​​spring.config.import​​方法直接导入 YAML 或属性文件。对于第二种情况,您需要使用前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。​​configtree:​

例如,假设 Kubernetes 挂载了以下卷:

ETC/
配置/
我的应用程序/
用户名
密码

该​​username​​文件的内容将是一个配置值,其内容​​password​​将是一个秘密。

要导入这些属性,您可以将以下内容添加到您的​​application.properties​​or​​application.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 服务被授予对密钥的访问权限时,该密钥将被挂载到容器中。例如,如果一个名为的 secret​​db.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. 激活属性

财产

笔记

​on-profile​

要使文档处于活动状态,必须匹配的配置文件表达式。

​on-cloud-platform​

​CloudPlatform​​必须检测到文档才能处于活动状态。

例如,以下内容指定第二个文档仅在 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. 宽松的绑定

财产

笔记

​my.main-project.person.first-name​

烤肉盒,推荐用于​​.properties​​​和​​.yml​​文件。

​my.main-project.person.firstName​

标准驼峰式语法。

​my.main-project.person.first_name​

下划线表示法,这是在文件中使用的另一种​​.properties​​​格式​​.yml​​。

​MY_MAINPROJECT_PERSON_FIRSTNAME​

大写格式,在使用系统环境变量时推荐使用。

表 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​​to​​z​​或​​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​​:

特征

​@ConfigurationProperties​

​@Value​

轻松绑定

是的

有限(见下文注释)

元数据支持

是的

​SpEL​​评估

是的

如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个 POJO 中,并用​​@ConfigurationProperties​​. 这样做将为您提供结构化的、类型安全的对象,您可以将其注入到您自己的 bean 中。

​SpEL​​在解析这些文件和填充环境时,不会处理来自应用程序属性文件的表达式。但是,可以在 中编写​​SpEL​​表达式​​@Value​​。如果应用程序属性文件中的属性值是一个​​SpEL​​表达式,则在通过​​@Value​​.

举报

相关推荐

0 条评论