本节将深入介绍Spring Boot。在这里,您可以了解可能要使用和自定义的关键功能。如果您尚未这样做,则可能需要阅读“ Getting -started.html ”和“ using-spring-boot.html ”部分,以便您有足够的基础知识。

1. SpringApplication

SpringApplication类提供了一个方便的方式来引导该从开始Spring应用程序main()的方法。在许多情况下,您可以委托给静态SpringApplication.run方法,如以下示例所示:

  1. public static void main(String[] args) {
  2. SpringApplication.run(MySpringConfiguration.class, args);
  3. }

当您的应用程序启动时,您应该看到类似于以下输出的内容:
_
/ \ / __
__ \ \ \ \
(()\ __
|’ |’ | |’ \ / ` | \ \ \ \ \
\ / )| | )| | | | | || ( | |))))
‘| _
| . | | | | | | \ ,| / / / /
======== | | ============= | __ / = / / / _ /
:: Spring Boot :: v2.4.3

2019-04-31 13:09:54.117 INFO 56603 —- [main] osbsapp.SampleApplication:在我的计算机上使用PID 56603(/apps/myapp.jar由pwebb启动)启动SampleApplication v0.1.0
2019-04-31 13:09:54.166 INFO 56603 —- [main] ationConfigServletWebServerApplicationContext:刷新org.springframework.boot.web.ser vlet.context.AnnotationConfigServletWebServerApplicationContext @ 6e5a8246:启动日期[WDT Jul 31 00:08:16 PDT 2013];上下文层次结构的根
2019-04-01 13:09:56.912信息41370 —- [main] .t.TomcatServletWebServerFactory:服务器初始化为端口:8080
2019-04-01 13:09:57.501信息41370 —- [main] osbsapp.SampleApplication:在2.992秒内启动SampleApplication(JVM运行3.658)
默认情况下,显示INFO日志消息,包括一些相关的启动详细信息,例如启动应用程序的用户。如果您需要除以外的其他日志级别INFO,则可以按日志级别中所述进行设置。使用主应用程序类包中的实现版本来确定应用程序版本。设置spring.main.log-startup-info为可以关闭启动信息记录false。这还将关闭应用程序活动配置文件的日志记录。

要在启动期间添加其他日志记录,可以logStartupInfo(boolean)在的子类中进行覆盖SpringApplication

1.1 启动失败

如果您的应用程序无法启动,则注册FailureAnalyzers后将有机会提供专门的错误消息和解决该问题的具体措施。例如,如果在port上启动Web应用程序8080并且该端口已在使用中,则应该看到类似于以下消息的内容:
**
申请启动失败
**

描述:

嵌入式Servlet容器无法启动。端口8080已被使用。

行动:

确定并停止正在端口8080上侦听的进程,或将此应用程序配置为在另一个端口上侦听。

Spring Boot提供了许多FailureAnalyzer实现,您可以添加自己的实现

如果没有故障分析器能够处理该异常,您仍然可以显示完整情况报告,以更好地了解出了什么问题。要做到这一点,你需要使debug财产启用DEBUG日志记录org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
例如,如果使用来运行应用程序java -jar,则可以debug按如下所示启用属性:
$ java -jar myproject-0.0.1-SNAPSHOT.jar —debug

1.2 延迟初始化

SpringApplication允许延迟地初始化应用程序。启用惰性初始化后,将根据需要创建bean,而不是在应用程序启动期间创建bean。因此,启用延迟初始化可以减少应用程序启动所花费的时间。在Web应用程序中,启用延迟初始化将导致许多与Web相关的Bean直到收到HTTP请求后才被初始化。
延迟初始化的缺点是,它可能会延迟发现应用程序问题的时间。如果延迟配置了错误配置的Bean,则在启动过程中将不再发生故障,并且只有在初始化Bean时问题才会变得明显。还必须注意确保JVM具有足够的内存来容纳所有应用程序的bean,而不仅仅是启动期间初始化的bean。由于这些原因,默认情况下默认不启用延迟初始化,因此建议在启用延迟初始化之前先对JVM的堆大小进行微调。
可以使用lazyInitializationon方法SpringApplicationBuildersetLazyInitializationon方法以编程方式启用延迟初始化SpringApplication。另外,可以使用spring.main.lazy-initialization以下示例中所示的属性来启用它:
特性
Yaml

  1. spring:
  2. main:
  3. lazy-initialization: true
如果要在对应用程序其余部分使用延迟初始化时禁用某些bean的延迟初始化,则可以使用@Lazy(false)批注将它们的延迟属性显式设置为false 。

1.3 自定义横幅

可以通过将banner.txt文件添加到类路径或将spring.banner.location属性设置为此类文件的位置来更改启动时打印的横幅。如果文件的编码不是UTF-8,则可以设置spring.banner.charset。除了一个文本文件,你还可以添加一个banner.gifbanner.jpgbanner.png图像文件到类路径或设置spring.banner.image.location属性。图像将转换为ASCII艺术作品并打印在任何文字横幅上方。
banner.txt文件内部,可以使用以下任意占位符:
表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.4.3
${spring-boot.formatted-version} 您正在使用的Spring Boot版本,其格式用于显示(用括号括起来,并带有前缀v)。例如(v2.4.3)
${Ansi.NAME}(或${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME} NAMEANSI转义代码的名称在哪里。有关AnsiPropertySource详细信息,请参见。
${application.title} 您的应用程序的标题,如中所述MANIFEST.MF。例如Implementation-Title: MyApp打印为MyApp
SpringApplication.setBanner(…)如果要以编程方式生成横幅,则可以使用 该方法。使用该org.springframework.boot.Banner接口并实现您自己的printBanner()方法。

您还可以使用该spring.main.banner-mode属性来确定横幅是否必须在System.outconsole)上打印,发送到配置的记录器(log)或根本不制作(off)。
打印的横幅注册为下面的这名一个singleton bean: springBootBanner

${application.version}${application.formatted-version},如果你使用Spring启动发射特性才可用。如果您正在运行未包装的jar并以开头,则无法解析这些值java -cp <classpath> <mainclass>
因此,我们建议您始终使用来启动未包装的罐子java org.springframework.boot.loader.JarLauncher。这将application.*在构建类路径和启动应用程序之前初始化标题变量。

1.4 自定义SpringApplication

如果SpringApplication默认设置不符合您的喜好,则可以创建一个本地实例并对其进行自定义。例如,要关闭横幅,您可以编写:

  1. public static void main(String[] args) {
  2. SpringApplication app = new SpringApplication(MySpringConfiguration.class);
  3. app.setBannerMode(Banner.Mode.OFF);
  4. app.run(args);
  5. }
传递给构造函数的参数SpringApplication是Spring bean的配置源。在大多数情况下,它们是对@Configuration类的引用,但也可以是对XML配置或应扫描的程序包的引用。

也可以SpringApplication通过使用application.properties文件来配置。有关详细信息,请参见外部化配置
有关配置选项的完整列表,请参见SpringApplicationJavadoc

1.5 Fluent Builder API

如果您需要构建ApplicationContext层次结构(具有父/子关系的多个上下文),或者您更喜欢使用“流利的”构建器API,则可以使用SpringApplicationBuilder
SpringApplicationBuilder让要链接的多个方法调用,并且包括parentchild其让你创建层次结构,以显示在下面的示例性方法:

  1. new SpringApplicationBuilder()
  2. .sources(Parent.class)
  3. .child(Application.class)
  4. .bannerMode(Banner.Mode.OFF)
  5. .run(args);
创建ApplicationContext层次结构时有一些限制。例如,Web组件必须包含在子上下文中,并且Environment父和子上下文都使用相同的组件。有关完整的详细信息,请参见SpringApplicationBuilderJavadoc

1.6 应用程序可用性

在平台上部署后,应用程序可以使用诸如Kubernetes Probes之类的基础结构向平台提供有关其可用性的信息。Spring Boot对常用的“活动性”和“就绪性”可用性状态提供了开箱即用的支持。如果您使用的是Spring Boot的“执行器”支持,那么这些状态将作为运行状况端点组公开。
另外,您还可以通过将ApplicationAvailability接口注入您自己的bean中来获取可用性状态。

1.6.1 生命状态

应用程序的“活动”状态表明其内部状态是否允许其正常运行,或者在当前出现故障时自行恢复。损坏的“活动”状态意味着应用程序处于无法恢复的状态,并且基础结构应重新启动应用程序。

通常,“活动”状态不应基于外部检查(例如健康检查)。如果确实如此,则发生故障的外部系统(数据库,Web API,外部缓存)将触发整个平台的大量重启和级联故障。

Spring Boot应用程序的内部状态主要由Spring表示ApplicationContext。如果应用程序上下文已成功启动,则Spring Boot会假定该应用程序处于有效状态。刷新上下文后,应用程序即被视为处于活动状态,请参阅Spring Boot应用程序生命周期和相关的Application Events

1.6.2 准备状态

应用程序的“就绪”状态告诉应用程序是否已准备好处理流量。失败的“就绪”状态告诉平台当前不应将流量路由到应用程序。这通常发生在启动过程中,正在处理CommandLineRunnerApplicationRunner处理组件时,或者在任何时候,如果应用程序认为它太忙而无法获得额外的流量,就会发生这种情况。
一旦调用了应用程序和命令行运行程序,就认为该应用程序已准备就绪,请参阅Spring Boot应用程序生命周期和相关的Application Events

预期在启动期间运行的任务应由CommandLineRunnerApplicationRunner组件执行,而不是使用Spring组件生命周期回调(例如)@PostConstruct

1.6.3 管理应用程序可用性状态

通过注入ApplicationAvailability接口并在接口上调用方法,应用程序组件可以随时检索当前的可用性状态。应用程序通常会希望监听状态更新或更新应用程序的状态。
例如,我们可以将应用程序的“就绪”状态导出到一个文件,以便Kubernetes的“ exec Probe”可以查看此文件:

  1. @Component
  2. public class ReadinessStateExporter {
  3. @EventListener
  4. public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
  5. switch (event.getState()) {
  6. case ACCEPTING_TRAFFIC:
  7. // create file /tmp/healthy
  8. break;
  9. case REFUSING_TRAFFIC:
  10. // remove file /tmp/healthy
  11. break;
  12. }
  13. }
  14. }

当应用程序崩溃且无法恢复时,我们还可以更新应用程序的状态:

  1. @Component
  2. public class LocalCacheVerifier {
  3. private final ApplicationEventPublisher eventPublisher;
  4. public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
  5. this.eventPublisher = eventPublisher;
  6. }
  7. public void checkLocalCache() {
  8. try {
  9. //...
  10. }
  11. catch (CacheCompletelyBrokenException ex) {
  12. AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
  13. }
  14. }
  15. }

Spring Boot通过Actuator Health Endpoints为“活动性”和“就绪性”提供Kubernetes HTTP探针。您可以在专用部分中获得有关在Kubernetes上部署Spring Boot应用程序的更多指南。

1.7 应用程序事件和监听器

除了通常的Spring Framework事件(例如)外ContextRefreshedEventSpringApplication还会发送一些其他应用程序事件。

实际上在ApplicationContext创建之前会触发一些事件,因此您无法将其注册为@Bean。您可以使用SpringApplication.addListeners(…)方法或SpringApplicationBuilder.listeners(…)方法注册它们。
如果您希望这些侦听器自动注册,而不管创建应用程序的方式如何,都可以将META-INF/spring.factories文件添加到项目中,并使用org.springframework.context.ApplicationListener键引用您的侦听器,如以下示例所示:org.springframework.context.ApplicationListener = com.example.project.MyListener

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

  1. ApplicationStartingEvent在运行开始时发送an ,但在进行任何处理之前(侦听器和初始化程序的注册除外)发送。
  2. 一个ApplicationEnvironmentPreparedEvent当被发送Environment到中已知的上下文中使用,但是在创建上下文之前。
  3. ApplicationContextInitializedEventApplicationContext准备好且已调用ApplicationContextInitializers之后但未加载任何bean定义之前,发送an 。
  4. ApplicationPreparedEvent在刷新开始之前但在加载bean定义之后发送an 。
  5. 一个ApplicationStartedEvent上下文已被刷新后发送,但是任何应用程序和命令行亚军都被调用前。
  6. 紧随AvailabilityChangeEvent其后发送的LivenessState.CORRECT,表示该应用程序被视为已生效。
  7. ApplicationReadyEvent任何之后被送到应用程序和命令行亚军已被调用。
  8. 紧随AvailabilityChangeEvent其后发送一个,ReadinessState.ACCEPTING_TRAFFIC以指示该应用程序已准备好处理请求。
  9. 一个ApplicationFailedEvent如果在启动时异常发送。

上面的列表仅包含SpringApplicationEvent与绑定的SpringApplication。除这些以外,以下事件也在之后ApplicationPreparedEvent和之前发布ApplicationStartedEvent

  • 准备就绪 WebServerInitializedEvent后发送A。和分别是servlet和反应式变量。WebServer``ServletWebServerInitializedEvent``ReactiveWebServerInitializedEvent
  • 刷新ContextRefreshedEvent时发送A。ApplicationContext
    | | 您通常不需要使用应用程序事件,但是很容易知道它们的存在。在内部,Spring Boot使用事件来处理各种任务。 | | :—-: | —- |
默认情况下,事件侦听器不应在可能在同一线程中执行的任务上运行冗长的任务。考虑改用应用程序和命令行运行程序

应用程序事件是通过使用Spring Framework的事件发布机制发送的。此机制的一部分确保在子级上下文中发布给侦听器的事件也在任何祖先上下文中也发布给侦听器。结果,如果您的应用程序使用SpringApplication实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。
为了使您的侦听器能够区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现来注入上下文,ApplicationContextAware或者,如果侦听器是bean,则可以使用注入上下文@Autowired

1.8 网络环境

一个SpringApplication试图创建正确类型的ApplicationContext代表您。用于确定a的算法WebApplicationType如下:

  • 如果存在Spring MVC,AnnotationConfigServletWebServerApplicationContext则使用
  • 如果不存在Spring MVC且存在Spring WebFlux,AnnotationConfigReactiveWebServerApplicationContext则使用
  • 否则,AnnotationConfigApplicationContext使用

这意味着,如果您WebClient在同一应用程序中使用Spring MVC和Spring WebFlux中的新功能,则默认情况下将使用Spring MVC。您可以通过调用轻松覆盖它setWebApplicationType(WebApplicationType)
也可以完全控制ApplicationContext调用所使用的类型setApplicationContextClass(…)

在JUnit测试中setWebApplicationType(WebApplicationType.NONE)使用时 通常需要调用SpringApplication

1.9 访问应用程序参数

如果您需要访问传递给的应用程序参数,则SpringApplication.run(…)可以注入org.springframework.boot.ApplicationArgumentsBean。该ApplicationArguments接口提供对原始String[]参数以及已解析optionnon-option参数的访问,如以下示例所示:

  1. import org.springframework.boot.*;
  2. import org.springframework.beans.factory.annotation.*;
  3. import org.springframework.stereotype.*;
  4. @Component
  5. public class MyBean {
  6. @Autowired
  7. public MyBean(ApplicationArguments args) {
  8. boolean debug = args.containsOption("debug");
  9. List<String> files = args.getNonOptionArgs();
  10. // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
  11. }
  12. }
Spring Boot也CommandLinePropertySource向Spring注册了一个Environment。这样,您还可以使用@Value注释注入单个应用程序参数。

1.10 使用ApplicationRunner或CommandLineRunner

如果启动后需要运行一些特定的代码SpringApplication,则可以实现ApplicationRunnerCommandLineRunner接口。这两个接口以相同的方式工作,并提供一个单一的run方法,该方法在SpringApplication.run(…)完成之前就被调用。

该合同非常适合应在应用程序启动后但开始接受流量之前运行的任务。

所述CommandLineRunner接口提供访问的应用程序的参数作为一个字符串数组,而ApplicationRunner用途ApplicationArguments接口前面讨论。以下示例显示了一个CommandLineRunnerwithrun方法:

  1. import org.springframework.boot.*;
  2. import org.springframework.stereotype.*;
  3. @Component
  4. public class MyBean implements CommandLineRunner {
  5. public void run(String... args) {
  6. // Do something...
  7. }
  8. }

如果定义了多个CommandLineRunnerApplicationRunner必须按特定顺序调用的bean,则可以额外实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order批注。

1.11 申请退出

每个都SpringApplication向JVM注册一个关闭钩子,以确保ApplicationContext退出时正常关闭。可以使用所有标准的Spring生命周期回调(例如DisposableBean接口或@PreDestroy批注)。
另外,org.springframework.boot.ExitCodeGenerator如果bean希望在SpringApplication.exit()调用时返回特定的退出代码,则可以实现该接口。然后可以将此退出代码传递System.exit()为状态代码,以将其返回,如以下示例所示:

  1. @SpringBootApplication
  2. public class ExitCodeApplication {
  3. @Bean
  4. public ExitCodeGenerator exitCodeGenerator() {
  5. return () -> 42;
  6. }
  7. public static void main(String[] args) {
  8. System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
  9. }
  10. }

而且,该ExitCodeGenerator接口可以通过异常来实现。当遇到这样的异常时,Spring Boot返回由实现的getExitCode()方法提供的退出代码。

1.12 管理员功能

通过指定spring.application.admin.enabled属性,可以为应用程序启用与管理员相关的功能。这将SpringApplicationAdminMXBean在平台上公开MBeanServer。您可以使用此功能来远程管理Spring Boot应用程序。此功能对于任何服务包装器实现也可能有用。

如果您想知道应用程序在哪个HTTP端口上运行,请通过键获取属性local.server.port

1.13 应用程序启动跟踪

在应用程序启动期间,SpringApplicationApplicationContext执行许多与应用程序生命周期,bean生命周期甚至处理应用程序事件有关的任务。使用ApplicationStartupSpring Framework ,您可以使用StartupSteps跟踪应用程序的启动顺序。可以收集这些数据以进行概要分析,或者只是为了更好地了解应用程序启动过程。
您可以ApplicationStartup在设置SpringApplication实例时选择一种实现。例如,要使用BufferingApplicationStartup,您可以编写:

  1. public static void main(String[] args) {
  2. SpringApplication app = new SpringApplication(MySpringConfiguration.class);
  3. app.setApplicationStartup(new BufferingApplicationStartup(2048));
  4. app.run(args);
  5. }

FlightRecorderApplicationStartupSpring Framework提供了第一个可用的实现。它将特定于Spring的启动事件添加到Java Flight Recorder会话中,旨在对应用程序进行性能分析并将其Spring上下文生命周期与JVM事件相关联(例如分配,GC,类加载…)。配置完成后,您可以在启用了Flight Recorder的情况下通过运行应用程序来记录数据:

  1. $ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

Spring Boot随BufferingApplicationStartup变种一起提供;此实现旨在缓冲启动步骤,并将其排入外部度量标准系统。应用程序可以BufferingApplicationStartup在任何组件中要求类型的Bean 。此外,Spring Boot Actuator将公开一个startup端点以将此信息公开为JSON文档

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,只有在拥有性能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属性的,如以下示例所示:

  1. import org.springframework.stereotype.*;
  2. import org.springframework.beans.factory.annotation.*;
  3. @Component
  4. public class MyBean {
  5. @Value("${name}")
  6. private String name;
  7. // ...
  8. }

在您的应用程序类路径上(例如,在jar内),您可以使用一个application.properties文件,该文件为提供合理的默认属性值name。在新环境中运行时,application.properties可以在jar外部提供一个文件,该文件将覆盖name。对于一次性测试,您可以使用特定的命令行开关(例如,java -jar app.jar --name="Spring")启动。

envconfigprops端点可以在确定为什么属性具有特定值有用。您可以使用这两个端点来诊断意外的属性值。有关详细信息,请参见“生产就绪功能”部分。

2.1 访问命令行属性

默认情况下,SpringApplication将任何命令行选项参数(即以开头的参数--,例如--server.port=9000)转换为aproperty并将其添加到Spring Environment。如前所述,命令行属性始终优先于基于文件的属性源。
如果不希望将命令行属性添加到中Environment,则可以使用禁用它们SpringApplication.setAddCommandLineProperties(false)

2.2 JSON应用程序属性

环境变量和系统属性通常具有一些限制,这意味着无法使用某些属性名称。为了解决这个问题,Spring Boot允许您将属性块编码为单个JSON结构。
当您的应用程序启动时,任何spring.application.jsonSPRING_APPLICATION_JSON属性都会被解析并添加到中Environment
例如,SPRING_APPLICATION_JSON可以在命令行中将UN * X shell中的属性作为环境变量提供:
$ SPRING_APPLICATION_JSON =’{“ acme”:{“ name”:“ test”}}}’java -jar myapp.jar
在前面的示例中,您最终acme.name=test在Spring中Environment
相同的JSON也可以作为系统属性提供:
$ java -Dspring.application.json =’{“ acme”:{“ name”:“ test”}}}’-jar myapp.jar
或者,您可以使用命令行参数来提供JSON:
$ java -jar myapp.jar —spring.application.json =’{“ acme”:{“ name”:“ test”}}}’
如果要部署到经典的Application Server,则还可以使用名为的JNDI变量java:comp/env/spring.application.json

尽管null来自JSON的值将添加到生成的属性源中,但是PropertySourcesPropertyResolvernull属性视为缺失值。这意味着JSON无法使用null值覆盖低阶属性源中的属性。

2.3 外部应用程序属性

春天开机就会自动查找和加载application.propertiesapplication.yaml应用程序启动时的文件从以下位置:

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

该列表按优先级排序(较低项的值覆盖较早项的值)。来自已加载文件的文档将添加PropertySources到Spring中Environment
如果您不喜欢application配置文件名,则可以通过指定spring.config.name环境属性来切换到另一个文件名。您还可以通过使用spring.config.locationenvironment属性(目录位置或文件路径的逗号分隔列表)来引用显式位置。以下示例显示如何指定其他文件名:
$ java -jar myproject.jar —spring.config.name = myproject
下面的示例演示如何指定两个位置:
$ java -jar myproject.jar —spring.config.location =可选:classpath:/default.properties,可选:classpath:/override.properties

optional:如果位置是可选的,则 使用前缀,并且您不介意它们是否不存在。
spring.config.name并且spring.config.location很早就用于确定必须加载哪些文件。必须将它们定义为环境属性(通常是OS环境变量,系统属性或命令行参数)。

如果spring.config.location包含目录(而不是文件),则应以目录结尾/(在运行时,将在目录后附加从生成spring.config.name之前生成的名称)。指定的文件spring.config.location按原样使用。无论是直接指定还是包含在目录中,配置文件都必须在名称中包含文件扩展名。所支持外的开箱典型的扩展是.properties.yaml.yml
如果指定了多个位置,则后面的位置可以覆盖前面的位置。
通过使用配置的位置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:/
  2. optional:classpath:/config/
  3. optional:file:./
  4. optional:file:./config/
  5. optional:file:./config/*/
  6. optional:classpath:custom-config/
  7. optional:file:./custom-config/

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

如果您使用环境变量而不是系统属性,则大多数操作系统都不允许使用句点分隔的键名,但是您可以使用下划线代替(例如,SPRING_CONFIG_NAME代替spring.config.name)。有关详细信息,请参见从环境变量绑定
如果您的应用程序在servlet容器或应用程序服务器中运行,则可以使用JNDI属性(中的java:comp/env)或servlet上下文初始化参数来代替环境变量或系统属性,也可以使用它们。

2.3.1 可选位置

默认情况下,当指定的配置数据位置不存在时,Spring Boot将抛出,ConfigDataLocationNotFoundException并且您的应用程序将不会启动。
如果要指定位置,但不介意它并不总是存在,则可以使用optional:前缀。您可以将此前缀与spring.config.locationspring.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.locationspring.config.additional-location属性使用通配符位置。

通配符位置必须仅包含一个,*并且以*/目录*/<filename>的搜索位置或文件的搜索位置结尾。带通配符的位置根据文件名的绝对路径按字母顺序排序。
通配符位置仅适用于外部目录。您不能在某个classpath:位置使用通配符。

2.3.3 配置文件专用文件

除了application属性文件,Spring Boot还将尝试使用命名约定来加载特定于配置文件的文件application-{profile}。例如,如果你的应用程序启动了一个名为轮廓prod,并使用YAML文件,然后双方application.ymlapplication-prod.yml会予以考虑。
特定于配置文件的属性从与standard相同的位置加载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文件中可能包含以下内容:
特性
Yaml

  1. spring:
  2. application:
  3. name: "myapp"
  4. config:
  5. import: "optional:file:./dev.properties"

这将触发dev.properties当前目录中文件的导入(如果存在这样的文件)。来自导入的值dev.properties将优先于触发导入的文件。在上面的示例中,dev.properties可以重新定义spring.application.name为其他值。不论声明多少次,导入都只会导入一次。在properties / yaml文件中的单个文档中定义导入的顺序无关紧要。例如,以下两个示例产生相同的结果:
特性
Yaml

  1. spring:
  2. config:
  3. import: my.properties
  4. my:
  5. property: value

特性
Yaml

  1. my:
  2. property: value
  3. spring:
  4. config:
  5. import: my.properties

在以上两个示例中,my.properties文件中的值将优先于触发其导入的文件。
可以在一个spring.config.import键下指定多个位置。位置将按照定义的顺序进行处理,以后的导入将优先。

Spring Boot包含可插入的API,该API允许支持各种不同的位置地址。默认情况下,您可以导入Java属性,YAML和“配置树”。
第三方jar可以为其他技术提供支持(不需要文件位于本地)。例如,您可以想象配置数据来自外部存储,例如Consul,Apache ZooKeeper或Netflix Archaius。
如果要支持自己的位置,请参阅软件包中的ConfigDataLocationResolverConfigDataLoaderorg.springframework.boot.context.config

2.3.5 导入无扩展名文件

某些云平台无法将文件扩展名添加到已装入卷的文件中。要导入这些无扩展名的文件,您需要给Spring Boot一个提示,以便它知道如何加载它们。您可以通过在方括号中添加扩展提示来做到这一点。
例如,假设您有一个/etc/config/myconfig要导入为yaml的文件。您可以application.properties使用以下方法从中导入它:
特性
Yaml

  1. spring:
  2. config:
  3. import: "file:/etc/config/myconfig[.yaml]"

2.3.6 使用配置树

在云平台上运行应用程序(例如Kubernetes)时,您通常需要读取平台提供的配置值。为此目的使用环境变量并不罕见,但是这样做可能会有弊端,特别是如果该值应该保密的话。
作为环境变量的替代方法,许多云平台现在允许您将配置映射到装入的数据卷中。例如,Kubernetes可以批量挂载ConfigMapsSecrets
可以使用两种常见的卷安装模式:

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

对于第一种情况,你可以直接导入使用YAML或属性文件中spring.config.import所描述的以上。对于第二种情况,您需要使用configtree:前缀,以便Spring Boot知道它需要将所有文件公开为属性。
作为示例,让我们想象一下Kubernetes已经安装了以下卷:

  1. etc/
  2. config/
  3. myapp/
  4. username
  5. password

username文件的内容将是一个配置值,而其中的内容password将是一个秘密。
要导入这些属性,可以将以下内容添加到您的application.propertiesapplication.yaml文件中:
特性
Yaml

  1. spring:
  2. config:
  3. import: "optional:configtree:/etc/config/"

然后,您可以按照通常的方式从中访问或注入myapp.usernamemyapp.password属性Environment

根据期望的内容, 配置树值可以绑定到字符串Stringbyte[]类型。

如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。任何configtree:以结尾结尾的位置/*/都将所有直接子级导入为配置树。
例如,给定以下卷:

  1. etc/
  2. config/
  3. dbconfig/
  4. db/
  5. username
  6. password
  7. mqconfig/
  8. mq/
  9. username
  10. password

您可以configtree:/etc/config/*/用作导入位置:
特性
Yaml

  1. spring:
  2. config:
  3. import: "optional:configtree:/etc/config/*/"

这将增加db.usernamedb.passwordmq.usernamemq.password属性。

使用通配符加载的目录按字母顺序排序。如果需要其他订单,则应将每个位置列为单独的导入

2.3.7 财产占位符

使用中的application.properties和时,它们中的值application.yml会通过现有的值进行过滤Environment,因此您可以参考以前定义的值(例如,从“系统”属性中)。标准的${name}property-placeholder语法可以在值中的任何位置使用。
例如,以下文件将设置app.description为“ MyApp是Spring Boot应用程序”:
特性
Yaml

  1. app:
  2. name: "MyApp"
  3. description: "${app.name} is a Spring Boot application"
您还可以使用此技术来创建现有Spring Boot属性的“简短”变体。有关详细信息,请参见howto.html操作方法。

2.3.8 处理多文档文件

Spring Boot允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档都独立添加。从上到下按顺序处理文档。以后的文档可以覆盖以前的文档中定义的属性。
对于application.yml文件,使用标准的YAML多文档语法。三个连续的连字符代表一个文档的末尾,以及下一个文档的开始。
例如,以下文件具有两个逻辑文档:

  1. spring.application.name: MyApp
  2. ---
  3. spring.config.activate.on-cloud-platform: kubernetes
  4. spring.application.name: MyCloudApp

对于application.properties文件,特殊#---注释用于标记文档拆分:

  1. spring.application.name=MyApp
  2. #---
  3. spring.config.activate.on-cloud-platform=kubernetes
  4. spring.application.name=MyCloudApp
属性文件分隔符不得包含任何前导空格,并且必须恰好具有三个连字符。分隔符之前和之后的行不得为注释。
多文档属性文件通常与激活属性(例如)结合使用spring.config.activate.on-profile。有关详细信息,请参见下一部分

2.3.9 激活属性

有时仅在满足某些条件时才激活给定的属性获取,这很有用。例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用来有条件地激活属性文档spring.config.activate.*
可以使用以下激活属性:
表2.激活属性

财产 笔记
on-profile 必须匹配才能使文档处于活动状态的配置文件表达式。
on-cloud-platform CloudPlatform必须对文件进行检测活跃。

例如,以下内容指定仅当在Kubernetes上运行时并且仅当“ prod”或“ staging”配置文件处于活动状态时,第二个文档才处于活动状态:
特性
Yaml

  1. myprop:
  2. always-set
  3. ---
  4. spring:
  5. config:
  6. activate:
  7. on-cloud-platform: "kubernetes"
  8. on-profile: "prod | staging"
  9. myotherprop: sometimes-set

2.4。加密属性

Spring Boot不提供对加密属性值的任何内置支持,但是,它确实提供了修改Spring包含的值所必需的挂钩点Environment。该EnvironmentPostProcessor界面允许您Environment在应用程序启动之前进行操作。有关详细信息,请参见howto.html
如果您正在寻找一种安全的方式来存储凭据和密码,则Spring Cloud Vault项目提供了对在HashiCorp Vault中存储外部化配置的支持。

2.5 使用YAML

YAML是JSON的超集,因此是一种用于指定层次结构配置数据的便捷格式。该SpringApplication级自动支持YAML来替代,只要你有属性SnakeYAML在classpath库。

如果您使用“入门”,则SnakeYAML将由自动提供spring-boot-starter

2.5.1 将YAML映射到属性

YAML文档需要从其层次结构格式转换为可以与Spring一起使用的平面结构Environment。例如,考虑以下YAML文档:

  1. environments:
  2. dev:
  3. url: https://dev.example.com
  4. name: Developer Setup
  5. prod:
  6. url: https://another.example.com
  7. name: My Cool App

为了从中访问这些属性Environment,它们将按如下所示进行展平:

  1. environments.dev.url=https://dev.example.com
  2. environments.dev.name=Developer Setup
  3. environments.prod.url=https://another.example.com
  4. environments.prod.name=My Cool App

同样,YAML列表也需要进行展平。它们表示为带有[index]取消引用程序的属性键。例如,考虑以下YAML:

  1. my:
  2. servers:
  3. - dev.example.com
  4. - another.example.com

前面的示例将转换为以下属性:

  1. my.servers[0]=dev.example.com
  2. my.servers[1]=another.example.com
[index]可以使用Spring Boot的类 将使用该符号的属性绑定到JavaListSet对象Binder。有关更多详细信息,请参见下面的“类型安全配置属性”部分。
无法使用@PropertySource@TestPropertySource注释加载YAML文件。因此,在需要以这种方式加载值的情况下,需要使用属性文件。

2.5.2 直接加载YAML

Spring Framework提供了两个方便的类,可用于加载YAML文档。该YamlPropertiesFactoryBean负载YAML作为PropertiesYamlMapFactoryBean负载YAML作为Map
YamlPropertySourceLoader如果要将YAML作为Spring加载,也可以使用该类PropertySource

2.6 配置随机值

RandomValuePropertySource是用于注射的随机值(例如,进入机密或试验例)是有用的。它可以产生整数,longs,uuid或字符串,如以下示例所示:
特性
Yaml

  1. my:
  2. secret: "${random.value}"
  3. number: "${random.int}"
  4. bignumber: "${random.long}"
  5. uuid: "${random.uuid}"
  6. number-less-than-ten: "${random.int(10)}"
  7. number-in-range: "${random.int[1024,65536]}"

random.int*语法是OPEN value (,max) CLOSE其中的OPEN,CLOSE任何字符和value,max是整数。如果max提供,value则为最小值,max为最大值(不包括)。

2.7 类型安全的配置属性

使用@Value("${property}")注释注入配置属性有时会很麻烦,尤其是当您使用多个属性或数据本质上是分层的时。Spring Boot提供了一种使用属性的替代方法,该方法使强类型的Bean可以管理和验证应用程序的配置。

另请参见和类型安全配置属性之间@Value区别

2.7.1 JavaBean属性绑定

可以绑定一个声明标准JavaBean属性的bean,如以下示例所示:

  1. package com.example;
  2. import java.net.InetAddress;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.List;
  6. import org.springframework.boot.context.properties.ConfigurationProperties;
  7. @ConfigurationProperties("acme")
  8. public class AcmeProperties {
  9. private boolean enabled;
  10. private InetAddress remoteAddress;
  11. private final Security security = new Security();
  12. public boolean isEnabled() { ... }
  13. public void setEnabled(boolean enabled) { ... }
  14. public InetAddress getRemoteAddress() { ... }
  15. public void setRemoteAddress(InetAddress remoteAddress) { ... }
  16. public Security getSecurity() { ... }
  17. public static class Security {
  18. private String username;
  19. private String password;
  20. private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
  21. public String getUsername() { ... }
  22. public void setUsername(String username) { ... }
  23. public String getPassword() { ... }
  24. public void setPassword(String password) { ... }
  25. public List<String> getRoles() { ... }
  26. public void setRoles(List<String> roles) { ... }
  27. }
  28. }

前面的POJO定义了以下属性:

  • acme.enabledfalse默认值为。
  • acme.remote-address,其类型可以从强制转换String
  • acme.security.username,带有嵌套的“安全”对象,其名称由属性的名称确定。特别是,返回类型根本不使用,可能已经使用过SecurityProperties
  • acme.security.password
  • acme.security.roles,其中的一个集合String默认为USER
    | | 映射到@ConfigurationPropertiesSpring Boot中可用类的属性是公共API,这些属性是通过属性文件,YAML文件,环境变量等配置的,但是类本身的访问器(获取器/设置器)不能直接使用。 | | :—-: | —- |

| | 这种安排依赖于默认的空构造函数,并且getter和setter通常是强制性的,因为绑定是通过标准Java Beans属性描述符进行的,就像在Spring MVC中一样。在以下情况下,可以忽略二传手:
- 只要将地图初始化,它们就需要使用吸气剂,但不一定需要使用setter,因为它们可以被活页夹改变。

  • 可以通过索引(通常使用YAML)或使用单个逗号分隔的值(属性)来访问集合和数组。在后一种情况下,必须使用二传手。我们建议始终为此类类型添加设置器。如果初始化集合,请确保它不是不可变的(如上例所示)。

  • 如果嵌套的POJO属性已初始化(如Security前面示例中的字段),则不需要setter。如果希望活页夹通过使用其默认构造函数动态创建实例,则需要一个setter。

有些人使用Lombok项目自动添加获取器和设置器。确保Lombok不会为这种类型生成任何特定的构造函数,因为容器会自动使用它来实例化该对象。
最后,仅考虑标准Java Bean属性,不支持对静态属性的绑定。 | | :—-: | —- |

2.7.2 构造函数绑定

上一节中的示例可以以不变的方式重写,如下例所示:

  1. package com.example;
  2. import java.net.InetAddress;
  3. import java.util.List;
  4. import org.springframework.boot.context.properties.ConfigurationProperties;
  5. import org.springframework.boot.context.properties.ConstructorBinding;
  6. import org.springframework.boot.context.properties.bind.DefaultValue;
  7. @ConstructorBinding
  8. @ConfigurationProperties("acme")
  9. public class AcmeProperties {
  10. private final boolean enabled;
  11. private final InetAddress remoteAddress;
  12. private final Security security;
  13. public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {
  14. this.enabled = enabled;
  15. this.remoteAddress = remoteAddress;
  16. this.security = security;
  17. }
  18. public boolean isEnabled() { ... }
  19. public InetAddress getRemoteAddress() { ... }
  20. public Security getSecurity() { ... }
  21. public static class Security {
  22. private final String username;
  23. private final String password;
  24. private final List<String> roles;
  25. public Security(String username, String password,
  26. @DefaultValue("USER") List<String> roles) {
  27. this.username = username;
  28. this.password = password;
  29. this.roles = roles;
  30. }
  31. public String getUsername() { ... }
  32. public String getPassword() { ... }
  33. public List<String> getRoles() { ... }
  34. }
  35. }

在此设置中,@ConstructorBinding注释用于指示应使用构造函数绑定。这意味着绑定器将期望找到带有您希望绑定的参数的构造函数。
类的嵌套成员@ConstructorBinding(例如Security上例)也将通过其构造函数进行绑定。
可以使用指定默认值,@DefaultValue并且将应用相同的转换服务将String值强制为缺少属性的目标类型。默认情况下,如果未绑定任何属性Security,则AcmeProperties实例将包含的nullsecurity。如果您希望Security即使没有属性绑定也返回一个非null的实例,则可以使用一个空的@DefaultValue注释来这样做:

  1. package com.example;
  2. import java.net.InetAddress;
  3. import java.util.List;
  4. import org.springframework.boot.context.properties.ConfigurationProperties;
  5. import org.springframework.boot.context.properties.ConstructorBinding;
  6. import org.springframework.boot.context.properties.bind.DefaultValue;
  7. @ConstructorBinding
  8. @ConfigurationProperties("acme")
  9. public class AcmeProperties {
  10. private final boolean enabled;
  11. private final InetAddress remoteAddress;
  12. private final Security security;
  13. public AcmeProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
  14. this.enabled = enabled;
  15. this.remoteAddress = remoteAddress;
  16. this.security = security;
  17. }
  18. }
要使用构造函数绑定,必须使用@EnableConfigurationProperties或配置属性扫描来启用该类。您不能对通过常规Spring机制创建的bean使用构造函数绑定(例如,@Componentbean,通过@Bean方法创建的bean或使用加载的bean @Import
如果您的类具有多个构造函数,则还可以@ConstructorBinding直接在应绑定的构造函数上使用。
不建议 使用java.util.Optionalwith,@ConfigurationProperties因为with主要用于返回类型。因此,它不太适合配置属性注入。为了与其他类型的属性保持一致,如果确实声明了一个Optional属性且该属性没有值,则将绑定null一个空值Optional

2.7.3 启用@ConfigurationProperties注释的类型

Spring Boot提供了绑定@ConfigurationProperties类型并将其注册为Bean的基础架构。您可以逐类启用配置属性,也可以启用与组件扫描类似的方式进行配置属性扫描。
有时,带注释的类@ConfigurationProperties可能不适合扫描,例如,如果您正在开发自己的自动配置,或者想要有条件地启用它们。在这些情况下,请使用@EnableConfigurationProperties注释指定要处理的类型列表。可以在任何@Configuration类上完成此操作,如以下示例所示:

  1. @Configuration(proxyBeanMethods = false)
  2. @EnableConfigurationProperties(AcmeProperties.class)
  3. public class MyConfiguration {
  4. }

要使用配置属性扫描,请将@ConfigurationPropertiesScan注释添加到您的应用程序。通常,它将添加到带有注释的主应用程序类中,@SpringBootApplication但可以将其添加到任何@Configuration类中。默认情况下,将从声明注释的类的包中进行扫描。如果要定义要扫描的特定程序包,可以按照以下示例所示进行操作:

  1. @SpringBootApplication
  2. @ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
  3. public class MyApplication {
  4. }
@ConfigurationPropertiesbean使用配置属性扫描或通过注册@EnableConfigurationProperties,豆具有常规名称:<prefix>-<fqn>,其中,<prefix>是在指定的环境键前缀@ConfigurationProperties注释和<fqn>是bean的全限定名。如果注释不提供任何前缀,则仅使用Bean的完全限定名称。
上例中的Bean名称为acme-com.example.AcmeProperties

我们建议@ConfigurationProperties仅处理环境,尤其不要从上下文中注入其他bean。对于极端情况,可以使用setter注入或*Aware框架提供的任何接口(例如,EnvironmentAware如果需要访问Environment)。如果仍然要使用构造函数注入其他bean,则必须使用注释配置属性bean@Component并使用基于JavaBean的属性绑定。

2.7.4 使用@ConfigurationProperties注释的类型

这种配置样式特别适用于SpringApplication外部YAML配置,如以下示例所示:

  1. acme:
  2. remote-address: 192.168.1.1
  3. security:
  4. username: admin
  5. roles:
  6. - USER
  7. - ADMIN

要使用@ConfigurationPropertiesbean,可以像使用其他任何bean一样注入它们,如以下示例所示:

  1. @Service
  2. public class MyService {
  3. private final AcmeProperties properties;
  4. @Autowired
  5. public MyService(AcmeProperties properties) {
  6. this.properties = properties;
  7. }
  8. //...
  9. @PostConstruct
  10. public void openConnection() {
  11. Server server = new Server(this.properties.getRemoteAddress());
  12. // ...
  13. }
  14. }
使用@ConfigurationProperties还可以让您生成元数据文件,IDE可以使用这些元数据文件为您自己的键提供自动补全功能。有关详细信息,请参见附录

2.7.5 第三方配置

除了@ConfigurationProperties用于注释类之外,您还可以在公共@Bean方法上使用它。当您要将属性绑定到控件之外的第三方组件时,这样做特别有用。
要从Environment属性中配置bean ,请添加@ConfigurationProperties到其bean注册中,如以下示例所示:

  1. @ConfigurationProperties(prefix = "another")
  2. @Bean
  3. public AnotherComponent anotherComponent() {
  4. ...
  5. }

another前缀定义的任何JavaBean属性都AnotherComponent以类似于前面AcmeProperties示例的方式映射到该bean 。

2.7.6 轻松绑定

Spring Boot使用一些宽松的规则将Environment属性绑定到@ConfigurationPropertiesBean,因此Environment属性名称和Bean属性名称之间不需要完全匹配。有用的常见示例包括破折号分隔的环境属性(例如,context-path绑定到contextPath)和大写的环境属性(例如,PORT绑定到port)。
例如,考虑以下@ConfigurationProperties类:

  1. @ConfigurationProperties(prefix="acme.my-project.person")
  2. public class OwnerProperties {
  3. private String firstName;
  4. public String getFirstName() {
  5. return this.firstName;
  6. }
  7. public void setFirstName(String firstName) {
  8. this.firstName = firstName;
  9. }
  10. }

通过前面的代码,可以一起使用以下属性名称:
表3.宽松的绑定

财产 笔记
acme.my-project.person.first-name 烤肉串盒,建议在.properties.yml文件中使用。
acme.myProject.person.firstName 标准驼峰式语法。
acme.my_project.person.first_name 下划线表示法,是在.properties.yml文件中使用的另一种格式。
ACME_MYPROJECT_PERSON_FIRSTNAME 大写格式,使用系统环境变量时建议使用。
prefix注释 的值必须为kebab大小写(小写并用分隔-,例如acme.my-project.person)。

表4.每个属性源的宽松绑定规则

财产来源 简单的 列表
属性文件 骆驼案,烤肉串案或下划线 使用[ ]或逗号分隔值的标准列表语法
YAML文件 骆驼案,烤肉串案或下划线 标准YAML列表语法或逗号分隔的值
环境变量 以下划线作为定界符的大写格式(请参阅从环境变量绑定)。 下划线括起来的数字值(请参阅环境变量的绑定
系统属性 骆驼案,烤肉串案或下划线 使用[ ]或逗号分隔值的标准列表语法
我们建议,如果可能的话,属性以小写的kebab格式存储,例如my.property-name=acme

绑定图

绑定到Map属性时,可能需要使用特殊的括号符号,以便key保留原始值。如果键没有被包围[],则所有非字母数字-.已删除的字符。
例如,考虑将以下属性绑定到Map<String,String>
特性
Yaml

  1. acme:
  2. map:
  3. "[/key1]": "value1"
  4. "[/key2]": "value2"
  5. "/key3": "value3"
对于YAML文件,方括号需要用引号引起来,以便正确解析密钥。

上面的性质将结合一个Map具有/key1/key2key3作为映射中的键。由于斜杠key3没有被方括号包围,因此已将其删除。
如果您key包含.且绑定到非标量值,则有时可能还需要使用括号符号。例如,绑定a.b=cMap<String, Object>将返回带有条目的Map,{"a"={"b"="c"}}[a.b]=c将返回带有条目的Map {"a.b"="c"}

从环境变量绑定

大多数操作系统在可用于环境变量的名称周围施加严格的规则。例如,Linux shell变量只能包含字母(atozAto Z),数字(0to 9)或下划线字符(_)。按照约定,Unix shell变量也将以大写字母命名。
Spring Boot的宽松绑定规则尽可能设计成与这些命名限制兼容。
要将规范形式的属性名称转换为环境变量名称,可以遵循以下规则:

  • .用下划线(_)代替点()。
  • 删除所有破折号(-)。
  • 转换为大写。

例如,配置属性spring.main.log-startup-info将是名为的环境变量SPRING_MAIN_LOGSTARTUPINFO
绑定到对象列表时也可以使用环境变量。要绑定到List,元素编号应在变量名称中用下划线括起来。
例如,配置属性my.acme[0].other将使用名为的环境变量MY_ACME_0_OTHER

2.7.7 合并复杂类型

如果在多个位置配置了列表,则通过替换整个列表来进行覆盖。
例如,假定默认情况下MyPojo具有namedescription属性的对象null。以下示例公开了MyPojo来自的对象列表AcmeProperties

  1. @ConfigurationProperties("acme")
  2. public class AcmeProperties {
  3. private final List<MyPojo> list = new ArrayList<>();
  4. public List<MyPojo> getList() {
  5. return this.list;
  6. }
  7. }

考虑以下配置:
特性
Yaml

  1. acme:
  2. list:
  3. - name: "my name"
  4. description: "my description"
  5. ---
  6. spring:
  7. config:
  8. activate:
  9. on-profile: "dev"
  10. acme:
  11. list:
  12. - name: "my another name"

如果dev配置文件未激活,则AcmeProperties.list包含一个MyPojo条目,如先前所定义。dev但是,如果启用了配置文件,则list 仍然仅包含一个条目(名称为my another name,说明为null)。此配置不会将第二个MyPojo实例添加到列表中,并且不会合并项目。
List在多个配置文件中指定a时,将使用优先级最高的一个(并且只有该优先级)。考虑以下示例:
特性
Yaml

  1. acme:
  2. list:
  3. - name: "my name"
  4. description: "my description"
  5. - name: "another name"
  6. description: "another description"
  7. ---
  8. spring:
  9. config:
  10. activate:
  11. on-profile: "dev"
  12. acme:
  13. list:
  14. - name: "my another name"

在前面的示例中,如果dev配置文件处于活动状态,则AcmeProperties.list包含一个 MyPojo条目(名称为my another name,说明为null)。对于YAML,可以使用逗号分隔的列表和YAML列表来完全覆盖列表的内容。
对于Map属性,可以绑定从多个来源绘制的属性值。但是,对于多个源中的同一属性,将使用优先级最高的属性。以下示例公开了Map<String, MyPojo>from AcmeProperties

  1. @ConfigurationProperties("acme")
  2. public class AcmeProperties {
  3. private final Map<String, MyPojo> map = new HashMap<>();
  4. public Map<String, MyPojo> getMap() {
  5. return this.map;
  6. }
  7. }

考虑以下配置:
特性
Yaml

  1. acme:
  2. map:
  3. key1:
  4. name: "my name 1"
  5. description: "my description 1"
  6. ---
  7. spring:
  8. config:
  9. activate:
  10. on-profile: "dev"
  11. acme:
  12. map:
  13. key1:
  14. name: "dev name 1"
  15. key2:
  16. name: "dev name 2"
  17. description: "dev description 2"

如果dev配置文件未处于活动状态,则AcmeProperties.map包含一个带有键的条目key1(名称为my name 1,说明为my description 1)。dev但是,如果启用了配置文件,则map包含两个带有键的项key1(名称为dev name 1和的描述为my description 1key2,名称为dev name 2和的描述为dev description 2)。

前述合并规则不仅适用于文件,还适用于所有属性源中的属性。

2.7.8 属性转换

当Spring Boot绑定到@ConfigurationPropertiesbean时,它试图将外部应用程序属性强制为正确的类型。如果您需要自定义类型转换,则可以提供一个ConversionServiceBean(具有一个名为的Bean conversionService)或一个定制属性编辑器(通过一个CustomEditorConfigurerBean)或定制Converters(具有定义为的Bean @ConfigurationPropertiesBinding)。

由于在应用程序生命周期中非常早就请求了此bean,因此请确保限制您ConversionService正在使用的依赖项。通常,您需要的任何依赖项可能在创建时未完全初始化。ConversionService如果配置键强制不需要自定义,则您可能要重命名自定义,而仅依赖具有限定符的自定义转换器@ConfigurationPropertiesBinding

转换时间

Spring Boot为表达持续时间提供了专门的支持。如果公开java.time.Duration属性,则应用程序属性中的以下格式可用:

  • 常规long表示形式(使用毫秒作为默认单位,除非@DurationUnit已指定a)
  • 标准的ISO-8601格式使用java.time.Duration
  • 值和单位耦合的更易读的格式(例如,10s表示10秒)

考虑以下示例:

  1. @ConfigurationProperties("app.system")
  2. public class AppSystemProperties {
  3. @DurationUnit(ChronoUnit.SECONDS)
  4. private Duration sessionTimeout = Duration.ofSeconds(30);
  5. private Duration readTimeout = Duration.ofMillis(1000);
  6. public Duration getSessionTimeout() {
  7. return this.sessionTimeout;
  8. }
  9. public void setSessionTimeout(Duration sessionTimeout) {
  10. this.sessionTimeout = sessionTimeout;
  11. }
  12. public Duration getReadTimeout() {
  13. return this.readTimeout;
  14. }
  15. public void setReadTimeout(Duration readTimeout) {
  16. this.readTimeout = readTimeout;
  17. }
  18. }

要指定30秒的会话超时30PT30S30s都等效。500毫秒的读取超时可以以任何形式如下指定:500PT0.5S500ms
您也可以使用任何受支持的单位。这些是:

  • ns 十亿分之一秒
  • us 微秒
  • ms 毫秒
  • s 几秒钟
  • m 几分钟
  • h 用了几个小时
  • d 好几天

默认单位是毫秒,可以使用@DurationUnit上面的示例中所示的方法进行覆盖。
如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:

  1. @ConfigurationProperties("app.system")
  2. @ConstructorBinding
  3. public class AppSystemProperties {
  4. private final Duration sessionTimeout;
  5. private final Duration readTimeout;
  6. public AppSystemProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
  7. @DefaultValue("1000ms") Duration readTimeout) {
  8. this.sessionTimeout = sessionTimeout;
  9. this.readTimeout = readTimeout;
  10. }
  11. public Duration getSessionTimeout() {
  12. return this.sessionTimeout;
  13. }
  14. public Duration getReadTimeout() {
  15. return this.readTimeout;
  16. }
  17. }
如果要升级Long属性,请确保以@DurationUnit毫秒为单位定义单位(使用)。这样做可以提供透明的升级路径,同时支持更丰富的格式。

转换期

除了持续时间,Spring Boot还可以使用java.time.Periodtype。可以在应用程序属性中使用以下格式:

  • 常规int表示形式(除非@PeriodUnit指定,否则使用天作为默认单位)
  • 标准的ISO-8601格式使用java.time.Period
  • 值和单位对耦合的更简单格式(例如,1y3d表示1年零3天)

简单格式支持以下单位:

  • y 多年
  • m 几个月
  • w 数周
  • d 好几天
    | | 该java.time.Period类型从不实际存储星期数,这是一个快捷方式,表示“ 7天”。 | | :—-: | —- |

转换数据大小

Spring Framework的DataSize值类型表示字节大小。如果公开DataSize属性,则应用程序属性中的以下格式可用:

  • 常规long表示形式(除非@DataSizeUnit已指定,否则使用字节作为默认单位)
  • 值和单位耦合的更具可读性的格式(例如,10MB意味着10兆字节)

考虑以下示例:

  1. @ConfigurationProperties("app.io")
  2. public class AppIoProperties {
  3. @DataSizeUnit(DataUnit.MEGABYTES)
  4. private DataSize bufferSize = DataSize.ofMegabytes(2);
  5. private DataSize sizeThreshold = DataSize.ofBytes(512);
  6. public DataSize getBufferSize() {
  7. return this.bufferSize;
  8. }
  9. public void setBufferSize(DataSize bufferSize) {
  10. this.bufferSize = bufferSize;
  11. }
  12. public DataSize getSizeThreshold() {
  13. return this.sizeThreshold;
  14. }
  15. public void setSizeThreshold(DataSize sizeThreshold) {
  16. this.sizeThreshold = sizeThreshold;
  17. }
  18. }

指定10 MB的缓冲区大小,10并且10MB等效。可以将256个字节的大小阈值指定为256256B
您也可以使用任何受支持的单位。这些是:

  • B 对于字节
  • KB 千字节
  • MB 兆字节
  • GB 千兆字节
  • TB 太字节

默认单位是字节,可以使用@DataSizeUnit上面的示例中所示的方法覆盖它。
如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:

  1. @ConfigurationProperties("app.io")
  2. @ConstructorBinding
  3. public class AppIoProperties {
  4. private final DataSize bufferSize;
  5. private final DataSize sizeThreshold;
  6. public AppIoProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
  7. @DefaultValue("512B") DataSize sizeThreshold) {
  8. this.bufferSize = bufferSize;
  9. this.sizeThreshold = sizeThreshold;
  10. }
  11. public DataSize getBufferSize() {
  12. return this.bufferSize;
  13. }
  14. public DataSize getSizeThreshold() {
  15. return this.sizeThreshold;
  16. }
  17. }
如果要升级Long属性,请确保定义单位(@DataSizeUnit如果不是字节)(使用)。这样做可以提供透明的升级路径,同时支持更丰富的格式。

2.7.9 @ConfigurationProperties验证

@ConfigurationProperties每当使用Spring的@Validated注释对其进行注释时,Spring Boot就会尝试验证类。您可以javax.validation直接在配置类上使用JSR-303约束注释。为此,请确保在类路径上有兼容的JSR-303实现,然后将约束注释添加到字段中,如以下示例所示:

  1. @ConfigurationProperties(prefix="acme")
  2. @Validated
  3. public class AcmeProperties {
  4. @NotNull
  5. private InetAddress remoteAddress;
  6. // ... getters and setters
  7. }
您还可以通过使用注释@Bean创建配置属性的方法来触发验证@Validated

为了确保始终为嵌套属性触发验证,即使未找到任何属性,相关字段也必须使用注释@Valid。下面的示例基于前面的AcmeProperties示例:

  1. @ConfigurationProperties(prefix="acme")
  2. @Validated
  3. public class AcmeProperties {
  4. @NotNull
  5. private InetAddress remoteAddress;
  6. @Valid
  7. private final Security security = new Security();
  8. // ... getters and setters
  9. public static class Security {
  10. @NotEmpty
  11. public String username;
  12. // ... getters and setters
  13. }
  14. }

您还可以Validator通过创建名为的bean定义来添加自定义Spring configurationPropertiesValidator。该@Bean方法应声明static。配置属性验证器是在应用程序生命周期的早期创建的,并且将@Bean方法声明为static可以使Bean得以创建而不必实例化@Configuration该类。这样做避免了由早期实例化引起的任何问题。

spring-boot-actuator模块包括一个公开所有@ConfigurationPropertiesbean的端点。将您的Web浏览器指向/actuator/configprops或使用等效的JMX端点。有关详细信息,请参见“生产就绪功能”部分。

2.7.10 @ConfigurationProperties与@Value

@Value注释是核心容器的功能,和它不提供相同的功能,类型安全配置属性。下表总结了@ConfigurationProperties和支持的功能@Value

特征 @ConfigurationProperties @Value
宽松的绑定 是的 受限(请参阅下面的注释
元数据支持 是的
SpEL 评估 是的
如果您确实想使用@Value,我们建议您以规范形式引用属性名称(kebab-case仅使用小写字母)。这将使Spring Boot可以使用与放松绑定时相同的逻辑@ConfigurationProperties。例如,@Value("{demo.item-price}")将拿起demo.item-pricedemo.itemPrice从表格application.properties文件,以及DEMO_ITEMPRICE从系统环境。如果你使用的@Value("{demo.itemPrice}")不是,demo.item-priceDEMO_ITEMPRICE不会予以考虑。

如果您为自己的组件定义了一组配置键,我们建议您将它们组合在以标记的POJO中@ConfigurationProperties。这样做将为您提供结构化的,类型安全的对象,您可以将其注入到自己的bean中。
SpEL在解析这些文件并填充环境时,不会处理来自应用程序属性文件的表达式。但是,可以在中编写SpEL表达式@Value。如果应用程序属性文件中属性的值是一个SpEL表达式,则通过进行使用时将对其求值@Value

3.个人资料

Spring Profiles提供了一种隔离应用程序配置部分并使之仅在某些环境中可用的方法。任何@Component@Configuration@ConfigurationProperties可与被标记@Profile,当它被加载到限制,因为显示在下面的例子:

  1. @Configuration(proxyBeanMethods = false)
  2. @Profile("production")
  3. public class ProductionConfiguration {
  4. // ...
  5. }
如果@ConfigurationProperties通过@EnableConfigurationProperties而不是自动扫描来注册bean ,则@Profile需要在@Configuration具有@EnableConfigurationProperties注释的类上指定注释。在@ConfigurationProperties被扫描的情况下,@Profile可以在@ConfigurationProperties类本身上指定。

您可以使用spring.profiles.active Environment属性来指定哪些配置文件处于活动状态。您可以通过本章前面介绍的任何方式指定属性。例如,您可以将其包括在您的中application.properties,如以下示例所示:
特性
Yaml

  1. spring:
  2. profiles:
  3. active: "dev,hsqldb"

您还可以使用以下开关在命令行上指定它:--spring.profiles.active=dev,hsqldb

3.1 添加活动配置文件

spring.profiles.active属性与其他属性遵循相同的排序规则:最高PropertySource获胜。这意味着您可以在其中指定活动配置文件application.properties,然后使用命令行开关替换它们。
有时,将属性添加到活动配置文件而不是替换它们很有用。该SpringApplication入口点设置额外的配置文件的Java API(即,是对那些被激活的顶级spring.profiles.active属性)。参见SpringApplication中setAdditionalProfiles()方法。如果给定的配置文件处于活动状态,则下一部分中描述的配置文件组也可以用于添加活动的配置文件。

3.2 个人资料组

有时,您在应用程序中定义和使用的配置文件的粒度太细,使用起来很麻烦。例如,您可能具有proddbprodmq配置文件,用于分别启用数据库和消息传递功能。
为了解决这个问题,Spring Boot允许您定义配置文件组。使用配置文件组,您可以为相关的配置文件组定义逻辑名。
例如,我们可以创建一个productionproddbprodmq配置文件组成的组。
特性
Yaml

  1. spring:
  2. profiles:
  3. group:
  4. production:
  5. - "proddb"
  6. - "prodmq"

我们的应用程序现在可以使用开始--spring.profiles.active=production活跃了productionproddbprodmq一重击轮廓。

3.3 以编程方式设置配置文件

您可以SpringApplication.setAdditionalProfiles(…)在应用程序运行之前通过调用来以编程方式设置活动配置文件。也可以通过使用Spring的ConfigurableEnvironment界面来激活配置文件。

3.4 特定于配置文件的配置文件

application.properties(或application.yml)和通过引用引用的文件的特定于档案的特定变体@ConfigurationProperties都被视为文件并已加载。有关详细信息,请参见“配置文件专用文件”。

4.记录

Spring Boot使用Commons Logging进行所有内部日志记录,但是使底层日志实现保持打开状态。提供了Java Util LoggingLog4J2Logback的默认配置。在每种情况下,记录器都已预先配置为使用控制台输出,同时还提供可选文件输出。
默认情况下,如果使用“启动器”,则使用Logback进行日志记录。还包括适当的Logback路由,以确保使用Java Util Logging,Commons Logging,Log4J或SLF4J的从属库都可以正常工作。

Java有许多可用的日志记录框架。如果上面的列表看起来令人困惑,请不要担心。通常,您不需要更改日志记录依赖性,并且Spring Boot默认值可以正常工作。
当您将应用程序部署到servlet容器或应用程序服务器时,通过Java Util Logging API执行的日志记录不会路由到应用程序的日志中。这样可以防止由容器或已部署到容器中的其他应用程序执行的日志记录出现在应用程序的日志中。

4.1 日志格式

Spring Boot的默认日志输出类似于以下示例:
2019-03-05 10:57:51.112信息45469 —- [main] org.apache.catalina.core.StandardEngine:启动Servlet引擎:Apache Tomcat / 7.0.52
2019-03-05 10:57:51.253信息45469 —- [ost-startStop-1] oaccC [Tomcat]。[localhost]。[/]:初始化Spring嵌入式WebApplicationContext
2019-03-05 10:57:51.253信息45469-[ost-startStop-1] osweb.context.ContextLoader:根WebApplicationContext:初始化在1358毫秒内完成
2019-03-05 10:57:51.698信息45469-[ost-startStop-1] osbceServletRegistrationBean:映射servlet:’dispatcherServlet’到[/]
2019-03-05 10:57:51.702信息45469 —- [ost-startStop-1] osbcembedded.FilterRegistrationBean:映射过滤器:’hiddenHttpMethodFilter’到:[/ *]
输出以下项目:

  • 日期和时间:毫秒精度,易于排序。
  • 日志级别:ERRORWARNINFODEBUG,或TRACE
  • 进程ID。
  • 一个---分离器来区分实际日志消息的开始。
  • 线程名称:用方括号括起来(对于控制台输出可能会被截断)。
  • 记录器名称:这通常是源类名称(通常缩写)。
  • 日志消息。
    | | Logback没有FATAL级别。它映射到ERROR。 | | :—-: | —- |

4.2 控制台输出

缺省日志配置在写入消息时将消息回显到控制台。默认情况下,将记录ERROR-level,WARN-level和INFO-level消息。您还可以通过使用--debug标志启动应用程序来启用“调试”模式。
$ java -jar myapp.jar-调试

您也可以debug=true在中指定application.properties

启用调试模式后,将配置一些核心记录器(嵌入式容器,Hibernate和Spring Boot)以输出更多信息。启用调试模式并没有配置您的应用程序记录所有消息DEBUG的水平。
另外,您可以通过使用--trace标志(或trace=true在中application.properties)启动应用程序来启用“跟踪”模式。这样做可以为某些核心记录器(嵌入式容器,Hibernate模式生成以及整个Spring产品组合)启用跟踪记录。

4.2.1 颜色编码输出

如果您的终端支持ANSI,则使用彩色输出来提高可读性。您可以设置spring.output.ansi.enabled支持的值以覆盖自动检测。
通过使用%clr转换字来配置颜色编码。转换器以最简单的形式根据对数级别为输出着色,如以下示例所示:

  1. %clr(%5p)

下表描述了日志级别到颜色的映射:

等级 颜色
FATAL 红色的
ERROR 红色的
WARN 黄色的
INFO 绿色的
DEBUG 绿色的
TRACE 绿色的

或者,您可以通过将其提供为转换的选项来指定应使用的颜色或样式。例如,要使文本变黄,请使用以下设置:

  1. %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持以下颜色和样式:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

    4.3 文件输出

    默认情况下,Spring Boot仅记录到控制台,不写日志文件。如果除了控制台输出外还想写日志文件,则需要设置一个logging.file.namelogging.file.path属性(例如,在中application.properties)。
    下表显示了如何logging.*一起使用这些属性:
    表5.日志记录属性
logging.file.name logging.file.path 例子 描述
(没有) (没有) 仅控制台记录。
具体档案 (没有) my.log 写入指定的日志文件。名称可以是确切的位置,也可以相对于当前目录。
(没有) 具体目录 /var/log 写入spring.log指定的目录。名称可以是确切的位置,也可以相对于当前目录。

日志文件达到10 MB时会旋转,并且与控制台输出一样,默认情况下会记录ERROR-level,WARN-level和INFO-level消息。

日志记录属性与实际的日志记录基础结构无关。结果,logback.configurationFileSpring Boot不会管理特定的配置密钥(例如Logback)。

4.4 文件旋转

如果您使用的是Logback,则可以使用application.propertiesapplication.yaml文件微调日志轮播设置。对于所有其他日志记录系统,您需要直接自己配置轮转设置(例如,如果使用Log4J2,则可以添加log4j.xml文件)。
支持以下轮换策略属性:

姓名 描述
logging.logback.rollingpolicy.file-name-pattern 用于创建日志档案的文件名模式。
logging.logback.rollingpolicy.clean-history-on-start 如果应在应用程序启动时进行日志归档清理。
logging.logback.rollingpolicy.max-file-size 归档前日志文件的最大大小。
logging.logback.rollingpolicy.total-size-cap 删除日志档案之前可以使用的最大大小。
logging.logback.rollingpolicy.max-history 保留日志存档的天数(默认为7)

4.5 日志级别

通过在其中使用TRACE,DEBUG,INFO,WARN,ERROR,FATAL或OFF之一,可以在Spring中设置所有记录器级别Environment(例如,在中application.properties)。该记录器可以通过使用被配置。logging.level.<logger-name>=<level>``level``root``logging.level.root
以下示例显示了中的潜在日志记录设置application.properties
特性
Yaml

  1. logging:
  2. level:
  3. root: "warn"
  4. org.springframework.web: "debug"
  5. org.hibernate: "error"

也可以使用环境变量来设置日志记录级别。例如,LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG将设置org.springframework.webDEBUG

以上方法仅适用于程序包级别的日志记录。由于轻松绑定总是将环境变量转换为小写,因此无法以这种方式为单个类配置日志记录。如果需要为类配置日志记录,则可以使用SPRING_APPLICATION_JSON变量。

4.6 日志组

能够将相关记录器分组在一起通常很有用,以便可以同时配置它们。例如,您可能通常会更改所有与Tomcat相关的记录器的记录级别,但是您不容易记住顶层软件包。
为了解决这个问题,Spring Boot允许您在Spring中定义日志记录组Environment。例如,这是通过将“ tomcat”组添加到您的方式来定义它的方法application.properties
特性
Yaml

  1. logging:
  2. group:
  3. tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"

定义后,您可以使用一行更改该组中所有记录器的级别:
特性
Yaml

  1. logging:
  2. level:
  3. tomcat: "trace"

Spring Boot包含以下预定义的日志记录组,它们可以直接使用:

姓名 记录仪
网路 org.springframework.core.codecorg.springframework.httporg.springframework.weborg.springframework.boot.actuate.endpoint.weborg.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.coreorg.hibernate.SQLorg.jooq.tools.LoggerListener

4.7 使用日志关闭挂钩

为了释放日志记录资源,通常最好在应用程序终止时停止日志记录系统。不幸的是,没有一种方法可以适用于所有应用程序类型。如果您的应用程序具有复杂的上下文层次结构或作为war文件部署,则需要研究基础日志系统直接提供的选项。例如,Logback提供了上下文选择器,允许每个Logger在其自己的上下文中创建。
对于在自己的JVM中部署的简单“单罐”应用程序,可以使用该logging.register-shutdown-hook属性。设置logging.register-shutdown-hooktrue将会注册一个关闭挂钩,该挂钩将在JVM退出时触发日志系统清理。
您可以在application.propertiesapplication.yaml文件中设置属性:
特性
Yaml

  1. logging:
  2. register-shutdown-hook: true

4.8 自定义日志配置

可以通过在类路径中包含适当的库来激活各种日志记录系统,并可以通过在类路径的根目录或以下SpringEnvironment属性指定的位置中提供适当的配置文件来进一步自定义各种日志记录系统logging.config
您可以通过使用org.springframework.boot.logging.LoggingSystemsystem属性来强制Spring Boot使用特定的日志记录系统。该值应该是实现的完全限定的类名LoggingSystem。您还可以通过使用值完全禁用Spring Boot的日志记录配置none

由于日志记录是ApplicationContext创建之前初始化的,因此无法从@PropertySourcesSpring@Configuration文件中控制日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。

根据您的日志记录系统,将加载以下文件:

测井系统 客制化
退回 logback-spring.xmllogback-spring.groovylogback.xml,或者logback.groovy
Log4j2 log4j2-spring.xml 或者 log4j2.xml
JDK(Java实用程序日志记录) logging.properties
如果可能,我们建议您将-spring变体用于日志记录配置(例如,logback-spring.xml而不是logback.xml)。如果使用标准配置位置,Spring将无法完全控制日志初始化。
从“可执行jar”运行时,Java Util Logging存在一些已知的类加载问题,这些问题会引起问题。我们建议您尽可能从“可执行jar”运行时避免使用它。

为了帮助进行定制,Environment如下表所述,一些其他属性从Spring转移到System属性:

春季环境 系统属性 评论
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD 记录异常时使用的转换字。
logging.file.name LOG_FILE 如果定义,它将在默认日志配置中使用。
logging.file.path LOG_PATH 如果定义,它将在默认日志配置中使用。
logging.pattern.console CONSOLE_LOG_PATTERN 在控制台上使用的日志模式(stdout)。
logging.pattern.dateformat LOG_DATEFORMAT_PATTERN 记录日期格式的附加模式。
logging.charset.console CONSOLE_LOG_CHARSET 用于控制台日志记录的字符集。
logging.pattern.file FILE_LOG_PATTERN 文件中使用的日志模式(如果LOG_FILE已启用)。
logging.charset.file FILE_LOG_CHARSET 用于文件记录的字符集(如果LOG_FILE已启用)。
logging.pattern.level LOG_LEVEL_PATTERN 呈现日志级别时使用的格式(默认%5p)。
PID PID 当前进程ID(如果可能,并且尚未将其定义为OS环境变量时发现)。

如果您使用的是Logback,还将传输以下属性:

春季环境 系统属性 评论
logging.logback.rollingpolicy.file-name-pattern LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN 过渡日志文件名的模式(默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。
logging.logback.rollingpolicy.clean-history-on-start LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START 是否在启动时清除存档日志文件。
logging.logback.rollingpolicy.max-file-size LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE 最大日志文件大小。
logging.logback.rollingpolicy.total-size-cap LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP 要保留的日志备份的总大小。
logging.logback.rollingpolicy.max-history LOGBACK_ROLLINGPOLICY_MAX_HISTORY 要保留的最大归档日志文件数。

所有受支持的日志记录系统在解析其配置文件时都可以查阅系统属性。有关spring-boot.jar示例,请参见中的默认配置:

  • 退回
  • Log4j 2
  • Java Util日志记录
    | | 如果要在日志记录属性中使用占位符,则应使用Spring Boot的语法而不是基础框架的语法。值得注意的是,如果您使用Logback,则应将其:用作属性名称与其默认值之间的分隔符,而不应使用:-。 | | :—-: | —- |

| | 您可以通过仅覆盖LOG_LEVEL_PATTERN(或logging.pattern.level使用Logback)将MDC和其他临时内容添加到日志行。例如,如果使用logging.pattern.level=user:%X{user} %5p,则默认日志格式包含“ user”的MDC条目(如果存在),如以下示例所示。2019-08-30 12:30:04.031用户:某人INFO 22174-[[nio-8080-exec-0] demo.Controller 处理已认证的请求 | | :—-: | —- |

4.9 登录扩展

Spring Boot包含许多Logback扩展,可以帮助进行高级配置。您可以在logback-spring.xml配置文件中使用这些扩展名。

由于标准logback.xml配置文件的加载时间过早,因此无法在其中使用扩展名。您需要使用logback-spring.xml或定义一个logging.config属性。
这些扩展不能与Logback的配置扫描一起使用。如果尝试这样做,则对配置文件进行更改将导致类似于以下记录之一的错误:

ch.qos.logback.core.joran.spi.Interpreter@4中的错误:71-[springProperty]没有适用的操作,当前ElementPath是[[configuration] [springProperty]]ch.qos.logback.core.joran.spi.Interpreter@4中的
错误:71-[springProfile]没有适用的操作,当前ElementPath是[[configuration] [springProfile]]

4.9.1 特定于配置文件的配置

使用<springProfile>标签,您可以根据活动的Spring配置文件选择包括或排除配置部分。概要文件部分在<configuration>元素内的任何位置都受支持。使用name属性指定哪个配置文件接受配置。所述<springProfile>标记可包含简档名称(例如staging)或轮廓表达。简档表达式允许例如表达更复杂的简档逻辑production & (eu-central | eu-west)。有关更多详细信息,请参阅参考指南。以下清单显示了三个样本概要文件:

  1. <springProfile name="staging">
  2. <!-- configuration to be enabled when the "staging" profile is active -->
  3. </springProfile>
  4. <springProfile name="dev | staging">
  5. <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
  6. </springProfile>
  7. <springProfile name="!production">
  8. <!-- configuration to be enabled when the "production" profile is not active -->
  9. </springProfile>

4.9.2 环境特性

<springProperty>标签可以让你从Spring公开属性Environment的范围内的logback使用。如果要从application.propertiesLogback配置中访问文件中的值,则这样做很有用。该标签的工作方式类似于Logback的标准<property>标签。但是,value您无需指定direct,而是可以指定source属性的(来自Environment)。如果需要将属性存储在local范围之外的其他位置,则可以使用该scope属性。如果需要后备值(如果未在中设置属性Environment),则可以使用defaultValue属性。以下示例显示如何公开用于Logback的属性:

  1. <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
  2. defaultValue="localhost"/>
  3. <appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
  4. <remoteHost>${fluentHost}</remoteHost>
  5. ...
  6. </appender>
source必须在串的情况下(如指定my.property-name)。但是,可以Environment使用宽松规则将属性添加到中。

5.国际化

Spring Boot支持本地化消息,因此您的应用程序可以迎合不同语言首选项的用户。默认情况下,Spring Bootmessages在类路径的根目录下查找资源包的存在。

当配置的资源束的默认属性文件可用时(即messages.properties默认情况下),将应用自动配置。如果您的资源包仅包含特定于语言的属性文件,则需要添加默认文件。如果未找到与任何配置的基本名称匹配的属性文件,则不会自动配置MessageSource

可以使用spring.messages名称空间来配置资源包的基本名称以及其他几个属性,如以下示例所示:
特性
Yaml

  1. spring:
  2. messages:
  3. basename: "messages,config.i18n.messages"
  4. fallback-to-system-locale: false
spring.messages.basename 支持以逗号分隔的位置列表,即包限定符或从类路径根目录解析的资源。

请参阅MessageSourceProperties以获取更多受支持的选项。

6. JSON

Spring Boot提供了与三个JSON映射库的集成:

  • 格森
  • 杰克逊
  • JSON-B

Jackson是首选的默认库。

6.1 杰克逊

提供了Jackson的自动配置功能,并且Jackson是的一部分spring-boot-starter-json。当Jackson放在类路径上时,将ObjectMapper自动配置Bean。提供了几个配置属性,用于自定义的配置ObjectMapper

6.2 格森

提供了Gson的自动配置。当Gson在类路径上时,将Gson自动配置Bean。spring.gson.*提供了几个配置属性用于自定义配置。为了获得更多控制权,GsonBuilderCustomizer可以使用一个或多个bean。

6.3 JSON-B

提供了JSON-B的自动配置。当JSON-B API和实现位于类路径上时,Jsonb将自动配置Bean。首选的JSON-B实现是提供依赖管理的Apache Johnzon。

7.开发Web应用程序

Spring Boot非常适合Web应用程序开发。您可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建独立的HTTP服务器。大多数Web应用程序都使用该spring-boot-starter-web模块来快速启动和运行。您还可以选择使用该spring-boot-starter-webflux模块来构建反应式Web应用程序。
如果尚未开发Spring Boot Web应用程序,则可以遵循“ Hello World!”。入门部分中的示例。

7.1 “ Spring Web MVC框架”

春天Web MVC框架(通常被称为“春MVC”)是一个丰富的“模型视图控制器” Web框架。Spring MVC允许您创建特殊的@Controller@RestControllerbean来处理传入的HTTP请求。控制器中的方法通过使用@RequestMapping批注映射到HTTP 。
以下代码显示了@RestController提供JSON数据的典型代码:

  1. @RestController
  2. @RequestMapping(value="/users")
  3. public class MyRestController {
  4. @RequestMapping(value="/{user}", method=RequestMethod.GET)
  5. public User getUser(@PathVariable Long user) {
  6. // ...
  7. }
  8. @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
  9. List<Customer> getUserCustomers(@PathVariable Long user) {
  10. // ...
  11. }
  12. @RequestMapping(value="/{user}", method=RequestMethod.DELETE)
  13. public User deleteUser(@PathVariable Long user) {
  14. // ...
  15. }
  16. }

Spring MVC是核心Spring Framework的一部分,有关详细信息,请参阅参考文档。在spring.io/guides上还有一些涵盖Spring MVC的指南。

7.1.1 Spring MVC自动配置

Spring Boot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。
自动配置在Spring的默认值之上添加了以下功能:

如果要保留这些Spring Boot MVC定制并进行更多的MVC定制(拦截器,格式化程序,视图控制器和其他功能),则可以添加自己@Configuration的type类,WebMvcConfigurer不添加 @EnableWebMvc
如果你想提供的定制情况RequestMappingHandlerMappingRequestMappingHandlerAdapter或者ExceptionHandlerExceptionResolver,仍然保持弹簧引导MVC自定义,你可以声明类型的豆WebMvcRegistrations,并用它来提供这些组件的定制实例。
如果你想利用Spring MVC中的完全控制,你可以添加自己的@Configuration注解为@EnableWebMvc,或者添加自己的@Configuration-annotatedDelegatingWebMvcConfiguration中的Javadoc中所述@EnableWebMvc

Spring MVC使用ConversionService与用于从您的application.propertiesapplication.yaml文件转换值的方法不同的方法。这意味着PeriodDurationDataSize转换器不可用,并且@DurationUnit@DataSizeUnit注释将被忽略。
如果要定制ConversionServiceSpring MVC使用的,可以为WebMvcConfigurerBean提供一个addFormatters方法。通过此方法,您可以注册所需的任何转换器,也可以委托给上可用的静态方法ApplicationConversionService

7.1.2 HttpMessageConverters

Spring MVC使用该HttpMessageConverter接口转换HTTP请求和响应。开箱即用中包含明智的默认设置。例如,可以将对象自动转换为JSON(通过使用Jackson库)或XML(通过使用Jackson XML扩展(如果可用)或通过使用JAXB(如果Jackson XML扩展不可用))。默认情况下,字符串编码为UTF-8
如果需要添加或自定义转换器,则可以使用Spring Boot的HttpMessageConverters类,如以下清单所示:

  1. import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
  2. import org.springframework.context.annotation.*;
  3. import org.springframework.http.converter.*;
  4. @Configuration(proxyBeanMethods = false)
  5. public class MyConfiguration {
  6. @Bean
  7. public HttpMessageConverters customConverters() {
  8. HttpMessageConverter<?> additional = ...
  9. HttpMessageConverter<?> another = ...
  10. return new HttpMessageConverters(additional, another);
  11. }
  12. }

HttpMessageConverter上下文中存在的任何Bean都将添加到转换器列表中。您也可以用相同的方法覆盖默认转换器。

7.1.3 自定义JSON序列化器和反序列化器

如果使用Jackson来序列化和反序列化JSON数据,则可能需要编写自己的JsonSerializerJsonDeserializer类。自定义序列化程序通常是通过模块向Jackson进行注册的,但是Spring Boot提供了一种可选的@JsonComponent注释,使直接注册Spring Bean变得更加容易。
您可以使用@JsonComponent直接的注解JsonSerializerJsonDeserializerKeyDeserializer实现。您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:

  1. import java.io.*;
  2. import com.fasterxml.jackson.core.*;
  3. import com.fasterxml.jackson.databind.*;
  4. import org.springframework.boot.jackson.*;
  5. @JsonComponent
  6. public class Example {
  7. public static class Serializer extends JsonSerializer<SomeObject> {
  8. // ...
  9. }
  10. public static class Deserializer extends JsonDeserializer<SomeObject> {
  11. // ...
  12. }
  13. }

中的所有@JsonComponentbean都会ApplicationContext自动向Jackson进行注册。因为使用@JsonComponent进行了元注释@Component,所以适用通常的组件扫描规则。
Spring Boot还提供了JsonObjectSerializerJsonObjectDeserializer基类,它们在序列化对象时为标准Jackson版本提供了有用的替代方法。有关详细信息,请参见JsonObjectSerializerJsonObjectDeserializer在Javadoc中。

7.1.4。MessageCodesResolver

Spring MVC的具有产生错误代码从绑定错误的渲染错误消息的策略:MessageCodesResolver。如果设置spring.mvc.message-codes-resolver-format属性PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE,Spring Boot会为您创建一个(请参阅中的枚举DefaultMessageCodesResolver.Format)。

7.1.5。静态内容

默认情况下,Spring Boot从类路径中名为/static/public/resources/META-INF/resources)的目录或根目录提供静态内容ServletContext。它使用ResourceHttpRequestHandlerSpring MVC中的from,因此您可以通过添加自己WebMvcConfigureraddResourceHandlers方法并覆盖该方法来修改该行为。
在独立的Web应用程序中,还启用了容器中的默认servlet,并将其用作后备,从ServletContextSpring决定不处理它的根开始提供内容。在大多数情况下,这不会发生(除非您修改默认的MVC配置),因为Spring始终可以通过处理请求DispatcherServlet
默认情况下,资源映射到/**,但是您可以使用spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新分配到/resources/**以下位置即可:
特性
Yaml

  1. spring:
  2. mvc:
  3. static-path-pattern: "/resources/**"

您也可以使用spring.web.resources.static-locations属性来自定义静态资源位置(用目录位置列表替换默认值)。根Servlet上下文路径"/"也会自动添加为位置。
除了前面提到的“标准”静态资源位置,Webjars内容也有特殊情况。/webjars/**如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。

src/main/webapp如果您的应用程序打包为jar,则 不要使用该目录。尽管此目录是一个通用标准,但它仅适用于war打包,如果生成jar,大多数构建工具都会将其静默忽略。

Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用案例,例如缓存清除静态资源或对Webjars使用版本无关的URL。
要对Webjar使用版本无关的URL,请添加webjars-locator-core依赖项。然后声明您的Webjar。使用jQuery作为一个例子,将"/webjars/jquery/jquery.min.js"在结果中"/webjars/jquery/x.y.z/jquery.min.js",其中x.y.z是Webjar版本。

如果使用JBoss,则需要声明webjars-locator-jboss-vfs依赖关系而不是webjars-locator-core。否则,所有Webjar都解析为404

要使用缓存清除,以下配置为所有静态资源配置了缓存清除解决方案,从而有效地<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>在URL中添加了内容哈希,例如,:
特性
Yaml

  1. spring:
  2. web:
  3. resources:
  4. chain:
  5. strategy:
  6. content:
  7. enabled: true
  8. paths: "/**"
通过ResourceUrlEncodingFilter为Thymeleaf和FreeMarker自动配置的,可以在运行时在模板中重写资源链接。使用JSP时,您应该手动声明此过滤器。当前尚不自动支持其他模板引擎,但可以与自定义模板宏/帮助程序一起使用,也可以使用ResourceUrlProvider

例如,当使用JavaScript模块加载器动态加载资源时,不可以重命名文件。这就是为什么其他策略也受支持并且可以组合的原因。“固定”策略在URL中添加静态版本字符串,而不更改文件名,如以下示例所示:
特性
Yaml

  1. spring:
  2. web:
  3. resources:
  4. chain:
  5. strategy:
  6. content:
  7. enabled: true
  8. paths: "/**"
  9. fixed:
  10. enabled: true
  11. paths: "/js/lib/"
  12. version: "v12"

通过这种配置,位于下面的JavaScript模块"/js/lib/"使用固定的版本控制策略("/v12/js/lib/mymodule.js"),而其他资源仍使用内容版本(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>)。
请参阅ResourceProperties以获取更多受支持的选项。

专门的博客文章和Spring Framework的参考文档中已经对该功能进行了全面的描述。

7.1.6。欢迎页面

Spring Boot支持静态和模板欢迎页面。它首先index.html在配置的静态内容位置中查找文件。如果找不到,则寻找index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

7.1.7。路径匹配和内容协商

Spring MVC可以通过查看请求路径并将其匹配到应用程序中定义的映射(例如,@GetMappingController方法的注释)来将传入的HTTP请求映射到处理程序。
Spring Boot默认选择禁用后缀模式匹配,这意味着"GET /projects/spring-boot.json"类似的请求将不会与@GetMapping("/projects/spring-boot")映射匹配。这被认为是Spring MVC应用程序最佳实践。过去,此功能主要用于未发送正确的“ Accept”请求标头的HTTP客户端。我们需要确保将正确的内容类型发送给客户端。如今,内容协商已变得更加可靠。
还有其他处理HTTP客户端的方法,这些方法不能始终发送正确的“ Accept”请求标头。除了使用后缀匹配,我们还可以使用查询参数来确保将诸如这样的请求"GET /projects/spring-boot?format=json"映射到@GetMapping("/projects/spring-boot")
特性
Yaml

  1. spring:
  2. mvc:
  3. contentnegotiation:
  4. favor-parameter: true

或者,如果您更喜欢使用其他参数名称:

  1. spring:
  2. mvc:
  3. contentnegotiation:
  4. favor-parameter: true
  5. parameter-name: "myparam"

开箱即用地支持大多数标准媒体类型,但是您也可以定义新的媒体类型:
特性
Yaml

  1. spring:
  2. mvc:
  3. contentnegotiation:
  4. media-types:
  5. markdown: "text/markdown"

后缀模式匹配已被弃用,并将在以后的版本中删除。如果您了解了注意事项,但仍希望您的应用程序使用后缀模式匹配,则需要以下配置:

  1. spring.mvc.contentnegotiation.favor-path-extension=true
  2. spring.mvc.pathmatch.use-suffix-pattern=true

另外,与其打开所有后缀模式,不如只支持注册的后缀模式,这更安全:
特性
Yaml

  1. spring:
  2. mvc:
  3. contentnegotiation:
  4. favor-path-extension: true
  5. pathmatch:
  6. use-registered-suffix-pattern: true

从Spring Framework 5.3开始,Spring MVC支持多种实现策略,用于将请求路径匹配到Controller处理程序。它以前仅支持该AntPathMatcher策略,但现在也提供了PathPatternParser。Spring Boot现在提供一个配置属性供您选择和选择新策略:
特性
Yaml

  1. spring:
  2. mvc:
  3. pathmatch:
  4. matching-strategy: "path-pattern-parser"

有关为什么应考虑使用此新实现的更多详细信息,请查看 专用博客文章

PathPatternParser是一个优化的实施,但限制使用 一些路径图案的变体 ,并且与后缀模式匹配(不相容spring.mvc.pathmatch.use-suffix-patternspring.mvc.pathmatch.use-registered-suffix-pattern)或映射DispatcherServlet 与一个Servlet前缀(spring.mvc.servlet.path)。

7.1.8。ConfigurableWebBindingInitializer

Spring MVC使用aWebBindingInitializer来初始化WebDataBinder特定请求。如果创建自己的ConfigurableWebBindingInitializer @Bean,Spring Boot会自动将Spring MVC配置为使用它。

7.1.9。模板引擎

除了REST Web服务之外,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持多种模板技术,包括Thymeleaf,FreeMarker和JSP。同样,许多其他模板引擎包括它们自己的Spring MVC集成。
Spring Boot包括对以下模板引擎的自动配置支持:

在默认配置下使用这些模板引擎之一时,会自动从中提取模板src/main/resources/templates

根据您运行应用程序的方式,您的IDE可能对类路径进行不同的排序。与使用Maven或Gradle或从其打包的jar运行应用程序时相比,从IDE的主要方法运行应用程序的顺序会有所不同。这可能导致Spring Boot无法找到期望的模板。如果遇到此问题,可以在IDE中重新排序类路径,以首先放置模块的类和资源。

7.1.10。错误处理

默认情况下,Spring Boot提供了/error一种可以明智地处理所有错误的映射,并且已在servlet容器中注册为“全局”错误页面。对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,存在一个“ whitelabel”错误视图,该视图以HTML格式呈现相同的数据(要对其进行自定义,请添加View解析为error)。
server.error如果要自定义默认错误处理行为,可以设置许多属性。请参阅附录的“服务器属性”部分。
要完全替换默认行为,可以实现ErrorController并注册该类型的Bean定义,或添加类型的BeanErrorAttributes以使用现有机制但替换其内容。

BasicErrorController可以用作自定义基类ErrorController。如果您想为新的内容类型添加处理程序(默认是text/html专门处理并为其他所有内容提供后备功能),则此功能特别有用。为此,请扩展BasicErrorController,添加@RequestMapping具有produces属性的带有的公共方法,并创建新类型的bean。

您还可以定义带有注释的类,@ControllerAdvice以自定义JSON文档以针对特定的控制器和/或异常类型返回,如以下示例所示:

  1. @ControllerAdvice(basePackageClasses = AcmeController.class)
  2. public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {
  3. @ExceptionHandler(YourException.class)
  4. @ResponseBody
  5. ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
  6. HttpStatus status = getStatus(request);
  7. return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
  8. }
  9. private HttpStatus getStatus(HttpServletRequest request) {
  10. Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
  11. if (statusCode == null) {
  12. return HttpStatus.INTERNAL_SERVER_ERROR;
  13. }
  14. return HttpStatus.valueOf(statusCode);
  15. }
  16. }

在前面的示例中,如果YourException由与相同的程序包中定义的控制器抛出,则使用POJOAcmeController的JSON表示CustomErrorType代替该ErrorAttributes表示。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,则可以将文件添加到/error目录中。错误页面可以是静态HTML(即添加到任何静态资源目录下),也可以使用模板来构建。文件名应为确切的状态代码或系列掩码。
例如,要映射404到静态HTML文件,您的目录结构如下:

  1. src/
  2. +- main/
  3. +- java/
  4. | + <source code>
  5. +- resources/
  6. +- public/
  7. +- error/
  8. | +- 404.html
  9. +- <other public assets>

5xx使用FreeMarker模板映射所有错误,您的目录结构如下:

  1. src/
  2. +- main/
  3. +- java/
  4. | + <source code>
  5. +- resources/
  6. +- templates/
  7. +- error/
  8. | +- 5xx.ftlh
  9. +- <other templates>

对于更复杂的映射,还可以添加实现该ErrorViewResolver接口的bean ,如以下示例所示:

  1. public class MyErrorViewResolver implements ErrorViewResolver {
  2. @Override
  3. public ModelAndView resolveErrorView(HttpServletRequest request,
  4. HttpStatus status, Map<String, Object> model) {
  5. // Use the request or status to optionally return a ModelAndView
  6. return ...
  7. }
  8. }

您还可以使用常规的Spring MVC功能,例如@ExceptionHandler方法@ControllerAdvice。在ErrorController随后拿起任何未处理的异常。

在Spring MVC之外映射错误页面

对于不使用Spring MVC的应用程序,您可以使用ErrorPageRegistrar接口直接注册ErrorPages。此抽象直接与基础嵌入式servlet容器一起使用,即使您没有Spring MVC也可以使用DispatcherServlet

  1. @Bean
  2. public ErrorPageRegistrar errorPageRegistrar(){
  3. return new MyErrorPageRegistrar();
  4. }
  5. // ...
  6. private static class MyErrorPageRegistrar implements ErrorPageRegistrar {
  7. @Override
  8. public void registerErrorPages(ErrorPageRegistry registry) {
  9. registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
  10. }
  11. }
如果您ErrorPage使用最终由a处理的路径注册Filter(这在某些非Spring Web框架,例如Jersey和Wicket中很常见),则Filter必须将其显式注册为ERROR调度程序,如以下示例所示:
  1. @Bean
  2. public FilterRegistrationBean myFilter() {
  3. FilterRegistrationBean registration = new FilterRegistrationBean();
  4. registration.setFilter(new MyFilter());
  5. ...
  6. registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
  7. return registration;
  8. }

请注意,默认值FilterRegistrationBean不包括ERROR调度程序类型。

战争部署中的错误处理

当部署到servlet容器时,Spring Boot使用其错误页面过滤器将具有错误状态的请求转发到适当的错误页面。这是必需的,因为Servlet规范没有提供用于注册错误页面的API。根据将war文件部署到的容器以及应用程序使用的技术,可能需要一些其他配置。
如果尚未提交响应,则错误页面过滤器只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0和更高版本在成功完成servlet的服务方法后提交响应。您应该通过设置com.ibm.ws.webcontainer.invokeFlushAfterService为来禁用此行为false
如果您使用的是Spring Security,并且想访问错误页面中的主体,则必须配置Spring Security的过滤器以在错误分派时调用。为此,请将spring.security.filter.dispatcher-types属性设置为async, error, forward, request

7.1.11。春季HATEOAS

如果您开发使用超媒体的RESTful API,Spring Boot将为Spring HATEOAS提供自动配置,该配置可与大多数应用程序很好地兼容。自动配置取代了使用@EnableHypermediaSupport和注册许多Bean的需求,以简化基于超媒体的应用程序的构建,包括LinkDiscoverers(用于客户端支持)和ObjectMapper配置为正确地将响应编组为所需表示形式的Bean 。的ObjectMapper是通过设置各种定制的spring.jackson.*属性,或者,如果存在的话,通过一个Jackson2ObjectMapperBuilder豆。
您可以使用来控制Spring HATEOAS的配置@EnableHypermediaSupport。请注意,这样做会禁用ObjectMapper前面所述的自定义。

7.1.12。CORS支持

跨域资源共享(CORS)是大多数浏览器实施的W3C规范,可让您灵活地指定授权哪种类型的跨域请求,而不是使用一些安全性和功能不强的方法(例如IFRAME或JSONP) 。
从4.2版本开始,Spring MVC支持CORS。在Spring Boot应用程序中使用带有注释的控制器方法CORS配置@CrossOrigin不需要任何特定的配置。 可以通过使用自定义方法注册bean来定义全局CORS配置,如以下示例所示:WebMvcConfigurer``addCorsMappings(CorsRegistry)

  1. @Configuration(proxyBeanMethods = false)
  2. public class MyConfiguration {
  3. @Bean
  4. public WebMvcConfigurer corsConfigurer() {
  5. return new WebMvcConfigurer() {
  6. @Override
  7. public void addCorsMappings(CorsRegistry registry) {
  8. registry.addMapping("/api/**");
  9. }
  10. };
  11. }
  12. }

7.2。“ Spring WebFlux框架”

Spring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且无阻塞的,并通过Reactor项目实现Reactive Streams规范。
Spring WebFlux有两种形式:功能性的和基于注释的。基于注释的模型非常类似于Spring MVC模型,如以下示例所示:

  1. @RestController
  2. @RequestMapping("/users")
  3. public class MyRestController {
  4. @GetMapping("/{user}")
  5. public Mono<User> getUser(@PathVariable Long user) {
  6. // ...
  7. }
  8. @GetMapping("/{user}/customers")
  9. public Flux<Customer> getUserCustomers(@PathVariable Long user) {
  10. // ...
  11. }
  12. @DeleteMapping("/{user}")
  13. public Mono<User> deleteUser(@PathVariable Long user) {
  14. // ...
  15. }
  16. }

功能变体“ WebFlux.fn”将路由配置与请求的实际处理分开,如以下示例所示:

  1. @Configuration(proxyBeanMethods = false)
  2. public class RoutingConfiguration {
  3. @Bean
  4. public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
  5. return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
  6. .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
  7. .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
  8. }
  9. }
  10. @Component
  11. public class UserHandler {
  12. public Mono<ServerResponse> getUser(ServerRequest request) {
  13. // ...
  14. }
  15. public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
  16. // ...
  17. }
  18. public Mono<ServerResponse> deleteUser(ServerRequest request) {
  19. // ...
  20. }
  21. }

WebFlux是Spring Framework的一部分,其参考文档中提供了详细信息。

您可以根据需要定义任意数量的RouterFunctionbean,以对路由器的定义进行模块化。如果需要应用优先级,可以订购Bean。

首先,将spring-boot-starter-webflux模块添加到您的应用程序。

在应用程序中 同时添加spring-boot-starter-webspring-boot-starter-webflux模块会导致Spring Boot自动配置Spring MVC,而不是WebFlux。之所以选择这种行为,是因为许多Spring开发人员将spring-boot-starter-webflux其添加到他们的Spring MVC应用程序中以使用反应式WebClient。您仍然可以通过将选定的应用程序类型设置为来强制执行选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)

7.2.1。Spring WebFlux自动配置

Spring Boot为Spring WebFlux提供了自动配置,可与大多数应用程序完美配合。
自动配置在Spring的默认值之上添加了以下功能:

如果您想保留Spring Boot WebFlux功能并想要添加其他WebFlux配置,则可以添加自己@Configuration的类型类,WebFluxConfigurer不添加 @EnableWebFlux
如果要完全控制Spring WebFlux,可以使用添加自己的@Configuration注释@EnableWebFlux

7.2.2。带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器

Spring WebFlux使用HttpMessageReaderHttpMessageWriter接口转换HTTP请求和响应。CodecConfigurer通过查看类路径中可用的库,将它们配置为具有合理的默认值。
Spring Boot为编解码器提供了专用的配置属性spring.codec.*。它还通过使用CodecCustomizer实例来应用进一步的自定义。例如,将spring.jackson.*配置密钥应用于Jackson编解码器。
如果需要添加或自定义编解码器,则可以创建一个自定义CodecCustomizer组件,如以下示例所示:

  1. import org.springframework.boot.web.codec.CodecCustomizer;
  2. @Configuration(proxyBeanMethods = false)
  3. public class MyConfiguration {
  4. @Bean
  5. public CodecCustomizer myCodecCustomizer() {
  6. return codecConfigurer -> {
  7. // ...
  8. };
  9. }
  10. }

您还可以利用Boot的自定义JSON序列化器和反序列化器

7.2.3。静态内容

默认情况下,Spring Boot从类路径中名为/static/public/resources/META-INF/resources)的目录中提供静态内容。它使用ResourceWebHandlerSpring WebFlux中的,因此您可以通过添加自己WebFluxConfigureraddResourceHandlers方法并覆盖该方法来修改该行为。
默认情况下,资源映射在上/**,但是您可以通过设置spring.webflux.static-path-pattern属性来对其进行调整。例如,将所有资源重新分配到/resources/**以下位置即可:
特性
Yaml

  1. spring:
  2. webflux:
  3. static-path-pattern: "/resources/**"

您还可以使用来自定义静态资源位置spring.web.resources.static-locations。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果index.html启动时您的任何位置都有,则为应用程序的主页。
除了前面列出的“标准”静态资源位置之外,Webjars内容也有特殊情况。/webjars/**如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。

Spring WebFlux应用程序不严格依赖Servlet API,因此不能将它们部署为war文件,也不使用src/main/webapp目录。

7.2.4。欢迎页面

Spring Boot支持静态和模板欢迎页面。它首先index.html在配置的静态内容位置中查找文件。如果找不到,则寻找index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

7.2.5。模板引擎

除了REST Web服务之外,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持多种模板技术,包括Thymeleaf,FreeMarker和Mustache。
Spring Boot包括对以下模板引擎的自动配置支持:

在默认配置下使用这些模板引擎之一时,会自动从中提取模板src/main/resources/templates

7.2.6。错误处理

Spring Boot提供了WebExceptionHandler一个以明智的方式处理所有错误的工具。它在处理顺序中的位置紧靠WebFlux提供的处理程序之前,该处理程序被认为是最后一个。对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“ whitelabel”错误处理程序,以HTML格式呈现相同的数据。您还可以提供自己的HTML模板来显示错误(请参阅下一节)。
定制此功能的第一步通常涉及使用现有机制,但替换或增加错误内容。为此,您可以添加类型的Bean ErrorAttributes
要更改错误处理行为,可以实现ErrorWebExceptionHandler并注册该类型的bean定义。由于aWebExceptionHandler级别很低,因此Spring Boot还提供了一种方便的方式AbstractErrorWebExceptionHandler,使您可以通过WebFlux功能方式处理错误,如以下示例所示:

  1. public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
  2. // Define constructor here
  3. @Override
  4. protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
  5. return RouterFunctions
  6. .route(aPredicate, aHandler)
  7. .andRoute(anotherPredicate, anotherHandler);
  8. }
  9. }

为了获得更完整的图像,您还可以DefaultErrorWebExceptionHandler直接继承子类并覆盖特定的方法。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,则可以将文件添加到/error目录中。错误页面可以是静态HTML(即添加到任何静态资源目录下),也可以使用模板构建。文件名应为确切的状态代码或系列掩码。
例如,要映射404到静态HTML文件,您的目录结构如下:

  1. src/
  2. +- main/
  3. +- java/
  4. | + <source code>
  5. +- resources/
  6. +- public/
  7. +- error/
  8. | +- 404.html
  9. +- <other public assets>

5xx使用Mustache模板映射所有错误,您的目录结构如下:

  1. src/
  2. +- main/
  3. +- java/
  4. | + <source code>
  5. +- resources/
  6. +- templates/
  7. +- error/
  8. | +- 5xx.mustache
  9. +- <other templates>

7.2.7。网页过滤器

Spring WebFlux提供了一个WebFilter可实现以过滤HTTP请求-响应交换的接口。 WebFilter在应用程序上下文中找到的bean将自动用于过滤每个交换。
如果过滤器的顺序很重要,则可以使用Ordered或对其进行注释@Order。Spring Boot自动配置可能会为您配置Web过滤器。这样做时,将使用下表中显示的顺序:

网页过滤器 命令
MetricsWebFilter Ordered.HIGHEST_PRECEDENCE + 1
WebFilterChainProxy (春季安全) -100
HttpTraceWebFilter Ordered.LOWEST_PRECEDENCE - 10

7.3。JAX-RS和泽西岛

如果您更喜欢REST端点的JAX-RS编程模型,则可以使用可用的实现之一来代替Spring MVC。 JerseyApache CXF开箱即用。CXF需要您注册其ServletFilter@Bean您的应用程序上下文。泽西岛(Jersey)有一些本机Spring支持,因此我们在Spring Boot中还与启动器一起为其提供了自动配置支持。
要开始使用Jersey,请将包含spring-boot-starter-jersey为依赖项,然后需要使用一种@Bean类型ResourceConfig注册所有端点,如以下示例所示:

  1. @Component
  2. public class JerseyConfig extends ResourceConfig {
  3. public JerseyConfig() {
  4. register(Endpoint.class);
  5. }
  6. }
泽西岛对扫描可执行归档文件的支持非常有限。例如,它无法扫描在完全可执行的jar文件中或在WEB-INF/classes运行可执行的war文件时在包中找到的端点。为避免此限制,packages不应使用该方法,并且应使用该register方法分别注册端点,如前面的示例所示。

对于更高级的自定义,您还可以注册任意数量的实现的Bean ResourceConfigCustomizer
所有注册的端点都应@Components带有HTTP资源注释(@GET及其他注释),如以下示例所示:

  1. @Component
  2. @Path("/hello")
  3. public class Endpoint {
  4. @GET
  5. public String message() {
  6. return "Hello";
  7. }
  8. }

由于Endpoint是Spring @Component,因此其生命周期由Spring管理,您可以使用@Autowired批注注入依赖项,并使用@Value批注注入外部配置。默认情况下,Jersey servlet已注册并映射到/*。您可以通过添加改变映射@ApplicationPath到你ResourceConfig
默认情况下,Jersey被设置为名为@Bean类型的Servlet 。默认情况下,该servlet延迟初始化,但是您可以通过设置来自定义该行为。您可以通过创建自己的同名bean来禁用或覆盖该bean。您还可以通过设置使用过滤器而不是servlet (在这种情况下,要替换或覆盖的是)。过滤器具有,您可以使用设置。通过使用指定属性映射,可以为servlet和过滤器注册都赋予init参数。ServletRegistrationBean``jerseyServletRegistration``spring.jersey.servlet.load-on-startup``spring.jersey.type=filter``@Bean``jerseyFilterRegistration``@Order``spring.jersey.filter.order``spring.jersey.init.*

7.4。嵌入式Servlet容器支持

Spring Boot包含对嵌入式TomcatJettyUndertow服务器的支持。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在port上侦听HTTP请求8080

7.4.1。Servlet,过滤器和侦听器

使用嵌入式Servlet容器时,您可以HttpSessionListener使用Spring Bean或扫描Servlet组件来注册Servlet规范中的Servlet,过滤器和所有侦听器(例如)。

将Servlet,过滤器和侦听器注册为Spring Bean

作为Spring bean的任何ServletFilter或servlet*Listener实例都向嵌入式容器注册。如果要application.properties在配置过程中引用一个值,这将特别方便。
默认情况下,如果上下文仅包含单个Servlet,则将其映射到/。如果有多个servlet bean,则将bean名称用作路径前缀。过滤器映射到/*
如果以公约为基础测绘不够灵活,你可以使用ServletRegistrationBeanFilterRegistrationBean以及ServletListenerRegistrationBean类的完全控制。
通常可以使无序滤豆处于安全状态。如果需要一个特定的顺序,你应该注释Filter@Order或使其实现Ordered。您无法Filter通过使用注释a的bean方法来配置其顺序@Order。如果您不能更改Filter要添加@Order或实现的类Ordered,则必须为定义一个FilterRegistrationBeanFilter并使用setOrder(int)方法设置注册bean的顺序。避免配置一个在处读取请求正文的过滤器Ordered.HIGHEST_PRECEDENCE,因为它可能与应用程序的字符编码配置不符。如果Servlet过滤器包装了请求,则应以小于或等于的顺序对其进行配置OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER

要查看Filter应用程序中每个组件的顺序,请为web 日志记录组logging.level.web=debug)启用调试级别的日志记录。然后,将在启动时记录已注册过滤器的详细信息,包括其顺序和URL模式。
注册Filterbean时要小心,因为它们是在应用程序生命周期中很早就初始化的。如果需要注册一个Filter与其他bean交互的对象,请考虑使用a DelegatingFilterProxyRegistrationBean

7.4.2。Servlet上下文初始化

嵌入式Servlet容器不会直接执行Servlet 3.0+javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。这是一个有意设计的决定,目的是减少旨在在战争中运行的第三方库可能破坏Spring Boot应用程序的风险。
如果您需要在Spring Boot应用程序中执行servlet上下文初始化,则应该注册一个实现该org.springframework.boot.web.servlet.ServletContextInitializer接口的bean 。单一onStartup方法提供对的访问,ServletContext并且在必要时可以轻松地用作现有的适配器WebApplicationInitializer

扫描Servlet,过滤器和侦听器

当使用嵌入式容器中,类自动登记注释有@WebServlet@WebFilter@WebListener可以通过使用被使能@ServletComponentScan

@ServletComponentScan 在独立容器中无效,而是使用容器的内置发现机制。

7.4.3。ServletWebServerApplicationContext

在后台,Spring BootApplicationContext对嵌入式servlet容器使用了不同类型的支持。该ServletWebServerApplicationContext是一种特殊类型的WebApplicationContext通过搜索单说引导自身ServletWebServerFactory豆。通常是TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory已自动配置。

通常,您不需要了解这些实现类。大多数应用程序都自动配置,并适当的ApplicationContextServletWebServerFactory以您的名义创建。

7.4.4。自定义嵌入式Servlet容器

可以使用SpringEnvironment属性来配置常见的servlet容器设置。通常,您将在application.propertiesapplication.yaml文件中定义属性。
常用服务器设置包括:

  • 网络设置:侦听传入HTTP请求的端口(server.port),绑定到的接口地址server.address,等等。
  • 会话设置:会话是否为持久(server.servlet.session.persistent),会话超时(server.servlet.session.timeout),会话数据位置(server.servlet.session.store-dir)和会话cookie配置(server.servlet.session.cookie.*)。
  • 错误管理:错误页面的位置(server.error.path),依此类推。
  • SSL协议
  • HTTP压缩

Spring Boot尝试尽可能多地公开通用设置,但这并不总是可能的。在这种情况下,专用名称空间提供服务器特定的自定义(请参阅server.tomcatserver.undertow)。例如,可以使用嵌入式servlet容器的特定功能配置访问日志

有关ServerProperties完整列表,请参见课程。

程序化定制

如果需要以编程方式配置嵌入式servlet容器,则可以注册一个实现该WebServerFactoryCustomizer接口的Spring bean 。 WebServerFactoryCustomizer提供对的访问ConfigurableServletWebServerFactory,其中包括许多自定义设置方法。以下示例显示以编程方式设置端口:

  1. import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  2. import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
  6. @Override
  7. public void customize(ConfigurableServletWebServerFactory server) {
  8. server.setPort(9000);
  9. }
  10. }

TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory是的专用变体ConfigurableServletWebServerFactory具有用于分别的Tomcat,码头和暗流额外定制setter方法。以下示例显示了如何进行自定义TomcatServletWebServerFactory,以提供对特定于Tomcat的配置选项的访问:

  1. @Component
  2. public class TomcatServerCustomizerExample implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
  3. @Override
  4. public void customize(TomcatServletWebServerFactory server) {
  5. server.addConnectorCustomizers(
  6. (tomcatConnector) -> tomcatConnector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
  7. }
  8. }

直接自定义ConfigurableServletWebServerFactory

对于需要您从扩展的更高级的用例ServletWebServerFactory,您可以自己公开这种类型的bean。
提供了许多配置选项的设置器。如果您需要做一些更奇特的操作,还提供了几种受保护的方法“挂钩”。有关详细信息,请参见源代码文档

自动配置的定制器仍会应用到您的定制工厂,因此请谨慎使用该选项。

7.4.5。JSP局限性

当运行使用嵌入式servlet容器(并打包为可执行归档文件)的Spring Boot应用程序时,JSP支持存在一些限制。

  • 对于Jetty和Tomcat,如果使用战争包装,它应该可以工作。与一起启动时java -jar,可执行的War将起作用,并且还将可部署到任何标准容器中。使用可执行jar时,不支持JSP。
  • Undertow不支持JSP。
  • 创建自定义error.jsp页面不会覆盖默认视图以进行错误处理。 应改用自定义错误页面

    7.5。嵌入式反应服务器支持

    Spring Boot包含对以下嵌入式反应式Web服务器的支持:Reactor Netty,Tomcat,Jetty和Undertow。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

    7.6。反应性服务器资源配置

    当自动配置Reactor Netty或Jetty服务器时,Spring Boot将创建特定的bean,这些bean将为服务器实例提供HTTP资源:ReactorResourceFactoryJettyResourceFactory
    默认情况下,在以下情况下,这些资源还将与Reactor Netty和Jetty客户端共享,以实现最佳性能:

  • 服务器和客户端使用相同的技术

  • 客户端实例是使用WebClient.BuilderSpring Boot自动配置的bean构建的

开发人员可以通过提供自定义ReactorResourceFactoryJettyResourceFactorybean来覆盖Jetty和Reactor Netty的资源配置-这将同时应用于客户端和服务器。
您可以在WebClient Runtime部分中了解有关客户端资源配置的更多信息。

8.正常关机

所有四个嵌入式Web服务器(Jetty,Reactor Netty,Tomcat和Undertow)以及响应式和基于Servlet的Web应用程序都支持正常关机。它是关闭应用程序上下文的一部分,并且在停止SmartLifecyclebean的最早阶段执行。该停止处理使用一个超时,该超时提供一个宽限期,在此宽限期内,现有请求将被允许完成,而新请求将不被允许。不允许新请求的确切方式因所使用的Web服务器而异。Jetty,Reactor Netty和Tomcat将停止在网络层接受请求。Undertow将接受请求,但会立即以服务不可用(503)响应进行响应。

使用Tomcat正常关机需要Tomcat 9.0.33或更高版本。

要启用正常关机,请配置server.shutdown属性,如以下示例所示:
特性
Yaml

  1. server:
  2. shutdown: "graceful"

要配置超时时间,请配置spring.lifecycle.timeout-per-shutdown-phase属性,如以下示例所示:
特性
Yaml

  1. spring:
  2. lifecycle:
  3. timeout-per-shutdown-phase: "20s"
如果您的IDE无法正常发送SIGTERM信号,则可能无法正常运行。有关更多详细信息,请参阅IDE的文档。

9. RSocket

RSocket是用于字节流传输的二进制协议。它通过通过单个连接传递的异步消息来启用对称交互模型。
spring-messagingSpring框架的模块在客户端和服务器端都支持RSocket请求者和响应者。有关更多详细信息,请参见Spring Framework参考中的RSocket部分,其中包括RSocket协议的概述。

9.1。RSocket策略自动配置

Spring Boot自动配置一个RSocketStrategiesbean,该bean提供用于编码和解码RSocket有效负载的所有必需的基础结构。默认情况下,自动配置将尝试(按顺序)配置以下内容:

  1. Jackson的CBOR编解码器
  2. 杰克逊的JSON编解码器

spring-boot-starter-rsocket启动同时提供的依赖。查阅Jackson支持部分,以了解有关定制可能性的更多信息。
开发人员可以RSocketStrategies通过创建实现该RSocketStrategiesCustomizer接口的bean来自定义组件。请注意,它们@Order很重要,因为它确定编解码器的顺序。

9.2。RSocket服务器自动配置

Spring Boot提供了RSocket服务器自动配置。所需的依赖项由提供spring-boot-starter-rsocket
Spring Boot允许通过WebFlux服务器通过WebSocket公开RSocket,或支持独立的RSocket服务器。这取决于应用程序的类型及其配置。
对于WebFlux应用程序(即类型WebApplicationType.REACTIVE),仅当以下属性匹配时,RSocket服务器才会插入Web服务器:
特性
Yaml

  1. spring:
  2. rsocket:
  3. server:
  4. mapping-path: "/rsocket"
  5. transport: "websocket"
由于RSocket本身是使用该库构建的,因此只有Reactor Netty支持将RSocket插入Web服务器。

另外,RSocket TCP或Websocket服务器也可以作为独立的嵌入式服务器启动。除了依赖性要求之外,唯一需要的配置是为该服务器定义端口:
特性
Yaml

  1. spring:
  2. rsocket:
  3. server:
  4. port: 9898

9.3。Spring Messaging RSocket支持

Spring Boot将为RSocket自动配置Spring Messaging基础结构。
这意味着Spring Boot将创建一个RSocketMessageHandlerbean,该bean将处理对您的应用程序的RSocket请求。

9.4。使用RSocketRequester调用RSocket服务

一旦RSocket在服务器和客户端之间建立了通道,任何一方都可以向另一方发送或接收请求。
作为服务器,您可以RSocketRequester在RSocket的任何处理程序方法上注入实例@Controller。作为客户端,您需要首先配置和建立RSocket连接。Spring Boot会RSocketRequester.Builder使用预期的编解码器自动配置。
RSocketRequester.Builder实例是一个原型bean,这意味着每个注入点将为您提供一个新实例。这是有意为之的,因为此构建器是有状态的,因此您不应使用同一实例创建具有不同设置的请求者。
以下代码显示了一个典型示例:

  1. @Service
  2. public class MyService {
  3. private final Mono<RSocketRequester> rsocketRequester;
  4. public MyService(RSocketRequester.Builder rsocketRequesterBuilder) {
  5. this.rsocketRequester = rsocketRequesterBuilder
  6. .connectTcp("example.org", 9898).cache();
  7. }
  8. public Mono<User> someRSocketCall(String name) {
  9. return this.rsocketRequester.flatMap(req ->
  10. req.route("user").data(name).retrieveMono(User.class));
  11. }
  12. }

10.安全性

如果Spring Security在类路径上,则默认情况下Web应用程序是安全的。Spring Boot依靠Spring Security的内容协商策略来确定使用httpBasic还是formLogin。要将方法级安全性添加到Web应用程序,您还可以添加@EnableGlobalMethodSecurity所需的设置。可以在《Spring Security参考指南》中找到更多信息。
默认值UserDetailsService只有一个用户。用户名为user,密码为随机密码,并在应用程序启动时以INFO级别显示,如下例所示:
使用生成的安全密码:78fa095d-3f4c-48b1-ad50-e24c31d5cf35

如果您微调日志记录配置,请确保将org.springframework.boot.autoconfigure.security类别设置为日志INFO级别的消息。否则,不会打印默认密码。

您可以通过提供spring.security.user.name和来更改用户名和密码spring.security.user.password
默认情况下,您在Web应用程序中获得的基本功能是:

  • 一个具有内存存储的bean UserDetailsService(或ReactiveUserDetailsServiceWebFlux应用程序)和一个具有生成的密码的单个用户(请参阅参考资料SecurityProperties.User,获取用户的属性)。
  • Accept整个应用程序的基于表单的登录或HTTP基本安全性(取决于请求中的标头)(如果执行器位于类路径上,则包括执行器端点)。
  • 一个DefaultAuthenticationEventPublisher用于发布身份验证事件。

您可以AuthenticationEventPublisher通过添加一个bean来提供不同的东西。

10.1。MVC安全

默认的安全配置在SecurityAutoConfiguration和中实现UserDetailsServiceAutoConfigurationSecurityAutoConfiguration导入SpringBootWebSecurityConfigurationWeb安全性并UserDetailsServiceAutoConfiguration配置身份验证,这在非Web应用程序中也很重要。要完全关闭默认的Web应用程序安全性配置或合并多个Spring Security组件(例如OAuth2 Client和Resource Server),请添加一个类型的bean SecurityFilterChain(这样做不会禁用UserDetailsService配置或Actuator的安全性)。
为了还关闭UserDetailsService的配置,您可以添加类型的豆UserDetailsServiceAuthenticationProviderAuthenticationManager
可以通过添加自定义SecurityFilterChainWebSecurityConfigurerAdapterbean来覆盖访问规则。Spring Boot提供了便利的方法,可用于覆盖执行器端点和静态资源的访问规则。 EndpointRequest可用于创建RequestMatcher基于management.endpoints.web.base-path属性的。 PathRequest可用于RequestMatcher在常用位置创建for资源。

10.2。WebFlux安全

与Spring MVC应用程序类似,您可以通过添加spring-boot-starter-security依赖项来保护WebFlux应用程序。默认的安全配置在ReactiveSecurityAutoConfiguration和中实现UserDetailsServiceAutoConfigurationReactiveSecurityAutoConfiguration导入WebFluxSecurityConfigurationWeb安全性并UserDetailsServiceAutoConfiguration配置身份验证,这在非Web应用程序中也很重要。要完全关闭默认的Web应用程序安全性配置,可以添加类型的Bean WebFilterChainProxy(这样做不会禁用UserDetailsService配置或执行器的安全性)。
要也关闭UserDetailsService配置,可以添加类型为ReactiveUserDetailsService或的Bean ReactiveAuthenticationManager
可以通过添加自定义SecurityWebFilterChainbean来配置访问规则以及使用多个Spring Security组件(例如OAuth 2 Client和Resource Server)。Spring Boot提供了便利的方法,可用于覆盖执行器端点和静态资源的访问规则。 EndpointRequest可用于创建ServerWebExchangeMatcher基于management.endpoints.web.base-path属性的。
PathRequest可用于ServerWebExchangeMatcher在常用位置创建for资源。
例如,您可以通过添加以下内容来自定义安全配置:

  1. @Bean
  2. public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  3. return http
  4. .authorizeExchange()
  5. .matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
  6. .pathMatchers("/foo", "/bar")
  7. .authenticated().and()
  8. .formLogin().and()
  9. .build();
  10. }

10.3。OAuth2

OAuth2是Spring支持的一种广泛使用的授权框架。

10.3.1。客户

如果您spring-security-oauth2-client在类路径中,则可以利用一些自动配置来设置OAuth2 / Open ID Connect客户端。此配置使用的属性OAuth2ClientProperties。相同的属性适用于servlet和反应式应用程序。
您可以在spring.security.oauth2.client前缀下注册多个OAuth2客户端和提供者,如以下示例所示:
特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. client:
  5. registration:
  6. my-client-1:
  7. client-id: "abcd"
  8. client-secret: "password"
  9. client-name: "Client for user scope"
  10. provider: "my-oauth-provider"
  11. scope: "user"
  12. redirect-uri: "https://my-redirect-uri.com"
  13. client-authentication-method: "basic"
  14. authorization-grant-type: "authorization-code"
  15. my-client-2:
  16. client-id: "abcd"
  17. client-secret: "password"
  18. client-name: "Client for email scope"
  19. provider: "my-oauth-provider"
  20. scope: "email"
  21. redirect-uri: "https://my-redirect-uri.com"
  22. client-authentication-method: "basic"
  23. authorization-grant-type: "authorization_code"
  24. provider:
  25. my-oauth-provider:
  26. authorization-uri: "https://my-auth-server/oauth/authorize"
  27. token-uri: "https://my-auth-server/oauth/token"
  28. user-info-uri: "https://my-auth-server/userinfo"
  29. user-info-authentication-method: "header"
  30. jwk-set-uri: "https://my-auth-server/token_keys"
  31. user-name-attribute: "name"

对于支持OpenID Connect发现的OpenID Connect提供程序,可以进一步简化配置。提供者需要配置为,issuer-uri后者是它声明为其发行者标识符的URI。例如,如果issuer-uri提供的是“ https://example.com”,则将OpenID Provider Configuration Request对“ https://example.com/.well-known/openid-configuration”进行标记。结果预期为OpenID Provider Configuration Response。以下示例显示如何使用来配置OpenID Connect提供程序issuer-uri
特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. client:
  5. provider:
  6. oidc-provider:
  7. issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"

默认情况下,Spring SecurityOAuth2LoginAuthenticationFilter只处理匹配的URL /login/oauth2/code/*。如果要自定义,redirect-uri以使用其他模式,则需要提供配置以处理该自定义模式。例如,对于Servlet应用程序,您可以添加SecurityFilterChain类似于以下内容的自己的应用程序:

  1. @Bean
  2. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  3. http
  4. .authorizeRequests()
  5. .anyRequest().authenticated()
  6. .and()
  7. .oauth2Login()
  8. .redirectionEndpoint()
  9. .baseUri("/custom-callback");
  10. return http.build();
  11. }
Spring Boot自动配置InMemoryOAuth2AuthorizedClientServiceSpring Security用于管理客户端注册的。的InMemoryOAuth2AuthorizedClientService功能有限,我们建议仅将其用于开发环境。对于生产环境,请考虑使用JdbcOAuth2AuthorizedClientService或创建自己的实现OAuth2AuthorizedClientService

普通提供商的OAuth2客户端注册

对于常见的OAuth2和OpenID提供商,包括谷歌,Github上,Facebook和1563,我们提供了一组供应商默认的(googlegithubfacebook,和okta,分别)。
如果不需要自定义这些提供程序,则可以将provider属性设置为需要为其推断默认值的属性。另外,如果用于客户端注册的密钥与默认支持的提供程序匹配,则Spring Boot也会进行推断。
换句话说,以下示例中的两种配置都使用Google提供程序:
特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. client:
  5. registration:
  6. my-client:
  7. client-id: "abcd"
  8. client-secret: "password"
  9. provider: "google"
  10. google:
  11. client-id: "abcd"
  12. client-secret: "password"

10.3.2。资源服务器

如果您spring-security-oauth2-resource-server在类路径中,则Spring Boot可以设置OAuth2资源服务器。对于JWT配置,需要指定JWK设置URI或OIDC颁发者URI,如以下示例所示:
特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. resourceserver:
  5. jwt:
  6. jwk-set-uri: "https://example.com/oauth2/default/v1/keys"

特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. resourceserver:
  5. jwt:
  6. issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"
如果授权服务器不支持JWK设置URI,则可以使用用于验证JWT签名的公钥配置资源服务器。可以使用spring.security.oauth2.resourceserver.jwt.public-key-location属性来完成此操作,该属性值需要指向包含PEM编码的x509格式的公钥的文件。

相同的属性适用于servlet和反应式应用程序。
另外,您可以JwtDecoder为Servlet应用程序或ReactiveJwtDecoder反应式应用程序定义自己的bean 。
如果使用不透明令牌而不是JWT,则可以配置以下属性以通过自省来验证令牌:
特性
Yaml

  1. spring:
  2. security:
  3. oauth2:
  4. resourceserver:
  5. opaquetoken:
  6. introspection-uri: "https://example.com/check-token"
  7. client-id: "my-client-id"
  8. client-secret: "my-client-secret"

同样,相同的属性适用于servlet和反应式应用程序。
另外,您可以OpaqueTokenIntrospector为Servlet应用程序或ReactiveOpaqueTokenIntrospector反应式应用程序定义自己的bean 。

10.3.3。授权服务器

当前,Spring Security不提供对实现OAuth 2.0授权服务器的支持。但是,Spring Security OAuth项目提供了此功能,该功能最终将完全被Spring Security取代。在此之前,您可以使用该spring-security-oauth2-autoconfigure模块轻松设置OAuth 2.0授权服务器;有关说明,请参见其文档

10.4。SAML 2.0

10.4.1。依赖党

如果您spring-security-saml2-service-provider在类路径中,则可以利用一些自动配置来设置SAML 2.0依赖方。此配置使用的属性Saml2RelyingPartyProperties
依赖方注册代表身份提供者IDP和服务提供者SP之间的配对配置。您可以在spring.security.saml2.relyingparty前缀下注册多个依赖方,如以下示例所示:
特性
Yaml

  1. spring:
  2. security:
  3. saml2:
  4. relyingparty:
  5. registration:
  6. my-relying-party1:
  7. signing:
  8. credentials:
  9. - private-key-location: "path-to-private-key"
  10. certificate-location: "path-to-certificate"
  11. decryption:
  12. credentials:
  13. - private-key-location: "path-to-private-key"
  14. certificate-location: "path-to-certificate"
  15. identityprovider:
  16. verification:
  17. credentials:
  18. - certificate-location: "path-to-verification-cert"
  19. entity-id: "remote-idp-entity-id1"
  20. sso-url: "https://remoteidp1.sso.url"
  21. my-relying-party2:
  22. signing:
  23. credentials:
  24. - private-key-location: "path-to-private-key"
  25. certificate-location: "path-to-certificate"
  26. decryption:
  27. credentials:
  28. - private-key-location: "path-to-private-key"
  29. certificate-location: "path-to-certificate"
  30. identityprovider:
  31. verification:
  32. credentials:
  33. - certificate-location: "path-to-other-verification-cert"
  34. entity-id: "remote-idp-entity-id2"
  35. sso-url: "https://remoteidp2.sso.url"

10.5。执行器安全

为了安全起见,默认情况下,除/health和以外的所有执行器/info都是禁用的。该management.endpoints.web.exposure.include属性可用于启用执行器。
如果春季安全是在类路径上,没有其他WebSecurityConfigurerAdapterSecurityFilterChain豆存在,所有的执行机构以外/health,并/info通过春天开机自动配置固定。如果您定义一个定制WebSecurityConfigurerAdapterSecurityFilterChainbean,Spring Boot自动配置将退出,您将完全控制执行器访问规则。

在设置之前management.endpoints.web.exposure.include,请确保裸露的执行器不包含敏感信息和/或通过将它们放置在防火墙后面或通过诸如Spring Security之类的东西进行保护。

10.5.1。跨站点请求伪造保护

由于Spring Boot依赖于Spring Security的默认值,因此默认情况下CSRF保护是打开的。这意味着在使用默认安全性配置时,需要POST(关闭和记录器端点)的执行器端点PUTDELETE将收到403禁止错误。

我们建议仅在创建非浏览器客户端使用的服务时完全禁用CSRF保护。

关于CSRF保护的其他信息可以在Spring Security Reference Guide中找到

11.使用SQL数据库

Spring框架提供了利用使用SQL数据库,直接JDBC访问广泛的支持JdbcTemplate来完成“对象关系映射”技术,比如Hibernate。 Spring Data提供了更高级别的功能:Repository直接从接口创建实现,并使用约定从您的方法名称生成查询。

11.1。配置数据源

Java的javax.sql.DataSource界面提供了使用数据库连接的标准方法。传统上,“数据源”使用URL以及一些凭据来建立数据库连接。

有关更多高级示例,请参见“操作方法”部分,通常可以完全控制DataSource的配置。

11.1.1。嵌入式数据库支持

使用内存嵌入式数据库来开发应用程序通常很方便。显然,内存数据库不提供持久存储。您需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。

“操作方法”部分包括有关如何初始化数据库的部分

Spring Boot可以自动配置嵌入式H2HSQLDerby数据库。您无需提供任何连接URL。您只需要包含要使用的嵌入式数据库的构建依赖项即可。

如果您在测试中使用此功能,则可能会注意到,整个测试套件将重复使用同一数据库,而不管您使用的应用程序上下文有多少。如果要确保每个上下文都有一个单独的嵌入式数据库,则应设置spring.datasource.generate-unique-nametrue

例如,典型的POM依赖关系如下:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jpa</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.hsqldb</groupId>
  7. <artifactId>hsqldb</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>
您需要依赖spring-jdbc才能自动配置嵌入式数据库。在此示例中,它通过传递spring-boot-starter-data-jpa
如果出于某种原因确实为嵌入式数据库配置了连接URL,请确保确保禁用了数据库的自动关闭功能。如果使用H2,则应使用H2 DB_CLOSE_ON_EXIT=FALSE。如果使用HSQLDB,则应确保shutdown=true未使用它。通过禁用数据库的自动关闭功能,Spring Boot可以控制何时关闭数据库,从而确保一旦不再需要访问数据库时就可以进行自动启动。

11.1.2。连接到生产数据库

生产数据库连接也可以使用pooling进行自动配置DataSource。Spring Boot使用以下算法来选择特定的实现:

  1. 我们更喜欢HikariCP的性能和并发性。如果HikariCP可用,我们总是选择它。
  2. 否则,如果Tomcat池DataSource可用,我们将使用它。
  3. 否则,如果Commons DBCP2可用,我们将使用它。
  4. 如果没有HikariCP,Tomcat和DBCP2,并且如果有Oracle UCP,我们将使用它。

如果使用spring-boot-starter-jdbcspring-boot-starter-data-jpa“启动器”,则会自动获得对的依赖HikariCP

您可以完全绕过该算法,并通过设置spring.datasource.type属性来指定要使用的连接池。如果您在tomcat-jdbc默认情况下提供的Tomcat容器中运行应用程序,则这一点尤其重要。
其他连接池始终可以手动配置。如果定义自己的DataSourcebean,则不会进行自动配置。

DataSource配置由中的外部配置属性控制spring.datasource.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. datasource:
  3. url: "jdbc:mysql://localhost/test"
  4. username: "dbuser"
  5. password: "dbpass"
您至少应通过设置spring.datasource.url属性来指定URL 。否则,Spring Boot会尝试自动配置嵌入式数据库。
Spring Boot可以从URL推断出大多数数据库的JDBC驱动程序类。如果需要指定特定的类,则可以使用该spring.datasource.driver-class-name属性。
对于DataSource要创建的池,我们需要能够验证有效的Driver类是否可用,因此我们在进行任何操作之前都要进行检查。换句话说,如果您设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,则该类必须是可加载的。

请参阅DataSourceProperties以获取更多受支持的选项。这些是与实际实现无关的标准选项。它也有可能微调实现特定的设置,使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*spring.datasource.dbcp2.*spring.datasource.oracleucp.*)。有关更多详细信息,请参阅所用连接池实现的文档。
例如,如果使用Tomcat连接池,则可以自定义许多其他设置,如以下示例所示:
特性
Yaml

  1. spring:
  2. datasource:
  3. tomcat:
  4. max-wait: 10000
  5. max-active: 50
  6. test-on-borrow: true

如果没有可用连接,这会将池设置为在引发异常之前等待10000 ms,将最大连接数限制为50,并在从池借用连接之前验证连接。

11.1.3。连接到JNDI数据源

如果您将Spring Boot应用程序部署到Application Server,则可能需要使用Application Server的内置功能来配置和管理DataSource,并使用JNDI对其进行访问。
spring.datasource.jndi-name属性可以被用作一个替代spring.datasource.urlspring.datasource.usernamespring.datasource.password属性来访问DataSource从一个特定的JNDI位置。例如,以下部分application.properties显示了如何访问定义的JBoss AS DataSource
特性
Yaml

  1. spring:
  2. datasource:
  3. jndi-name: "java:jboss/datasources/customers"

11.2。使用JdbcTemplate

SpringJdbcTemplateNamedParameterJdbcTemplateclass是自动配置的,您可以将@Autowire它们直接放入自己的bean中,如以下示例所示:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class MyBean {
  6. private final JdbcTemplate jdbcTemplate;
  7. @Autowired
  8. public MyBean(JdbcTemplate jdbcTemplate) {
  9. this.jdbcTemplate = jdbcTemplate;
  10. }
  11. // ...
  12. }

您可以使用属性来自定义模板的某些属性spring.jdbc.template.*,如以下示例所示:
特性
Yaml

  1. spring:
  2. jdbc:
  3. template:
  4. max-rows: 500
NamedParameterJdbcTemplate重复使用相同的JdbcTemplate幕后情况。如果JdbcTemplate定义了多个,并且不存在主要候选对象,NamedParameterJdbcTemplate则不会自动配置。

11.3。JPA和Spring Data JPA

Java Persistence API是一种标准技术,可让您将对象“映射”到关系数据库。该spring-boot-starter-data-jpaPOM提供了上手的快捷方式。它提供以下关键依赖性:

11.3.1。实体类别

传统上,JPA“实体”类在persistence.xml文件中指定。在Spring Boot中,此文件不是必需的,而是使用“实体扫描”。默认情况下,将搜索主配置类(用@EnableAutoConfiguration或注释的一个@SpringBootApplication)下的所有软件包。
任何类别标注了@Entity@Embeddable或者@MappedSuperclass被认为是。典型的实体类类似于以下示例:

  1. package com.example.myapp.domain;
  2. import java.io.Serializable;
  3. import javax.persistence.*;
  4. @Entity
  5. public class City implements Serializable {
  6. @Id
  7. @GeneratedValue
  8. private Long id;
  9. @Column(nullable = false)
  10. private String name;
  11. @Column(nullable = false)
  12. private String state;
  13. // ... additional members, often include @OneToMany mappings
  14. protected City() {
  15. // no-args constructor required by JPA spec
  16. // this one is protected since it shouldn't be used directly
  17. }
  18. public City(String name, String state) {
  19. this.name = name;
  20. this.state = state;
  21. }
  22. public String getName() {
  23. return this.name;
  24. }
  25. public String getState() {
  26. return this.state;
  27. }
  28. // ... etc
  29. }
您可以使用@EntityScan注释来自定义实体扫描位置。请参阅“ howto.html ”方法。

11.3.2。Spring Data JPA存储库

Spring Data JPA存储库是可以定义以访问数据的接口。JPA查询是根据您的方法名称自动创建的。例如,一个CityRepository接口可能声明了findAllByState(String state)一种查找给定州所有城市的方法。
对于更复杂的查询,您可以使用Spring Data的Query注释对方法进行注释。
Spring Data存储库通常从RepositoryCrudRepository接口扩展。如果您使用自动配置,则会从包含主配置类(用@EnableAutoConfiguration或注释的主配置类)的软件包中搜索存储库@SpringBootApplication
以下示例显示了典型的Spring Data存储库接口定义:

  1. package com.example.myapp.domain;
  2. import org.springframework.data.domain.*;
  3. import org.springframework.data.repository.*;
  4. public interface CityRepository extends Repository<City, Long> {
  5. Page<City> findAll(Pageable pageable);
  6. City findByNameAndStateAllIgnoringCase(String name, String state);
  7. }

Spring Data JPA存储库支持三种不同的引导模式:默认,延迟和延迟。要启用延迟引导或延迟引导,请将spring.data.jpa.repositories.bootstrap-mode属性分别设置为deferredlazy。当使用延迟或懒惰引导时,自动配置的EntityManagerFactoryBuilder将使用上下文的AsyncTaskExecutor(如果有)作为引导执行器。如果存在多个,applicationTaskExecutor将使用一个命名的。

使用延迟或延迟引导时,请确保在应用程序上下文引导阶段之后,延迟对JPA基础结构的任何访问。
我们几乎没有刮过Spring Data JPA的表面。有关完整的详细信息,请参见Spring Data JPA参考文档

11.3.3。创建和删除JPA数据库

默认情况下,当您使用嵌入式数据库(H2,HSQL或Derby)时,才会自动创建JPA数据库。您可以使用spring.jpa.*属性来显式配置JPA设置。例如,要创建和删除表,可以将以下行添加到中application.properties
spring.jpa.hibernate.ddl-auto =创建-放置

Hibernate自己的内部属性名称是(如果您记得更好)hibernate.hbm2ddl.auto。您可以通过使用spring.jpa.properties.*(与其他Hibernate本机属性一起)设置它(将前缀添加到实体管理器之前先删除前缀)。下面的行显示了为Hibernate设置JPA属性的示例:

spring.jpa.properties.hibernate.globally_quoted_identifiers = true
在前面的示例中的线穿过的一个值truehibernate.globally_quoted_identifiers属性设置为休眠实体管理器。
默认情况下,DDL执行(或验证)推迟到ApplicationContext开始执行之前。还有一个spring.jpa.generate-ddl标志,但是如果激活了Hibernate自动配置,则不会使用它,因为ddl-auto设置更细粒度。

11.3.4。在视图中打开EntityManager

如果您正在运行Web应用程序,则默认情况下,Spring Boot注册OpenEntityManagerInViewInterceptor以应用“在视图中打开EntityManager”模式,以允许在Web视图中进行延迟加载。如果你不希望这种行为,你应该设置spring.jpa.open-in-viewfalseapplication.properties

11.4。Spring Data JDBC

Spring Data包括对JDBC的存储库支持,并将自动为上的方法生成SQL CrudRepository。对于更高级的查询,@Query提供了注释。
当必要的依赖项位于类路径上时,Spring Boot将自动配置Spring Data的JDBC存储库。可以将它们添加到您的项目中,而只需依赖于spring-boot-starter-data-jdbc。如有必要,您可以通过向应用程序中添加@EnableJdbcRepositories注释或JdbcConfiguration子类来控制Spring Data JDBC的配置。

有关Spring Data JDBC的完整详细信息,请参考参考文档

11.5。使用H2的Web控制台

H2数据库提供了一个基于浏览器的控制台是春天开机都能自动为您配置。满足以下条件时,将自动配置控制台:

  • 您正在开发基于servlet的Web应用程序。
  • com.h2database:h2 在类路径上。
  • 您正在使用Spring Boot的开发人员工具
    | | 如果您不使用Spring Boot的开发人员工具,但仍想使用H2的控制台,则可以将spring.h2.console.enabled属性配置为true。 | | :—-: | —- |
H2控制台仅在开发期间使用,因此您应注意确保spring.h2.console.enabled不在true生产环境中使用。

11.5.1。更改H2控制台的路径

默认情况下,控制台位于/h2-console。您可以使用spring.h2.console.path属性来自定义控制台的路径。

11.6。使用jOOQ

jOOQ面向对象查询(jOOQ)是Data Geekery的流行产品,它可以从数据库中生成Java代码,并允许您通过其流畅的API来构建类型安全的SQL查询。商业版和开源版都可以与Spring Boot一起使用。

11.6.1。代码生成

为了使用jOOQ类型安全查询,您需要从数据库架构中生成Java类。您可以按照jOOQ用户手册中的说明进行操作。如果您使用jooq-codegen-maven插件,并且还使用spring-boot-starter-parent“父POM”,则可以安全地忽略插件的<version>标签。您还可以使用Spring Boot定义的版本变量(例如h2.version)来声明插件的数据库依赖关系。以下清单显示了一个示例:

  1. <plugin>
  2. <groupId>org.jooq</groupId>
  3. <artifactId>jooq-codegen-maven</artifactId>
  4. <executions>
  5. ...
  6. </executions>
  7. <dependencies>
  8. <dependency>
  9. <groupId>com.h2database</groupId>
  10. <artifactId>h2</artifactId>
  11. <version>${h2.version}</version>
  12. </dependency>
  13. </dependencies>
  14. <configuration>
  15. <jdbc>
  16. <driver>org.h2.Driver</driver>
  17. <url>jdbc:h2:~/yourdatabase</url>
  18. </jdbc>
  19. <generator>
  20. ...
  21. </generator>
  22. </configuration>
  23. </plugin>

11.6.2。使用DSLContext

jOOQ提供的流畅的API通过该org.jooq.DSLContext接口启动。Spring Boot将a自动配置DSLContext为Spring Bean并将其连接到您的应用程序DataSource。要使用DSLContext,可以使用@Autowire它,如以下示例所示:

  1. @Component
  2. public class JooqExample implements CommandLineRunner {
  3. private final DSLContext create;
  4. @Autowired
  5. public JooqExample(DSLContext dslContext) {
  6. this.create = dslContext;
  7. }
  8. }
jOOQ手册倾向于使用名为的变量create来保存DSLContext

然后,您可以使用DSLContext构造查询,如以下示例所示:

  1. public List<GregorianCalendar> authorsBornAfter1980() {
  2. return this.create.selectFrom(AUTHOR)
  3. .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
  4. .fetch(AUTHOR.DATE_OF_BIRTH);
  5. }

11.6.3。jOOQ SQL方言

除非spring.jooq.sql-dialect配置了该属性,否则Spring Boot会确定要用于您的数据源的SQL语言。如果Spring Boot无法检测到方言,则使用DEFAULT

Spring Boot只能自动配置开源版本的jOOQ支持的方言。

11.6.4。定制jOOQ

通过定义自己的@Bean定义(可以在Configuration创建jOOQ时使用)可以实现更高级的自定义。您可以为以下jOOQ类型定义bean:

  • ConnectionProvider
  • ExecutorProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordUnmapperProvider
  • Settings
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider
  • TransactionListenerProvider

org.jooq.Configuration @Bean如果要完全控制jOOQ配置,也可以创建自己的。

11.7。使用R2DBC

响应式关系数据库连接(R2DBC)项目将响应式编程API引入关系数据库。R2DBCio.r2dbc.spi.Connection提供了使用非阻塞数据库连接的标准方法。连接是通过来提供的ConnectionFactoryDataSource与jdbc相似。
ConnectionFactory配置由中的外部配置属性控制spring.r2dbc.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. r2dbc:
  3. url: "r2dbc:postgresql://localhost/test"
  4. username: "dbuser"
  5. password: "dbpass"
您不需要指定驱动程序类名称,因为Spring Boot从R2DBC的Connection Factory发现中获取驱动程序。
至少应提供网址。在URL中指定的信息优先于个人的特性,即nameusernamepassword和池选项。
“操作方法”部分包括有关如何初始化数据库的部分

要自定义由a创建的连接ConnectionFactory,即设置不需要(或无法)在中央数据库配置中配置的特定参数,可以使用ConnectionFactoryOptionsBuilderCustomizer @Bean。以下示例显示了如何从应用程序配置中获取其余选项的同时手动覆盖数据库端口:

  1. @Bean
  2. public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
  3. return (builder) -> builder.option(PORT, 5432);
  4. }

以下示例显示了如何设置一些PostgreSQL连接选项:

  1. @Bean
  2. public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
  3. Map<String, String> options = new HashMap<>();
  4. options.put("lock_timeout", "30s");
  5. options.put("statement_timeout", "60s");
  6. return (builder) -> builder.option(OPTIONS, options);
  7. }

ConnectionFactorybean可用时,常规JDBCDataSource自动配置将退出。如果要保留JDBCDataSource自动配置,并且对在反应性应用程序中使用阻塞JDBC API的风险感到满意,请在应用程序中添加@Import(DataSourceAutoConfiguration.class)一个@Configuration类以重新启用它。

11.7.1。嵌入式数据库支持

JDBC支持类似,Spring Boot可以自动配置嵌入式数据库以进行响应式使用。您无需提供任何连接URL。您只需要包括要使用的嵌入式数据库的构建依赖关系,如以下示例所示:

  1. <dependency>
  2. <groupId>io.r2dbc</groupId>
  3. <artifactId>r2dbc-h2</artifactId>
  4. <scope>runtime</scope>
  5. </dependency>
如果您在测试中使用此功能,则可能会注意到,整个测试套件将重复使用同一数据库,而不管您使用的应用程序上下文有多少。如果要确保每个上下文都有一个单独的嵌入式数据库,则应设置spring.r2dbc.generate-unique-nametrue

11.7.2。使用DatabaseClient

一个DatabaseClientbean是自动配置,你可以@Autowire直接到自己的豆类,如下面的例子:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.data.r2dbc.function.DatabaseClient;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class MyBean {
  6. private final DatabaseClient databaseClient;
  7. @Autowired
  8. public MyBean(DatabaseClient databaseClient) {
  9. this.databaseClient = databaseClient;
  10. }
  11. // ...
  12. }

11.7.3。Spring Data R2DBC存储库

Spring Data R2DBC存储库是可以定义以访问数据的接口。查询是根据您的方法名称自动创建的。例如,一个CityRepository接口可能声明了findAllByState(String state)一种查找给定州所有城市的方法。
对于更复杂的查询,您可以使用Spring Data的Query注释对方法进行注释。
Spring Data存储库通常从RepositoryCrudRepository接口扩展。如果您使用自动配置,则会从包含主配置类(用@EnableAutoConfiguration或注释的主配置类)的软件包中搜索存储库@SpringBootApplication
以下示例显示了典型的Spring Data存储库接口定义:

  1. package com.example.myapp.domain;
  2. import org.springframework.data.domain.*;
  3. import org.springframework.data.repository.*;
  4. import reactor.core.publisher.Mono;
  5. public interface CityRepository extends Repository<City, Long> {
  6. Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);
  7. }
我们几乎没有刮过Spring Data R2DBC的表面。有关完整的详细信息,请参见Spring Data R2DBC参考文档

12.使用NoSQL技术

Spring Data提供了其他项目,可帮助您访问各种NoSQL技术,包括:

Spring Boot为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase和LDAP提供自动配置。您可以使用其他项目,但是必须自己配置它们。请参阅spring.io/projects/spring-data上的相应参考文档。

12.1。雷迪斯

Redis是一个缓存,消息代理和功能丰富的键值存储。Spring Boot为LettuceJedis客户端库以及Spring Data Redis提供的最基本的抽象提供了基本的自动配置。
有一个spring-boot-starter-data-redis“启动器”可以方便地收集依赖关系。默认情况下,它使用Lettuce。该启动程序可以处理传统应用程序和响应式应用程序。

我们还提供了spring-boot-starter-data-redis-reactive“入门级”软件,可与其他商店保持一致,并提供响应性支持。

12.1.1。连接到Redis

您可以像注入其他任何Spring Bean一样注入自动配置的RedisConnectionFactoryStringRedisTemplate或VanillaRedisTemplate实例。默认情况下,该实例尝试在以下位置连接到Redis服务器localhost:6379。下面的清单显示了这种Bean的示例:

  1. @Component
  2. public class MyBean {
  3. private StringRedisTemplate template;
  4. @Autowired
  5. public MyBean(StringRedisTemplate template) {
  6. this.template = template;
  7. }
  8. // ...
  9. }
您还可以注册任意数量的Bean,以实现LettuceClientConfigurationBuilderCustomizer更高级的自定义。如果您使用Jedis,JedisClientConfigurationBuilderCustomizer也可以使用。

如果您添加自己@Bean的任何一种自动配置类型,它将替换默认类型(除非是RedisTemplate,当排除基于Bean名称redisTemplate而不是其类型时为)。默认情况下,如果commons-pool2在类路径上,则会得到一个池化连接工厂。

12.2。MongoDB

MongoDB是一个开源NoSQL文档数据库,它使用类似JSON的架构而不是传统的基于表的关系数据。Spring Boot为MongoDB的使用提供了许多便利,包括spring-boot-starter-data-mongodbspring-boot-starter-data-mongodb-reactiveStarters。

12.2.1。连接到MongoDB数据库

要访问MongoDB数据库,可以注入自动配置的org.springframework.data.mongodb.MongoDatabaseFactory。默认情况下,该实例尝试通过连接到MongoDB服务器mongodb://localhost/test。以下示例显示了如何连接到MongoDB数据库:

  1. import org.springframework.data.mongodb.MongoDatabaseFactory;
  2. import com.mongodb.client.MongoDatabase;
  3. @Component
  4. public class MyBean {
  5. private final MongoDatabaseFactory mongo;
  6. @Autowired
  7. public MyBean(MongoDatabaseFactory mongo) {
  8. this.mongo = mongo;
  9. }
  10. // ...
  11. public void example() {
  12. MongoDatabase db = mongo.getMongoDatabase();
  13. // ...
  14. }
  15. }

如果定义了自己的MongoClient,它将用于自动配置合适的MongoDatabaseFactory
自动配置MongoClient是使用MongoClientSettingsBean创建的。如果定义了自己的MongoClientSettings,则无需修改即可使用它,并且spring.data.mongodb属性将被忽略。否则,MongoClientSettings将自动配置a并对其spring.data.mongodb应用属性。无论哪种情况,都可以声明一个或多个MongoClientSettingsBuilderCustomizerbean来微调MongoClientSettings配置。每个都将与MongoClientSettings.Builder用于构建的依次调用MongoClientSettings
您可以设置spring.data.mongodb.uri属性以更改URL并配置其他设置,例如副本集,如以下示例所示:

  1. spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test

或者,您可以使用离散属性指定连接详细信息。例如,您可以在中声明以下设置application.properties
特性
Yaml

  1. spring:
  2. data:
  3. mongodb:
  4. host: "mongoserver.example.com"
  5. port: 27017
  6. database: "test"
  7. username: "user"
  8. password: "secret"
如果spring.data.mongodb.port未指定,27017则使用默认值。您可以从前面显示的示例中删除此行。
如果您不使用Spring Data MongoDB,则可以注入一个MongoClientbean而不是使用MongoDatabaseFactory。如果您想完全控制建立MongoDB连接的方式,也可以声明自己的MongoDatabaseFactoryMongoClientbean。
如果使用反应性驱动程序,则SSL需要Netty。如果Netty可用并且尚未自定义要使用的工厂,则自动配置会自动配置该工厂。

12.2.2。MongoTemplate

Spring Data MongoDB提供了一个MongoTemplate与Spring的设计非常相似的类JdbcTemplate。与一样JdbcTemplate,Spring Boot为您自动配置一个Bean来注入模板,如下所示:

  1. import org.springframework.data.mongodb.core.MongoTemplate;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class MyBean {
  5. private final MongoTemplate mongoTemplate;
  6. public MyBean(MongoTemplate mongoTemplate) {
  7. this.mongoTemplate = mongoTemplate;
  8. }
  9. // ...
  10. }

有关完整的详细信息,请参见MongoOperationsJavadoc

12.2.3。Spring Data MongoDB存储库

Spring Data包括对MongoDB的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动构造查询。
实际上,Spring Data JPA和Spring Data MongoDB共享相同的通用基础架构。您可以从以前的JPA示例开始,并假设它City现在是MongoDB数据类而不是JPA @Entity,它的工作方式相同,如以下示例所示:

  1. package com.example.myapp.domain;
  2. import org.springframework.data.domain.*;
  3. import org.springframework.data.repository.*;
  4. public interface CityRepository extends Repository<City, Long> {
  5. Page<City> findAll(Pageable pageable);
  6. City findByNameAndStateAllIgnoringCase(String name, String state);
  7. }
您可以使用@EntityScan注释来自定义文档扫描位置。
有关Spring Data MongoDB的完整详细信息,包括其丰富的对象映射技术,请参阅其参考文档

12.2.4。嵌入式Mongo

Spring Boot为Embedded Mongo提供自动配置。要在Spring Boot应用程序中使用它,请添加对的依赖de.flapdoodle.embed:de.flapdoodle.embed.mongo
可以通过设置spring.data.mongodb.port属性来配置Mongo侦听的端口。要使用随机分配的空闲端口,请使用值0。created MongoClientbyMongoAutoConfiguration被自动配置为使用随机分配的端口。

如果未配置自定义端口,则默认情况下,嵌入式支持会使用随机端口(而不是27017)。

如果类路径上有SLF4J,则Mongo产生的输出将自动路由到名为的记录器org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo
您可以声明自己的beanIMongodConfigIRuntimeConfigbean,以控制Mongo实例的配置和日志记录路由。可以通过声明DownloadConfigBuilderCustomizerbean来定制下载配置。

12.3。Neo4j

Neo4j是一个开源NoSQL图形数据库,它使用通过一级关系连接的节点的丰富数据模型,与传统的RDBMS方法相比,它更适合于连接的大数据。Spring Boot提供了许多使用Neo4j的便利,包括spring-boot-starter-data-neo4j“ Starter”。

12.3.1。连接到Neo4j数据库

要访问Neo4j服务器,您可以注入自动配置的org.neo4j.driver.Driver。默认情况下,实例尝试localhost:7687使用Bolt协议连接到Neo4j服务器。以下示例显示了如何注入Neo4j Driver,除其他事项外,Neo4j使您可以访问Session

  1. @Component
  2. public class MyBean {
  3. private final Driver driver;
  4. @Autowired
  5. public MyBean(Driver driver) {
  6. this.driver = driver;
  7. }
  8. // ...
  9. }

您可以使用spring.neo4j.*属性来配置驱动程序的各个方面。以下示例显示如何配置uri和凭据以使用:
特性
Yaml

  1. spring:
  2. neo4j:
  3. uri: "bolt://my-server:7687"
  4. authentication:
  5. username: "neo4j"
  6. password: "secret"

自动配置Driver是使用创建的ConfigBuilder。要微调其配置,请声明一个或多个ConfigBuilderCustomizerbean。每个都将与ConfigBuilder用于构建的依次调用Driver

12.3.2。Spring Data Neo4j存储库

Spring Data包括对Neo4j的存储库支持。有关Spring Data Neo4j的完整详细信息,请参考参考文档
Spring Data Neo4j与许多其他Spring Data模块一样,与Spring Data JPA共享公共基础结构。您可以使用前面的JPA示例,并将其定义City为Spring Data Neo4j@Node而不是JPA @Entity,并且存储库抽象以相同的方式工作,如以下示例所示:

  1. package com.example.myapp.domain;
  2. import java.util.Optional;
  3. import org.springframework.data.neo4j.repository.*;
  4. public interface CityRepository extends Neo4jRepository<City, Long> {
  5. Optional<City> findOneByNameAndState(String name, String state);
  6. }

spring-boot-starter-data-neo4j“入门”使仓库的支持以及事务管理。Spring Boot使用Neo4jTemplateReactiveNeo4jTemplatebean支持经典和反应性Neo4j存储库。当Project Reactor在类路径上可用时,反应式样式也会自动配置。
您可以通过在-bean上分别使用@EnableNeo4jRepositories和来定制位置以查找存储库和实体。@EntityScan``@Configuration

| | 在使用反应式样式的应用程序中,ReactiveTransactionManager不会自动配置a。要启用事务管理,必须在配置中定义以下Bean:``` @Bean public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver, ReactiveDatabaseSelectionProvider databaseNameProvider) { return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider); }

  1. |
  2. | :---: | --- |
  3. <a name="boot-features-solr"></a>
  4. ### 12.4。索尔
  5. [Apache Solr](https://lucene.apache.org/solr/)是一个搜索引擎。Spring Boot为Solr 5客户端库提供了基本的自动配置,并由[Spring Data Solr](https://github.com/spring-projects/spring-data-solr)在其之上提供了抽象。有一个`spring-boot-starter-data-solr`“启动器”可以方便地收集依赖关系。
  6. | | Spring Boot 2.3开始,已弃用对Spring Data Solr的支持,并将在以后的发行版中将其删除。 |
  7. | :---: | --- |
  8. <a name="boot-features-connecting-to-solr"></a>
  9. #### 12.4.1。连接到Solr
  10. 您可以像插入`SolrClient`其他任何Spring Bean一样注入自动配置的实例。默认情况下,该实例尝试连接到的服务器`[localhost:8983/solr](http://localhost:8983/solr)`。以下示例显示如何注入Solr bean

@Component public class MyBean { private SolrClient solr; @Autowired public MyBean(SolrClient solr) { this.solr = solr; } // … }

  1. 如果添加自己`@Bean`type `SolrClient`,它将替换默认值。
  2. <a name="boot-features-spring-data-solr-repositories"></a>
  3. #### 12.4.2。Spring Data Solr存储库
  4. Spring Data包括对Apache Solr的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动为您构建查询。<br />实际上,Spring Data JPASpring Data Solr共享相同的通用基础结构。您可以从以前的JPA示例开始,假设`City`现在是一个`@SolrDocument`类,而不是JPA `@Entity`,它的工作方式相同。<br />IP:有关Spring Data Solr的完整详细信息,请参阅[参考文档](https://docs.spring.io/spring-data/solr/docs/4.3.5/reference/html/)。
  5. <a name="boot-features-elasticsearch"></a>
  6. ### 12.5。弹性搜索
  7. [Elasticsearch](https://www.elastic.co/products/elasticsearch)是一个开源,分布式,RESTful搜索和分析引擎。Spring Boot为Elasticsearch提供了基本的自动配置。<br />Spring Boot支持多个客户端:
  8. - 官方Java“低级”和“高级” REST客户端<br />
  9. - `ReactiveElasticsearchClient`Spring数据Elasticsearch提供<br />
  10. Spring Boot提供了专用的“入门” `spring-boot-starter-data-elasticsearch`
  11. <a name="boot-features-connecting-to-elasticsearch-rest"></a>
  12. #### 12.5.1。使用REST客户端连接到Elasticsearch
  13. Elasticsearch附带了[两个](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html)可用于查询集群的[REST客户端](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html):“低级”客户端和“高级”客户端。Spring Boot为随附的“高级”客户端提供支持`org.elasticsearch.client:elasticsearch-rest-high-level-client`。<br />如果您对类路径具有这种依赖性,Spring Boot将自动配置并注册一个`RestHighLevelClient`默认为target的bean `[localhost:9200](http://localhost:9200/)`。您可以进一步调整`RestHighLevelClient`配置方式,如以下示例所示:<br />特性<br />Yaml

spring: elasticsearch: rest: uris: “https://search.example.com:9200“ read-timeout: “10s” username: “user” password: “secret”

  1. 您还可以注册任意数量的Bean,以实现`RestClientBuilderCustomizer`更高级的自定义。要完全控制注册,请定义一个`RestClientBuilder`bean
  2. | | 如果您的应用程序需要访问“低级” `RestClient`,则可以通过调用`client.getLowLevelClient()`自动配置来获得它`RestHighLevelClient` |
  3. | :---: | --- |
  4. <a name="boot-features-connecting-to-elasticsearch-reactive-rest"></a>
  5. #### 12.5.2。使用反应式REST客户端连接到Elasticsearch
  6. [Spring Data Elasticsearch](https://spring.io/projects/spring-data-elasticsearch)附带`ReactiveElasticsearchClient`用于以反应方式查询Elasticsearch实例。它建立在WebFlux的基础上`WebClient`,因此`spring-boot-starter-elasticsearch`和`spring-boot-starter-webflux`依赖项对于启用此支持都是有用的。<br />默认情况下,Spring Boot将自动配置并注册一个`ReactiveElasticsearchClient` target的bean `[localhost:9200](http://localhost:9200/)`。您可以进一步调整其配置,如以下示例所示:<br />特性<br />Yaml

spring: data: elasticsearch: client: reactive: endpoints: “search.example.com:9200” use-ssl: true socket-timeout: “10s” username: “user” password: “secret”

  1. 如果配置属性不够,并且您想完全控制客户端配置,则可以注册一个自定义`ClientConfiguration`bean
  2. <a name="boot-features-connecting-to-elasticsearch-spring-data"></a>
  3. #### 12.5.3。使用Spring数据连接到Elasticsearch
  4. 要连接到Elasticsearch`RestHighLevelClient`必须定义一个bean,它由Spring Boot自动配置或由应用程序手动提供(请参阅前面的部分)。有了此配置后,`ElasticsearchRestTemplate`可以像其他任何Spring bean一样注入an ,如以下示例所示:

@Component public class MyBean { private final ElasticsearchRestTemplate template; public MyBean(ElasticsearchRestTemplate template) { this.template = template; } // … }

  1. 在存在`spring-data-elasticsearch`和使用`WebClient`(通常是`spring-boot-starter-webflux`)所需的依赖关系的情况下,Spring Boot还可以自动配置[ReactiveElasticsearchClient](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-connecting-to-elasticsearch-reactive-rest)和`ReactiveElasticsearchTemplate`as bean。它们与其他REST客户端等效。
  2. <a name="boot-features-spring-data-elasticsearch-repositories"></a>
  3. #### 12.5.4。Spring Data Elasticsearch存储库
  4. Spring Data包括对Elasticsearch的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动为您构造查询。<br />实际上,Spring Data JPASpring Data Elasticsearch共享相同的通用基础架构。您可以从以前的JPA示例开始,并假设`City`现在是Elasticsearch`@Document`类而不是JPA `@Entity`,它的工作方式相同。
  5. | | 有关Spring Data Elasticsearch的完整详细信息,请[参考参考文档](https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/)。 |
  6. | :---: | --- |
  7. Spring Boot使用`ElasticsearchRestTemplate``ReactiveElasticsearchTemplate`bean支持经典和反应式Elasticsearch存储库。给定所需的依赖项,这些bean最有可能由Spring Boot自动配置。<br />如果您希望使用自己的模板来支持Elasticsearch存储库,则可以添加自己的`ElasticsearchRestTemplate``ElasticsearchOperations` `@Bean`(只要命名为)`"elasticsearchTemplate"`。同样适用于`ReactiveElasticsearchTemplate``ReactiveElasticsearchOperations`,并带有Bean名称`"reactiveElasticsearchTemplate"`。<br />您可以选择使用以下属性禁用存储库支持:<br />特性<br />Yaml

spring: data: elasticsearch: repositories: enabled: false

  1. <a name="boot-features-cassandra"></a>
  2. ### 12.6。卡桑德拉
  3. [Cassandra](https://cassandra.apache.org/)是一个开放源代码的分布式数据库管理系统,旨在处理许多商品服务器上的大量数据。Spring Boot为Cassandra提供自动配置,并由[Spring Data Cassandra](https://github.com/spring-projects/spring-data-cassandra)在其之上提供抽象。有一个`spring-boot-starter-data-cassandra`“启动器”可以方便地收集依赖关系。
  4. <a name="boot-features-connecting-to-cassandra"></a>
  5. #### 12.6.1。连接到Cassandra
  6. 您可以像使用其他任何Spring Bean一样注入自动配置`CassandraTemplate`的`CqlSession`实例或Cassandra实例。这些`spring.data.cassandra.*`属性可用于自定义连接。一般情况下,提供`keyspace-name`和`contact-points`以及本地数据中心的名称,如下面的例子:<br />特性<br />Yaml

spring: data: cassandra: keyspace-name: “mykeyspace” contact-points: “cassandrahost1:9042,cassandrahost2:9042” local-datacenter: “datacenter1”

  1. 如果所有联系人的端口都相同,则可以使用快捷方式,仅指定主机名,如以下示例所示:<br />特性<br />Yaml

spring: data: cassandra: keyspace-name: “mykeyspace” contact-points: “cassandrahost1,cassandrahost2” local-datacenter: “datacenter1”

  1. | | 这两个示例与默认端口为相同`9042`。如果需要配置端口,请使用`spring.data.cassandra.port` |
  2. | :---: | --- |
  3. | | Cassandra驱动程序具有自己的配置基础结构`application.conf`,该结构在类路径的根目录中加载。<br />Spring Boot不会查找此类文件,而是通过`spring.data.cassandra.*`名称空间提供了许多配置属性。要进行更高级的驱动程序定制,您可以注册任意数量的实现的Bean `DriverConfigLoaderBuilderCustomizer`。该`CqlSession`可与类型的豆进行定制`CqlSessionBuilderCustomizer` |
  4. | :---: | --- |
  5. | | 如果要`CqlSessionBuilder`用于创建多个`CqlSession`bean,请记住该构建器是可变的,因此请确保为每个会话注入一个新副本。 |
  6. | :---: | --- |
  7. 以下代码清单显示了如何注入Cassandra bean

@Component public class MyBean { private final CassandraTemplate template; public MyBean(CassandraTemplate template) { this.template = template; } // … }

  1. 如果添加自己`@Bean`type `CassandraTemplate`,它将替换默认值。
  2. <a name="boot-features-spring-data-cassandra-repositories"></a>
  3. #### 12.6.2。Spring Data Cassandra存储库
  4. Spring Data包括对Cassandra的基本存储库支持。当前,此功能比前面讨论的JPA存储库更受限制,需要使用来注释finder方法`@Query`
  5. | | 有关Spring Data Cassandra的完整详细信息,请[参考参考文档](https://docs.spring.io/spring-data/cassandra/docs/)。 |
  6. | :---: | --- |
  7. <a name="boot-features-couchbase"></a>
  8. ### 12.7。Couchbase
  9. [Couchbase](https://www.couchbase.com/)是一个开放源代码,分布式,多模型NoSQL面向文档的数据库,已针对交互式应用程序进行了优化。Spring Boot为Couchbase提供自动配置,并由[Spring Data Couchbase](https://github.com/spring-projects/spring-data-couchbase)在其之上提供抽象。有`spring-boot-starter-data-couchbase`和`spring-boot-starter-data-couchbase-reactive`“启动器”在一个方便的方法收集的依赖关系。
  10. <a name="boot-features-connecting-to-couchbase"></a>
  11. #### 12.7.1。连接到Couchbase
  12. 您可以`Cluster`通过添加Couchbase SDK和一些配置来获得。这些`spring.couchbase.*`属性可用于自定义连接。通常,您提供[连接字符串](https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0011-connection-string.md),用户名和密码,如以下示例所示:<br />特性<br />Yaml

spring: couchbase: connection-string: “couchbase://192.168.1.123” username: “user” password: “secret”

  1. 也可以自定义某些`ClusterEnvironment`设置。例如,以下配置更改了用于打开新`Bucket`邮件并启用SSL支持的超时:<br />特性<br />Yaml

spring: couchbase: env: timeouts: connect: “3s” ssl: key-store: “/location/of/keystore.jks” key-store-password: “secret”

  1. | | 检查`spring.couchbase.env.*`属性以获取更多详细信息。为了获得更多控制权,`ClusterEnvironmentBuilderCustomizer`可以使用一个或多个bean |
  2. | :---: | --- |
  3. <a name="boot-features-spring-data-couchbase-repositories"></a>
  4. #### 12.7.2。Spring Data Couchbase存储库
  5. Spring Data包括对Couchbase的存储库支持。有关Spring Data Couchbase的完整详细信息,请[参考参考文档](https://docs.spring.io/spring-data/couchbase/docs/4.1.5/reference/html/)。<br />您可以`CouchbaseTemplate`像使用其他任何Spring Bean一样注入自动配置的实例,前提是该`CouchbaseClientFactory`bean可用。`Cluster`如上所述,当a可用且已指定存储桶名称时,会发生这种情况:<br />特性<br />Yaml

spring: data: couchbase: bucket-name: “my-bucket”

  1. 以下示例显示了如何注入`CouchbaseTemplate`bean

@Component public class MyBean { private final CouchbaseTemplate template; @Autowired public MyBean(CouchbaseTemplate template) { this.template = template; } // … }

  1. 您可以在自己的配置中定义一些Bean,以覆盖自动配置提供的那些:
  2. - 一个`CouchbaseMappingContext` `@Bean`用的名称`couchbaseMappingContext`。<br />
  3. - 一个`CustomConversions` `@Bean`用的名称`couchbaseCustomConversions`。<br />
  4. - 一个`CouchbaseTemplate` `@Bean`用的名称`couchbaseTemplate`。<br />
  5. 为了避免在您自己的配置中对这些名称进行硬编码,您可以重复使用`BeanNames`Spring Data Couchbase提供的名称。例如,您可以自定义要使用的转换器,如下所示:

@Configuration(proxyBeanMethods = false) public class SomeConfiguration { @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS) public CustomConversions myCustomConversions() { return new CustomConversions(…); } // … }

  1. <a name="boot-features-ldap"></a>
  2. ### 12.8。LDAP
  3. [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)(轻型目录访问协议)是一种开放的,与供应商无关的行业标准应用程序协议,用于通过IP网络访问和维护分布式目录信息服务。Spring Boot为任何兼容的LDAP服务器提供自动配置,并从[UnboundID](https://ldap.com/unboundid-ldap-sdk-for-java/)支持嵌入式内存LDAP服务器。<br />LDAP抽象由[Spring Data LDAP提供](https://github.com/spring-projects/spring-data-ldap)。有一个`spring-boot-starter-data-ldap`“启动器”可以方便地收集依赖关系。
  4. <a name="boot-features-ldap-connecting"></a>
  5. #### 12.8.1。连接到LDAP服务器
  6. 要连接到LDAP服务器,请确保声明对`spring-boot-starter-data-ldap`“ Starter”的依赖`spring-ldap-core`,然后在application.properties中声明服务器的URL,如以下示例所示:<br />特性<br />Yaml

spring: ldap: urls: “ldap://myserver:1235” username: “admin” password: “secret”

  1. 如果需要自定义连接设置,则可以使用`spring.ldap.base``spring.ldap.base-environment`属性。<br />将`LdapContextSource`根据这些设置自动配置。如果`DirContextAuthenticationStrategy`bean可用,则将其与自动配置的关联`LdapContextSource`。如果您需要对其进行自定义(例如使用)`PooledContextSource`,则仍可以注入自动配置`LdapContextSource`。确保将您的定制标记`ContextSource`为,`@Primary`以便自动配置`LdapTemplate`使用它。
  2. <a name="boot-features-ldap-spring-data-repositories"></a>
  3. #### 12.8.2。Spring Data LDAP存储库
  4. Spring Data包括对LDAP的存储库支持。有关Spring Data LDAP的完整详细信息,请[参考参考文档](https://docs.spring.io/spring-data/ldap/docs/1.0.x/reference/html/)。<br />您还可以`LdapTemplate`像使用其他任何Spring Bean一样注入自动配置的实例,如以下示例所示:

@Component public class MyBean { private final LdapTemplate template; @Autowired public MyBean(LdapTemplate template) { this.template = template; } // … }

  1. <a name="boot-features-ldap-embedded"></a>
  2. #### 12.8.3。嵌入式内存LDAP服务器
  3. 出于测试目的,Spring Boot支持从[UnboundID](https://ldap.com/unboundid-ldap-sdk-for-java/)自动配置内存中的LDAP服务器。要配置服务器,请向其添加依赖项`com.unboundid:unboundid-ldapsdk`并声明一个`spring.ldap.embedded.base-dn`属性,如下所示:<br />特性<br />Yaml

spring: ldap: embedded: base-dn: “dc=spring,dc=io”

  1. | | 可以定义多个base-dn值,但是,由于专有名称通常包含逗号,因此必须使用正确的符号定义它们。<br />在yaml文件中,您可以使用yaml列表符号。在属性文件中,必须将索引包括在属性名称中:<br />特性<br />Yaml

spring.ldap.embedded.base-dn:

  • dc=spring,dc=io
  • dc=pivotal,dc=io ``` | | :—-: | —- |

默认情况下,服务器在随机端口上启动并触发常规LDAP支持。无需指定spring.ldap.urls属性。
如果schema.ldif您的类路径中有一个文件,它将用于初始化服务器。如果要从其他资源加载初始化脚本,则也可以使用该spring.ldap.embedded.ldif属性。
默认情况下,使用标准架构来验证LDIF文件。您可以通过设置spring.ldap.embedded.validation.enabled属性来完全关闭验证。如果您具有定制属性,则可以spring.ldap.embedded.validation.schema用来定义定制属性类型或对象类。

12.9。InfluxDB

InfluxDB是一个开放源代码的时间序列数据库,已优化用于在操作监视,应用程序度量,物联网传感器数据和实时分析等领域中快速,高可用性地存储和检索时间序列数据。

12.9.1。连接到InfluxDB

InfluxDB如果influxdb-java客户端位于类路径上并且设置了数据库的URL,Spring Boot会自动配置一个实例,如以下示例所示:
特性
Yaml

  1. spring:
  2. influx:
  3. url: "https://172.0.0.1:8086"

如果与InfluxDB的连接需要用户和密码,则可以相应地设置spring.influx.userspring.influx.password属性。
InfluxDB依赖OkHttp。如果需要在InfluxDB后台调整http客户端的使用,则可以注册一个InfluxDbOkHttpClientBuilderProviderbean。

13.缓存

Spring框架支持透明地向应用程序添加缓存。从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。缓存逻辑是透明应用的,不会对调用者造成任何干扰。只要通过@EnableCaching注释启用了缓存支持,Spring Boot就会自动配置缓存基础结构。

检查Spring Framework参考的相关部分以获取更多详细信息。

简而言之,要将缓存添加到服务的操作中,请在其方法中添加相关的注释,如以下示例所示:

  1. import org.springframework.cache.annotation.Cacheable;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class MathService {
  5. @Cacheable("piDecimals")
  6. public int computePiDecimal(int i) {
  7. // ...
  8. }
  9. }

本示例说明了在可能耗资巨大的操作上使用缓存的方法。在调用之前computePiDecimal,抽象将在piDecimals高速缓存中寻找与i参数匹配的条目。如果找到条目,则高速缓存中的内容会立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

您还可以@CacheResult透明地使用标准JSR-107(JCache)批注(例如)。但是,我们强烈建议您不要混合使用Spring Cache和JCache批注。

如果您不添加任何特定的缓存库,Spring Boot会自动配置一个使用内存中并发映射的简单提供程序。当需要缓存时(例如piDecimals前面的示例),此提供程序将为您创建它。实际上,不建议将简单的提供程序用于生产用途,但是它对于入门并确保您了解功能非常有用。确定要使用的缓存提供程序后,请确保阅读其文档,以了解如何配置应用程序使用的缓存。几乎所有提供程序都要求您显式配置在应用程序中使用的每个缓存。有些提供了一种自定义spring.cache.cache-names属性定义的默认缓存的方法。

也可以透明地更新或从缓存中逐出数据。

13.1。支持的缓存提供程序

缓存抽象不提供实际的存储,而是依赖于org.springframework.cache.Cacheorg.springframework.cache.CacheManager接口实现的抽象。
如果尚未定义类型CacheManagerCacheResolver名称的bean cacheResolver(请参阅参考资料CachingConfigurer),Spring Boot会尝试检测以下提供程序(按指示的顺序):

  1. 通用的
  2. JCache(JSR-107)(EhCache 3,Hazelcast,Infinispan等)
  3. EhCache 2.x
  4. 淡褐色
  5. Infinispan
  6. Couchbase
  7. 雷迪斯
  8. 咖啡因
  9. 简单的
    | | 也可以通过设置属性来强制特定的缓存提供程序spring.cache.type。如果您需要在某些环境(例如测试)中完全禁用缓存,请使用此属性。 | | :—-: | —- |
使用spring-boot-starter-cache“入门”可以快速添加基本缓存依赖项。起动器带进来spring-context-support。如果您手动添加依赖项,则必须包括spring-context-support才能使用JCache,EhCache 2.x或Caffeine支持。

如果CacheManagerSpring Boot自动配置了,您可以通过公开实现该CacheManagerCustomizer接口的bean,在完全初始化之前进一步调整其配置。下面的示例设置一个标志,指示null应将值向下传递到基础映射:

  1. @Bean
  2. public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
  3. return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
  4. @Override
  5. public void customize(ConcurrentMapCacheManager cacheManager) {
  6. cacheManager.setAllowNullValues(false);
  7. }
  8. };
  9. }
在前面的示例中,需要进行自动配置ConcurrentMapCacheManager。如果不是这种情况(您提供了自己的配置,或者自动配置了其他缓存提供程序),则根本不会调用定制程序。您可以根据需要拥有任意数量的定制程序,也可以使用@Order或对其进行排序Ordered

13.1.1。通用的

如果上下文定义了至少一个org.springframework.cache.Cachebean,则使用通用缓存。将CacheManager包装该类型的所有bean。

13.1.2。JCache(JSR-107)

JCache通过javax.cache.spi.CachingProvider类路径上的存在进行引导(即,类路径上存在符合JSR-107的缓存库),并且JCacheCacheManagerspring-boot-starter-cache“启动器”提供。提供了各种兼容的库,Spring Boot为Ehcache 3,Hazelcast和Infinispan提供了依赖管理。也可以添加任何其他兼容的库。
可能会出现多个提供者,在这种情况下,必须明确指定提供者。即使JSR-107标准没有强制采用标准化的方式来定义配置文件的位置,Spring Boot也会尽其所能以设置具有实现细节的缓存,如以下示例所示:
特性
Yaml

  1. # Only necessary if more than one provider is present
  2. spring:
  3. cache:
  4. jcache:
  5. provider: "com.acme.MyCachingProvider"
  6. config: "classpath:acme.xml"
当缓存库同时提供本机实现和JSR-107支持时,Spring Boot会首选JSR-107支持,因此,如果切换到其他JSR-107实现,则可以使用相同的功能。
Spring Boot对Hazelcast具有常规支持。如果单个HazelcastInstance可用,则CacheManager除非spring.cache.jcache.config指定了该属性,否则也会自动将其重新使用。

有两种方法可以自定义基础javax.cache.cacheManager

  • 可以在启动时通过设置spring.cache.cache-names属性来创建缓存。如果定义了定制javax.cache.configuration.Configurationbean,则将其用于定制它们。
  • org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer使用的引用调用beanCacheManager进行完全定制。
    | | 如果javax.cache.CacheManager定义了标准bean,则它将自动包装在org.springframework.cache.CacheManager抽象期望的实现中。不再对其应用定制。 | | :—-: | —- |

13.1.3。EhCache 2.x

如果ehcache.xml可以在类路径的根目录找到名为的文件,则使用EhCache2.x。如果找到EhCache 2.x,则使用“启动器”EhCacheCacheManager提供的spring-boot-starter-cache启动程序引导缓存管理器。也可以提供备用配置文件,如以下示例所示:
特性
Yaml

  1. spring:
  2. cache:
  3. ehcache:
  4. config: "classpath:config/another-config.xml"

13.1.4。淡褐色

Spring Boot对Hazelcast具有常规支持。如果HazelcastInstance已经自动配置了,则会自动将其包装在中CacheManager

13.1.5。Infinispan

Infinispan没有默认配置文件位置,因此必须明确指定它。否则,将使用默认的引导程序。
特性
Yaml

  1. spring:
  2. cache:
  3. infinispan:
  4. config: "infinispan.xml"

可以在启动时通过设置spring.cache.cache-names属性来创建缓存。如果定义了定制ConfigurationBuilderbean,则将其用于定制高速缓存。

Spring Boot对Infinispan的支持仅限于嵌入式模式,并且非常基础。如果您需要更多选择,则应该使用官方的Infinispan Spring Boot启动程序。有关更多详细信息,请参见Infinispan的文档

13.1.6。Couchbase

如果Spring Data Couchbase可用并且已配置Couchbase ,CouchbaseCacheManager则会自动配置a。可以通过设置spring.cache.cache-names属性在启动时创建其他高速缓存,并且可以使用spring.cache.couchbase.*属性配置高速缓存默认值。例如,以下配置创建cache1cache2缓存条目的到期时间为10分钟:
特性
Yaml

  1. spring:
  2. cache:
  3. cache-names: "cache1,cache2"
  4. couchbase:
  5. expiration: "10m"

如果需要对配置进行更多控制,请考虑注册CouchbaseCacheManagerBuilderCustomizerBean。以下示例显示了一个定制程序,它为cache1和配置特定的条目到期时间cache2

  1. @Bean
  2. public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
  3. return (builder) -> builder
  4. .withCacheConfiguration("cache1",
  5. CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
  6. .withCacheConfiguration("cache2",
  7. CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));
  8. }

13.1.7。雷迪斯

如果Redis可用并已配置,RedisCacheManager则会自动配置a。可以通过设置spring.cache.cache-names属性在启动时创建其他高速缓存,并且可以使用spring.cache.redis.*属性配置高速缓存默认值。例如,以下配置创建cache1cache2缓存的_生存时间为_10分钟:
特性
Yaml

  1. spring:
  2. cache:
  3. cache-names: "cache1,cache2"
  4. redis:
  5. time-to-live: "10m"
默认情况下,会添加密钥前缀,这样,如果两个单独的缓存使用相同的密钥,则Redis不会有重叠的密钥,也不会返回无效值。如果您创建自己的,我们强烈建议将此设置保持启用状态RedisCacheManager
您可以通过添加RedisCacheConfiguration @Bean自己的a来完全控制默认配置。如果您要自定义默认的序列化策略,这将很有用。

如果需要对配置进行更多控制,请考虑注册RedisCacheManagerBuilderCustomizerBean。以下示例显示了一个定制器,该定制器为cache1和配置生存的特定时间cache2

  1. @Bean
  2. public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
  3. return (builder) -> builder
  4. .withCacheConfiguration("cache1",
  5. RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
  6. .withCacheConfiguration("cache2",
  7. RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));
  8. }

13.1.8。咖啡因

Caffeine是对Guava缓存的Java 8重写,它取代了对Guava的支持。如果存在咖啡因,CaffeineCacheManager则将spring-boot-starter-cache自动配置(由“入门”提供)。缓存可以在启动时通过设置spring.cache.cache-names属性来创建,并且可以通过以下方式之一(按指示的顺序)进行自定义:

  1. 缓存规范由 spring.cache.caffeine.spec
  2. com.github.benmanes.caffeine.cache.CaffeineSpec定义了一个bean
  3. com.github.benmanes.caffeine.cache.Caffeine定义了一个bean

例如,以下配置创建cache1cache2缓存的最大大小为500,_生存时间为_10分钟
特性
Yaml

  1. spring:
  2. cache:
  3. cache-names: "cache1,cache2"
  4. caffeine:
  5. spec: "maximumSize=500,expireAfterAccess=600s"

如果com.github.benmanes.caffeine.cache.CacheLoader定义了bean,它将自动与关联CaffeineCacheManager。由于CacheLoader将会与缓存管理器管理的所有缓存相关联,因此必须将其定义为CacheLoader<Object, Object>。自动配置将忽略任何其他通用类型。

13.1.9。简单的

如果找不到其他提供者,ConcurrentHashMap则配置使用作为缓存存储的简单实现。如果您的应用程序中不存在任何缓存库,则这是默认设置。默认情况下,将根据需要创建缓存,但是您可以通过设置cache-names属性来限制可用缓存的列表。例如,如果只需要cache1cache2缓存,则按cache-names如下所示设置属性:
特性
Yaml

  1. spring:
  2. cache:
  3. cache-names: "cache1,cache2"

如果这样做,并且您的应用程序使用了未列出的缓存,那么当需要该缓存时,它将在运行时失败,但在启动时失败。这类似于使用未声明的缓存时“实际”缓存提供程序的行为。

13.1.10。没有

@EnableCaching配置中存在时,也将期望使用合适的缓存配置。如果需要在某些环境中完全禁用缓存,请强制缓存类型none使用无操作实现,如以下示例所示:
特性
Yaml

  1. spring:
  2. cache:
  3. type: "none"

14.消息传递

从简化的JMS API使用JmsTemplate到完整的基础结构以异步接收消息,Spring框架为与消息传递系统集成提供了广泛的支持。Spring AMQP为高级消息队列协议提供了类似的功能集。Spring Boot还为RabbitTemplate和RabbitMQ提供了自动配置选项。Spring WebSocket本身包括对STOMP消息的支持,而Spring Boot通过启动程序和少量的自动配置对此提供了支持。Spring Boot还支持Apache Kafka。

14.1。JMS

javax.jms.ConnectionFactory界面提供了一种javax.jms.Connection用于创建与JMS代理进行交互的的标准方法。尽管Spring需要ConnectionFactory使用JMS来工作,但是您通常不需要自己直接使用它,而可以依赖于更高级别的消息抽象。(有关详细信息,请参见Spring Framework参考文档的相关部分。)Spring Boot还会自动配置必要的基础结构来发送和接收消息。

14.1.1。ActiveMQ支持

ActiveMQ在类路径中可用时,Spring Boot也可以配置ConnectionFactory。如果存在代理,则将自动启动和配置嵌入式代理(前提是未通过配置指定代理URL)。

如果使用spring-boot-starter-activemq,则提供了连接或嵌入ActiveMQ实例的必要依赖关系,以及与JMS集成的Spring基础结构。

ActiveMQ配置由中的外部配置属性控制spring.activemq.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. activemq:
  3. broker-url: "tcp://192.168.1.210:9876"
  4. user: "admin"
  5. password: "secret"

默认情况下,a用合理的设置CachingConnectionFactory包装本机ConnectionFactory,您可以通过以下方式中的外部配置属性来控制这些设置spring.jms.*
特性
Yaml

  1. spring:
  2. jms:
  3. cache:
  4. session-cache-size: 5

如果您希望使用本机池,则可以通过向其添加依赖项org.messaginghub:pooled-jms并进行相应的配置来实现JmsPoolConnectionFactory,如以下示例所示:
特性
Yaml

  1. spring:
  2. activemq:
  3. pool:
  4. enabled: true
  5. max-connections: 50
请参阅ActiveMQProperties以获取更多受支持的选项。您还可以注册任意数量的Bean,以实现ActiveMQConnectionFactoryCustomizer更高级的自定义。

默认情况下,ActiveMQ将创建一个目的地(如果目的地尚不存在),以便根据其提供的名称来解析目的地。

14.1.2。ActiveMQ Artemis支持

当Spring BootConnectionFactory检测到ActiveMQ Artemis在类路径中可用时,可以自动配置a 。如果存在代理,则将自动启动和配置嵌入式代理(除非已明确设置mode属性)。支持的模式是embedded(明确表示需要嵌入式代理,并且如果类路径上不存在代理,则会发生错误),以及native(使用netty传输协议连接到代理)。配置后者后,Spring BootConnectionFactory将使用默认设置配置一个连接到在本地计算机上运行的代理的代理。

如果使用spring-boot-starter-artemis,则将提供连接到现有ActiveMQ Artemis实例所需的依赖项,以及提供与JMS集成的Spring基础结构。添加org.apache.activemq:artemis-jms-server到您的应用程序可以让您使用嵌入式模式。

ActiveMQ Artemis配置由中的外部配置属性控制spring.artemis.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. artemis:
  3. mode: native
  4. host: "192.168.1.210"
  5. port: 9876
  6. user: "admin"
  7. password: "secret"

嵌入代理时,可以选择是否要启用持久性并列出应使其可用的目的地。可以将它们指定为以逗号分隔的列表,以使用默认选项创建它们,或者您可以分别为高级队列和主题配置定义类型为org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration或的bean org.apache.activemq.artemis.jms.server.config.TopicConfiguration
默认情况下,a用合理的设置CachingConnectionFactory包装本机ConnectionFactory,您可以通过以下方式中的外部配置属性来控制这些设置spring.jms.*
特性
Yaml

  1. spring:
  2. jms:
  3. cache:
  4. session-cache-size: 5

如果您希望使用本机池,则可以通过向其添加依赖项org.messaginghub:pooled-jms并进行相应的配置来实现JmsPoolConnectionFactory,如以下示例所示:
特性
Yaml

  1. spring:
  2. artemis:
  3. pool:
  4. enabled: true
  5. max-connections: 50

请参阅ArtemisProperties以获取更多受支持的选项。
不涉及JNDI查找,并且使用nameArtemis配置中的属性或通过配置提供的名称来根据目的地名称解析目的地。

14.1.3。使用JNDI ConnectionFactory

如果您正在应用程序服务器中运行应用程序,则Spring Boot会尝试ConnectionFactory使用JNDI查找JMS 。默认情况下,java:/JmsXAjava:/XAConnectionFactory处于选中状态。spring.jms.jndi-name如果需要指定替代位置,则可以使用该属性,如以下示例所示:
特性
Yaml

  1. spring:
  2. jms:
  3. jndi-name: "java:/MyConnectionFactory"

14.1.4。发送信息

SpringJmsTemplate是自动配置的,您可以将其直接自动连接到您自己的bean中,如以下示例所示:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jms.core.JmsTemplate;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class MyBean {
  6. private final JmsTemplate jmsTemplate;
  7. @Autowired
  8. public MyBean(JmsTemplate jmsTemplate) {
  9. this.jmsTemplate = jmsTemplate;
  10. }
  11. // ...
  12. }
JmsMessagingTemplate可以类似的方式注入。如果定义了aDestinationResolverMessageConverterbean,则将其自动关联到auto-configured JmsTemplate

14.1.5。接收讯息

存在JMS基础结构时,可以对任何bean进行注释@JmsListener以创建侦听器端点。如果JmsListenerContainerFactory未定义,则会自动配置一个默认值。如果定义了aDestinationResolverMessageConverterbean,它将自动关联到默认工厂。
默认情况下,默认工厂是事务性的。如果您在JtaTransactionManager存在a的基础结构中运行,则默认情况下它将与侦听器容器关联。如果不是,sessionTransacted则启用该标志。在后一种情况下,可以通过添加@Transactional侦听器方法(或其委托)将本地数据存储事务与传入消息的处理相关联。这样可以确保本地事务完成后,传入消息得到确认。这还包括发送已在同一JMS会话上执行的响应消息。
以下组件在someQueue目标上创建侦听器端点:

  1. @Component
  2. public class MyBean {
  3. @JmsListener(destination = "someQueue")
  4. public void processMessage(String content) {
  5. // ...
  6. }
  7. }
有关更多详细信息,请参见的Javadoc@EnableJms

如果您需要创建更多JmsListenerContainerFactory实例,或者想要覆盖默认实例,Spring Boot提供了一个DefaultJmsListenerContainerFactoryConfigurer可用于初始化的实例,该实例具有DefaultJmsListenerContainerFactory与自动配置的实例相同的设置。
例如,以下示例公开了另一个使用特定工厂的工厂MessageConverter

  1. @Configuration(proxyBeanMethods = false)
  2. static class JmsConfiguration {
  3. @Bean
  4. public DefaultJmsListenerContainerFactory myFactory(
  5. DefaultJmsListenerContainerFactoryConfigurer configurer) {
  6. DefaultJmsListenerContainerFactory factory =
  7. new DefaultJmsListenerContainerFactory();
  8. configurer.configure(factory, connectionFactory());
  9. factory.setMessageConverter(myMessageConverter());
  10. return factory;
  11. }
  12. }

然后,您可以@JmsListener按以下任何带注释的方法使用工厂:

  1. @Component
  2. public class MyBean {
  3. @JmsListener(destination = "someQueue", containerFactory="myFactory")
  4. public void processMessage(String content) {
  5. // ...
  6. }
  7. }

14.2。AMQP

高级消息队列协议(AMQP)是面向消息中间件的与平台无关的有线级别协议。Spring AMQP项目将Spring的核心概念应用于基于AMQP的消息传递解决方案的开发。Spring Boot为通过RabbitMQ使用AMQP提供了许多便利,包括spring-boot-starter-amqp“启动器”。

14.2.1。RabbitMQ支持

RabbitMQ是基于AMQP协议的轻型,可靠,可伸缩和便携式消息代理。Spring用于RabbitMQ通过AMQP协议进行通信。
RabbitMQ配置由中的外部配置属性控制spring.rabbitmq.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. rabbitmq:
  3. host: "localhost"
  4. port: 5672
  5. username: "admin"
  6. password: "secret"

另外,您可以使用addresses属性配置相同的连接:
特性
Yaml

  1. spring:
  2. rabbitmq:
  3. addresses: "amqp://admin:secret@localhost"
以这种方式指定地址时,hostport属性将被忽略。如果地址使用amqps协议,则会自动启用SSL支持。

如果ConnectionNameStrategy上下文中存在bean,它将自动用于命名由auto-configured创建的连接ConnectionFactory。请参阅RabbitProperties以获取更多受支持的选项。

有关更多详细信息请参阅了解RabbitMQ使用的协议AMQP

14.2.2。发送信息

Spring的AmqpTemplateAmqpAdmin是自动配置的,您可以将它们直接自动连接到自己的bean中,如以下示例所示:

  1. import org.springframework.amqp.core.AmqpAdmin;
  2. import org.springframework.amqp.core.AmqpTemplate;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Component;
  5. @Component
  6. public class MyBean {
  7. private final AmqpAdmin amqpAdmin;
  8. private final AmqpTemplate amqpTemplate;
  9. @Autowired
  10. public MyBean(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {
  11. this.amqpAdmin = amqpAdmin;
  12. this.amqpTemplate = amqpTemplate;
  13. }
  14. // ...
  15. }
RabbitMessagingTemplate可以类似的方式注入。如果MessageConverter定义了bean,它将自动关联到auto-configured AmqpTemplate

如有必要,任何org.springframework.amqp.core.Queue定义为bean的对象都会自动用于在RabbitMQ实例上声明相应的队列。
要重试操作,您可以启用重试AmqpTemplate(例如,在代理连接丢失的情况下):
特性
Yaml

  1. spring:
  2. rabbitmq:
  3. template:
  4. retry:
  5. enabled: true
  6. initial-interval: "2s"

默认情况下,重试是禁用的。您也可以RetryTemplate通过声明RabbitRetryTemplateCustomizerbean来以编程方式自定义。
如果您需要创建更多RabbitTemplate实例,或者想覆盖默认实例,Spring Boot提供了一个RabbitTemplateConfigurerbean,您可以使用它初始化RabbitTemplate与自动配置所使用的工厂相同的设置。

14.2.3。接收讯息

存在Rabbit基础结构时,可以对任何bean进行注释@RabbitListener以创建侦听器端点。如果RabbitListenerContainerFactory未定义,SimpleRabbitListenerContainerFactory则会自动配置一个默认值,您可以使用该spring.rabbitmq.listener.type属性切换到直接容器。如果定义了aMessageConverterMessageRecovererbean,它将自动与默认工厂关联。
以下示例组件在someQueue队列上创建一个侦听器端点:

  1. @Component
  2. public class MyBean {
  3. @RabbitListener(queues = "someQueue")
  4. public void processMessage(String content) {
  5. // ...
  6. }
  7. }
有关更多详细信息,请参见的Javadoc@EnableRabbit

如果您需要创建更多RabbitListenerContainerFactory实例或想要覆盖默认实例,Spring Boot提供了一个SimpleRabbitListenerContainerFactoryConfigurerDirectRabbitListenerContainerFactoryConfigurer,您可以使用SimpleRabbitListenerContainerFactoryDirectRabbitListenerContainerFactory自动配置所使用的工厂相同的设置来初始化一个和。

选择哪种容器都没有关系。这两个bean通过自动配置公开。

例如,以下配置类公开了另一个使用特定工厂的工厂MessageConverter

  1. @Configuration(proxyBeanMethods = false)
  2. static class RabbitConfiguration {
  3. @Bean
  4. public SimpleRabbitListenerContainerFactory myFactory(
  5. SimpleRabbitListenerContainerFactoryConfigurer configurer) {
  6. SimpleRabbitListenerContainerFactory factory =
  7. new SimpleRabbitListenerContainerFactory();
  8. configurer.configure(factory, connectionFactory);
  9. factory.setMessageConverter(myMessageConverter());
  10. return factory;
  11. }
  12. }

然后,您可以按任何带@RabbitListener注释的方法使用工厂,如下所示:

  1. @Component
  2. public class MyBean {
  3. @RabbitListener(queues = "someQueue", containerFactory="myFactory")
  4. public void processMessage(String content) {
  5. // ...
  6. }
  7. }

您可以启用重试来处理侦听器引发异常的情况。默认情况下RejectAndDontRequeueRecoverer使用,但是您可以定义MessageRecoverer自己的a。重试用尽后,如果将代理配置为这样做,则消息将被拒绝并被丢弃或路由到死信交换。默认情况下,重试是禁用的。您也可以RetryTemplate通过声明RabbitRetryTemplateCustomizerbean来以编程方式自定义。

默认情况下,如果禁用了重试,并且侦听器抛出异常,则会无限期地重试传递。您可以通过两种方式修改此行为:将defaultRequeueRejected属性设置为,false以便尝试进行零次重新传递,或者抛出AmqpRejectAndDontRequeueException来指示应该拒绝该消息。后者是启用重试并达到最大传递尝试次数时使用的机制。

14.3。Apache Kafka支持

通过提供spring-kafka项目的自动配置来支持Apache Kafka
Kafka配置由中的外部配置属性控制spring.kafka.*。例如,您可以在中声明以下部分application.properties
特性
Yaml

  1. spring:
  2. kafka:
  3. bootstrap-servers: "localhost:9092"
  4. consumer:
  5. group-id: "myGroup"
要在启动时创建主题,请添加类型为的Bean NewTopic。如果该主题已经存在,则将忽略Bean。

请参阅KafkaProperties以获取更多受支持的选项。

14.3.1。发送信息

SpringKafkaTemplate是自动配置的,您可以直接在自己的Bean中自动对其进行布线,如以下示例所示:

  1. @Component
  2. public class MyBean {
  3. private final KafkaTemplate kafkaTemplate;
  4. @Autowired
  5. public MyBean(KafkaTemplate kafkaTemplate) {
  6. this.kafkaTemplate = kafkaTemplate;
  7. }
  8. // ...
  9. }
如果spring.kafka.producer.transaction-id-prefix定义了属性,KafkaTransactionManager则会自动配置a。另外,如果RecordMessageConverter定义了bean,它将自动关联到auto-configured KafkaTemplate

14.3.2。接收讯息

存在Apache Kafka基础结构时,可以对任何bean进行注释@KafkaListener以创建侦听器端点。如果KafkaListenerContainerFactory尚未定义,则会使用中定义的键自动配置默认值spring.kafka.listener.*
以下组件在该someTopic主题上创建一个侦听器端点:

  1. @Component
  2. public class MyBean {
  3. @KafkaListener(topics = "someTopic")
  4. public void processMessage(String content) {
  5. // ...
  6. }
  7. }

如果KafkaTransactionManager定义了bean,它将自动关联到容器工厂。类似地,如果RecordFilterStrategyErrorHandlerAfterRollbackProcessorConsumerAwareRebalanceListener豆被定义,它被自动关联为出厂默认。
根据侦听器的类型,aRecordMessageConverterBatchMessageConverterbean与默认工厂关联。如果RecordMessageConverter对于批处理侦听器仅存在一个bean,则将其包装在中BatchMessageConverter

ChainedKafkaTransactionManager必须标记 一个自定义,@Primary因为它通常引用自动配置的KafkaTransactionManagerbean。

14.3.3。卡夫卡流

用于Apache Kafka的Spring提供了一个工厂bean来创建StreamsBuilder对象并管理其流的生命周期。KafkaStreamsConfiguration只要kafka-streams在类路径上通过Spring Boot自动配置所需的bean,并通过@EnableKafkaStreams注释启用Kafka Streams 。
启用Kafka Streams意味着必须设置应用程序ID和引导服务器。可以使用来配置前者spring.kafka.streams.application-idspring.application.name如果未设置,则默认为。后者可以全局设置,也可以仅针对流覆盖。
使用专用属性可以使用几个其他属性。可以使用spring.kafka.streams.properties名称空间设置其他任意Kafka属性。另请参见其他Kafka属性
要使用工厂bean,StreamsBuilder@Bean按照以下示例所示将其连接到您的计算机中:

  1. @Configuration(proxyBeanMethods = false)
  2. @EnableKafkaStreams
  3. public static class KafkaStreamsExampleConfiguration {
  4. @Bean
  5. public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
  6. KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
  7. stream.map((k, v) -> new KeyValue<>(k, v.toUpperCase())).to("ks1Out",
  8. Produced.with(Serdes.Integer(), new JsonSerde<>()));
  9. return stream;
  10. }
  11. }

默认情况下,由StreamBuilder它创建的对象管理的流将自动启动。您可以使用spring.kafka.streams.auto-startup属性来自定义此行为。

14.3.4。卡夫卡的其他属性

自动配置支持的属性显示在appendix-application-properties.html中。请注意,在大多数情况下,这些属性(连字符或camelCase)直接映射到Apache Kafka点缀属性。有关详细信息,请参阅Apache Kafka文档。
这些属性的前几个属性适用于所有组件(生产者,使用者,管理员和流),但如果您希望使用不同的值,则可以在组件级别上指定。Apache Kafka会指定重要性为HIGH,MEDIUM或LOW的属性。Spring Boot自动配置支持所有HIGH重要性属性,一些选定的MEDIUM和LOW属性以及任何没有默认值的属性。
KafkaProperties该类直接提供了Kafka支持的属性的子集。如果希望使用不直接支持的其他属性来配置生产者或使用者,请使用以下属性:
特性
Yaml

  1. spring:
  2. kafka:
  3. properties:
  4. "[prop.one]": "first"
  5. admin:
  6. properties:
  7. "[prop.two]": "second"
  8. consumer:
  9. properties:
  10. "[prop.three]": "third"
  11. producer:
  12. properties:
  13. "[prop.four]": "fourth"
  14. streams:
  15. properties:
  16. "[prop.five]": "fifth"

这将公共prop.oneKafka属性设置为first(适用于生产者,消费者和管理员),将prop.twoadmin属性设置为second,将prop.three消费者属性设置为third,将prop.four生产者属性设置为fourth并将prop.fivestream属性设置为fifth
您还可以JsonDeserializer如下配置Spring Kafka :
特性
Yaml

  1. spring:
  2. kafka:
  3. consumer:
  4. value-deserializer: "org.springframework.kafka.support.serializer.JsonDeserializer"
  5. properties:
  6. "[spring.json.value.default.type]": "com.example.Invoice"
  7. "[spring.json.trusted.packages]": "com.example,org.acme"

同样,您可以禁用JsonSerializer发送的报头类型信息的默认行为:
特性
Yaml

  1. spring:
  2. kafka:
  3. producer:
  4. value-serializer: "org.springframework.kafka.support.serializer.JsonSerializer"
  5. properties:
  6. "[spring.json.add.type.headers]": false
以这种方式设置的属性将覆盖Spring Boot显式支持的任何配置项。

14.3.5。使用嵌入式Kafka进行测试

Spring for Apache Kafka提供了一种使用嵌入式Apache Kafka代理测试项目的便捷方法。要使用此功能,请@EmbeddedKafkaspring-kafka-test模块中用注释测试类。有关更多信息,请参阅Spring for Apache Kafka参考手册
要使Spring Boot自动配置与上述嵌入式Apache Kafka代理一起使用,您需要将嵌入式代理地址(由填充EmbeddedKafkaBroker)的系统属性重新映射到Apache Kafka的Spring Boot配置属性中。有几种方法可以做到这一点:

  • 提供系统属性以将嵌入式代理地址映射到spring.kafka.bootstrap-servers测试类中:

    1. static {
    2. System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY, "spring.kafka.bootstrap-servers");
    3. }
  • @EmbeddedKafka注释上配置属性名称:

    1. @EmbeddedKafka(topics = "someTopic",
    2. bootstrapServersProperty = "spring.kafka.bootstrap-servers")
  • 在配置属性中使用占位符:

特性
Yaml

  1. spring:
  2. kafka:
  3. bootstrap-servers: "${spring.embedded.kafka.brokers}"

15.使用RestTemplate调用REST服务

如果您需要从应用程序中调用远程REST服务,则可以使用Spring Framework的RestTemplate类。由于RestTemplate实例在使用前通常需要自定义,因此Spring Boot不提供任何单个自动配置的RestTemplatebean。但是,它会自动配置a RestTemplateBuilder,可以RestTemplate在需要时创建实例。自动配置RestTemplateBuilder可确保明智HttpMessageConverters地应用于RestTemplate实例。
以下代码显示了一个典型示例:

  1. @Service
  2. public class MyService {
  3. private final RestTemplate restTemplate;
  4. public MyService(RestTemplateBuilder restTemplateBuilder) {
  5. this.restTemplate = restTemplateBuilder.build();
  6. }
  7. public Details someRestCall(String name) {
  8. return this.restTemplate.getForObject("/{name}/details", Details.class, name);
  9. }
  10. }
RestTemplateBuilder包括许多有用的方法,可用于快速配置RestTemplate。例如,要添加BASIC身份验证支持,可以使用builder.basicAuthentication("user", "password").build()

15.1。RestTemplate自定义

有三种主要的RestTemplate自定义方法,具体取决于您希望自定义应用的范围。
为了使所有自定义的范围尽可能缩小,请注入自动配置的内容RestTemplateBuilder,然后根据需要调用其方法。每个方法调用都返回一个新RestTemplateBuilder实例,因此自定义仅影响构建器的使用。
要进行应用程序范围的附加自定义,请使用RestTemplateCustomizerBean。所有此类bean都会自动向自动配置中注册,RestTemplateBuilder并应用于自动生成的任何模板。
以下示例显示了一个定制器,该定制器为除以下之外的所有主机配置代理的使用192.168.0.5

  1. static class ProxyCustomizer implements RestTemplateCustomizer {
  2. @Override
  3. public void customize(RestTemplate restTemplate) {
  4. HttpHost proxy = new HttpHost("proxy.example.com");
  5. HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
  6. @Override
  7. public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context)
  8. throws HttpException {
  9. if (target.getHostName().equals("192.168.0.5")) {
  10. return null;
  11. }
  12. return super.determineProxy(target, request, context);
  13. }
  14. }).build();
  15. restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
  16. }
  17. }

最后,您还可以创建自己的RestTemplateBuilderbean。为防止关闭a的自动配置RestTemplateBuilder并防止使用任何RestTemplateCustomizerbean,请确保使用来配置自定义实例RestTemplateBuilderConfigurer。下面的示例展示了RestTemplateBuilderSpring Boot将自动配置的a,除了还指定了自定义连接和读取超时:

  1. @Bean
  2. public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
  3. return configurer.configure(new RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5))
  4. .setReadTimeout(Duration.ofSeconds(2));
  5. }

最极端(很少使用)的选项是在RestTemplateBuilder不使用配置程序的情况下创建自己的bean。这样做会关闭a的自动配置,RestTemplateBuilder并防止使用任何RestTemplateCustomizerbean。

16.使用WebClient调用REST服务

如果您的类路径上具有Spring WebFlux,则还可以选择WebClient用于调用远程REST服务。与相比RestTemplate,此客户具有更实用的感觉,并且完全反应灵敏。您可以在Spring Framework文档WebClient的专用部分中了解有关的更多信息。
Spring BootWebClient.Builder为您创建并预配置了一个;强烈建议将其注入您的组件中并使用它来创建WebClient实例。Spring Boot正在配置该构建器以共享HTTP资源,以与服务器相同的方式反映编解码器的设置(请参阅WebFlux HTTP编解码器自动配置),以及更多。
以下代码显示了一个典型示例:

  1. @Service
  2. public class MyService {
  3. private final WebClient webClient;
  4. public MyService(WebClient.Builder webClientBuilder) {
  5. this.webClient = webClientBuilder.baseUrl("https://example.org").build();
  6. }
  7. public Mono<Details> someRestCall(String name) {
  8. return this.webClient.get().uri("/{name}/details", name)
  9. .retrieve().bodyToMono(Details.class);
  10. }
  11. }

16.1。WebClient运行时

Spring Boot会根据应用程序类路径上可用的库自动检测ClientHttpConnector要使用哪个驱动器WebClient。目前,还支持Reactor Netty和Jetty RS客户端。
spring-boot-starter-webflux启动依赖于io.projectreactor.netty:reactor-netty默认情况下,这使服务器和客户端的实现。如果选择使用Jetty作为反应式服务器,则应在Jetty反应式HTTP客户端库上添加依赖项org.eclipse.jetty:jetty-reactive-httpclient。对服务器和客户端使用相同的技术具有优势,因为它将自动在客户端和服务器之间共享HTTP资源。
开发人员可以通过提供自定义ReactorResourceFactoryJettyResourceFactorybean来覆盖Jetty和Reactor Netty的资源配置-这将同时应用于客户端和服务器。
如果希望为客户端覆盖该选择,则可以定义自己的ClientHttpConnectorbean,并完全控制客户端配置。
您可以WebClient在Spring Framework参考文档中了解有关配置选项的更多信息。

16.2。WebClient自定义

有三种主要的WebClient自定义方法,具体取决于您希望自定义应用的范围。
为了使所有自定义的范围尽可能缩小,请注入自动配置的内容WebClient.Builder,然后根据需要调用其方法。 WebClient.Builder实例是有状态的:构建器上的任何更改都会反映在随后使用它创建的所有客户端中。如果要使用同一构建器创建多个客户端,则还可以考虑使用克隆该构建器WebClient.Builder other = builder.clone();
要对所有WebClient.Builder实例进行应用程序级的附加自定义,您可以声明WebClientCustomizerbean并WebClient.Builder在注入点更改本地实例。
最后,您可以使用原始API并使用WebClient.create()。在这种情况下,不会应用自动配置或WebClientCustomizer

17.验证

只要JSR-303实现(例如Hibernate验证器)位于类路径上,就会自动启用Bean验证1.1支持的方法验证功能。这使Bean方法javax.validation的参数和/或返回值受到约束。具有此类带注释方法的目标类需要@Validated在类型级别用注释进行注释,以便在其方法中搜索内联约束注释。
例如,以下服务触发第一个参数的验证,确保其大小在8到10之间:

  1. @Service
  2. @Validated
  3. public class MyBean {
  4. public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
  5. Author author) {
  6. ...
  7. }
  8. }

18.发送电子邮件

Spring框架提供了使用JavaMailSender接口发送电子邮件的抽象,Spring Boot为它提供了自动配置以及启动程序模块。

有关如何使用的详细说明,请参见参考文档JavaMailSender

如果spring.mail.host和相关库(由定义spring-boot-starter-mail)可用,JavaMailSender则如果不存在则创建默认库。可以通过spring.mail名称空间中的配置项进一步自定义发送方。请参阅MailProperties以获取更多详细信息。
特别是,某些默认超时值是无限的,您可能需要更改该值,以避免线程被无响应的邮件服务器阻塞,如以下示例所示:
特性
Yaml

  1. spring:
  2. mail:
  3. properties:
  4. "[mail.smtp.connectiontimeout]": 5000
  5. "[mail.smtp.timeout]": 3000
  6. "[mail.smtp.writetimeout]": 5000

也可以JavaMailSender使用SessionJNDI中的现有配置进行配置:
特性
Yaml

  1. spring:
  2. mail:
  3. jndi-name: "mail/Session"

jndi-name设置,它优先于所有其他会话相关的设置。

19.与JTA的分布式事务

Spring Boot通过使用Atomikos嵌入式事务管理器支持跨多个XA资源的分布式JTA事务。还提供了不支持使用Bitronix嵌入式事务管理器的支持,但在将来的版本中将删除该支持。部署到合适的Java EE应用程序服务器时,还支持JTA事务。
当检测到JTA环境时,JtaTransactionManager将使用Spring来管理事务。自动配置的JMS,DataSource和JPA Bean已升级为支持XA事务。您可以使用标准Spring习惯用法(例如@Transactional)来参与分布式事务。如果您在JTA环境中,但仍要使用本地事务,则可以将spring.jta.enabled属性设置false为禁用JTA自动配置。

19.1。使用Atomikos交易管理器

Atomikos是一种流行的开源事务管理器,可以嵌入到您的Spring Boot应用程序中。您可以使用spring-boot-starter-jta-atomikos入门程序来引入适当的Atomikos库。Spring Boot自动配置Atomikos,并确保将适当的depends-on设置应用于您的Spring Bean,以正确启动和关闭命令。
默认情况下,Atomikos事务日志写入transaction-logs应用程序主目录中的目录(应用程序jar文件所在的目录)。您可以通过spring.jta.log-dirapplication.properties文件中设置属性来自定义此目录的位置。以开头的属性spring.jta.atomikos.properties也可以用于自定义Atomikos UserTransactionServiceImp。有关完整的详细信息,请参见AtomikosPropertiesJavadoc

为了确保多个事务管理器可以安全地协调同一资源管理器,必须为每个Atomikos实例配置一个唯一的ID。默认情况下,此ID是运行Atomikos的计算机的IP地址。为确保生产中的唯一性,应spring.jta.transaction-manager-id为应用程序的每个实例为属性配置一个不同的值。

19.2。使用Bitronix交易管理器

从Spring Boot 2.3开始,对Bitronix的支持已被弃用,并将在以后的版本中删除。

您可以使用spring-boot-starter-jta-bitronix启动器将适当的Bitronix依赖项添加到项目中。与Atomikos一样,Spring Boot会自动配置Bitronix并对您的bean进行后处理,以确保启动和关闭顺序正确。
默认情况下,Bitronix事务日志文件(part1.btmpart2.btm)被写入transaction-logs应用程序主目录中的目录。您可以通过设置spring.jta.log-dir属性来自定义此目录的位置。以开头的属性spring.jta.bitronix.properties也绑定到bitronix.tm.ConfigurationBean,从而可以进行完全自定义。有关详细信息,请参见Bitronix文档

为了确保多个事务管理器可以安全地协调同一资源管理器,必须为每个Bitronix实例配置唯一的ID。默认情况下,此ID是运行Bitronix的计算机的IP地址。为确保生产中的唯一性,应spring.jta.transaction-manager-id为应用程序的每个实例为属性配置一个不同的值。

19.3。使用Java EE托管事务管理器

如果将Spring Boot应用程序打包为warear文件,并将其部署到Java EE应用程序服务器,则可以使用应用程序服务器的内置事务管理器。Spring Boot尝试通过查看常见的JNDI位置(java:comp/UserTransactionjava:comp/TransactionManager等)来自动配置事务管理器。如果使用应用程序服务器提供的事务服务,通常还需要确保所有资源都由服务器管理并通过JNDI公开。Spring Boot尝试通过ConnectionFactory在JNDI路径(java:/JmsXAjava:/XAConnectionFactory)中查找来尝试自动配置JMS ,您可以使用该spring.datasource.jndi-name属性来配置DataSource

19.4。混合XA和非XA JMS连接

使用JTA时,主要的JMS ConnectionFactoryBean可识别XA,并参与分布式事务。在某些情况下,您可能想通过使用非XA处理某些JMS消息ConnectionFactory。例如,您的JMS处理逻辑可能需要比XA超时更长的时间。
如果要使用非XA ConnectionFactory,则可以注入nonXaJmsConnectionFactorybean而不是@Primary jmsConnectionFactorybean。为了保持一致性,jmsConnectionFactory还使用bean别名提供了bean xaJmsConnectionFactory
以下示例显示了如何注入ConnectionFactory实例:

  1. // Inject the primary (XA aware) ConnectionFactory
  2. @Autowired
  3. private ConnectionFactory defaultConnectionFactory;
  4. // Inject the XA aware ConnectionFactory (uses the alias and injects the same as above)
  5. @Autowired
  6. @Qualifier("xaJmsConnectionFactory")
  7. private ConnectionFactory xaConnectionFactory;
  8. // Inject the non-XA aware ConnectionFactory
  9. @Autowired
  10. @Qualifier("nonXaJmsConnectionFactory")
  11. private ConnectionFactory nonXaConnectionFactory;

19.5。支持替代嵌入式事务管理器

XAConnectionFactoryWrapperXADataSourceWrapper接口可用于支持替代嵌入式事务经理。这些接口负责包装XAConnectionFactoryXADataSourcebean,并将它们作为常规ConnectionFactoryDataSourcebean公开,它们透明地注册到分布式事务中。数据源和JMS自动配置使用JTA变体,前提是您拥有一个JtaTransactionManagerBean并在其中注册了适当的XA包装器Bean ApplicationContext
AtomikosXAConnectionFactoryWrapperAtomikosXADataSourceWrapper提供了如何编写XA包装很好的例子。

20. Hazelcast

如果Hazelcast位于类路径上,并且找到了合适的配置,则Spring Boot会自动配置一个HazelcastInstance您可以在应用程序中注入的。
Spring Boot首先尝试通过检查以下配置选项来创建客户端:

  • com.hazelcast.client.config.ClientConfig豆子的存在。
  • spring.hazelcast.config属性定义的配置文件。
  • hazelcast.client.config系统属性的存在。
  • 一个hazelcast-client.xml在工作目录或在classpath的根目录。
  • 一个hazelcast-client.yaml在工作目录或在classpath的根目录。
    | | Spring Boot同时支持Hazelcast 4和Hazelcast3。如果您降级到Hazelcast 3,hazelcast-client则应将其添加到类路径中以配置客户端。 | | :—-: | —- |

如果无法创建客户端,Spring Boot会尝试配置嵌入式服务器。如果定义一个com.hazelcast.config.Configbean,Spring Boot会使用它。如果您的配置定义了一个实例名称,Spring Boot会尝试查找一个现有实例,而不是创建一个新实例。
您还可以指定通过配置使用的Hazelcast配置文件,如以下示例所示:
特性
Yaml

  1. spring:
  2. hazelcast:
  3. config: "classpath:config/my-hazelcast.xml"

否则,Spring Boot会尝试从默认位置查找Hazelcast配置:hazelcast.xml在工作目录中或类路径的根目录中,或者.yaml在相同位置中的对应目录中。我们还检查是否hazelcast.config设置了系统属性。有关更多详细信息,请参见Hazelcast文档

Spring Boot还具有对Hazelcast的显式缓存支持。如果启用了缓存,HazelcastInstance则会自动将其包装在CacheManager实现中。

21. Quartz Scheduler

Spring Boot为使用Quartz Scheduler提供了许多便利,包括spring-boot-starter-quartz“ Starter”。如果Quartz可用,将Scheduler自动配置a(通过SchedulerFactoryBean抽象)。
以下类型的Bean会被自动拾取并与关联Scheduler

  • JobDetail:定义特定的作业。 JobDetail实例可以使用JobBuilderAPI构建。
  • Calendar
  • Trigger:定义何时触发特定作业。

默认情况下,使用内存JobStore。但是,如果DataSource应用程序中有可用的bean,并且spring.quartz.job-store-type属性已相应配置,则可以配置基于JDBC的存储,如以下示例所示:
特性
Yaml

  1. spring:
  2. quartz:
  3. job-store-type: "jdbc"

使用JDBC存储时,可以在启动时初始化模式,如以下示例所示:
特性
Yaml

  1. spring:
  2. quartz:
  3. jdbc:
  4. initialize-schema: "always"
默认情况下,使用Quartz库随附的标准脚本检测并初始化数据库。这些脚本删除现有表,并在每次重新启动时删除所有触发器。也可以通过设置spring.quartz.jdbc.schema属性来提供自定义脚本。

要让Quartz使用DataSource应用程序主程序以外的其他程序DataSource,请声明一个DataSourcebean,并用注释其@Bean方法@QuartzDataSource。这样做可以确保和DataSource都使用特定于Quartz的SchedulerFactoryBean模式进行初始化。同样,要让Quartz使用TransactionManager应用程序的main之外的其他方法TransactionManager声明一个TransactionManagerbean,并用注释其@Bean方法@QuartzTransactionManager
默认情况下,通过配置创建的作业将不会覆盖从持久性作业存储中读取的已注册作业。要启用覆盖现有作业定义的功能,请设置该spring.quartz.overwrite-existing-jobs属性。
Quartz Scheduler配置可以使用spring.quartz属性和SchedulerFactoryBeanCustomizerbean,从而可以进行程序SchedulerFactoryBean自定义。可以使用定制高级Quartz配置属性spring.quartz.properties.*

特别是,Executorbean没有与调度程序关联,因为Quartz通过提供了一种配置调度程序的方式spring.quartz.properties。如果您需要自定义任务执行器,请考虑实现SchedulerFactoryBeanCustomizer

作业可以定义设置器以注入数据映射属性。常规豆也可以类似的方式注入,如以下示例所示:

  1. public class SampleJob extends QuartzJobBean {
  2. private MyService myService;
  3. private String name;
  4. // Inject "MyService" bean
  5. public void setMyService(MyService myService) { ... }
  6. // Inject the "name" job data property
  7. public void setName(String name) { ... }
  8. @Override
  9. protected void executeInternal(JobExecutionContext context)
  10. throws JobExecutionException {
  11. ...
  12. }
  13. }

22.任务执行和计划

Executor上下文中没有bean的情况下,Spring Boot会ThreadPoolTaskExecutor使用合理的默认值自动配置a ,这些默认值可以自动与异步任务执行(@EnableAsync)和Spring MVC异步请求处理相关联。

如果您Executor在上下文中定义了一个自定义,则常规任务执行(即@EnableAsync)将透明地使用它,但由于需要AsyncTaskExecutor实现(命名为applicationTaskExecutor),因此不会配置Spring MVC支持。根据你的目标的安排,你可以改变你Executor到一个ThreadPoolTaskExecutor或同时定义一个ThreadPoolTaskExecutorAsyncConfigurer包装您的自定义Executor
通过自动配置TaskExecutorBuilder,您可以轻松创建实例,以重现默认情况下自动配置的功能。

线程池使用8个核心线程,这些线程可以根据负载增长和收缩。可以使用spring.task.execution名称空间对那些默认设置进行微调,如以下示例所示:
特性
Yaml

  1. spring:
  2. task:
  3. execution:
  4. pool:
  5. max-size: 16
  6. queue-capacity: 100
  7. keep-alive: "10s"

这会将线程池更改为使用有界队列,以便在队列已满(100个任务)时,线程池最多增加到16个线程。池的收缩更加激进,因为当线程空闲10秒(而不是默认情况下的60秒)时,它们将被回收。
ThreadPoolTaskScheduler如果需要与计划的任务执行(@EnableScheduling)关联,也可以自动配置A。线程池默认使用一个线程,可以使用spring.task.scheduling名称空间对这些设置进行微调。
既是TaskExecutorBuilder豆和TaskSchedulerBuilder绿豆可在上下文提供如果要创建一个自定义的遗嘱执行人或调度的需求。

23. Spring集成

Spring Boot提供了许多使用Spring Integration的便利,包括spring-boot-starter-integration“ Starter”。Spring Integration在消息传递以及其他传输(例如HTTP,TCP等)上提供了抽象。如果您的类路径上有Spring Integration,则可以通过@EnableIntegration注释对其进行初始化。
Spring Boot还配置了一些功能,这些功能由其他Spring Integration模块的存在触发。如果spring-integration-jmx也在类路径上,则消息处理统计信息将通过JMX发布。如果spring-integration-jdbc可用,那么可以在启动时创建默认的数据库架构,如以下行所示:
特性
Yaml

  1. spring:
  2. integration:
  3. jdbc:
  4. initialize-schema: "always"

如果spring-integration-rsocket可用,开发人员可以使用"spring.rsocket.server.*"属性配置RSocket服务器,并使其使用IntegrationRSocketEndpointRSocketOutboundGateway组件来处理传入的RSocket消息。该基础结构可以处理Spring Integration RSocket通道适配器和@MessageMapping处理程序("spring.integration.rsocket.server.message-mapping-enabled"已配置)。
Spring Boot也可以ClientRSocketConnector使用配置属性自动配置:
特性
Yaml

  1. # Connecting to a RSocket server over TCP
  2. spring:
  3. integration:
  4. rsocket:
  5. client:
  6. host: "example.org"
  7. port: 9898

特性
Yaml

  1. # Connecting to a RSocket Server over WebSocket
  2. spring:
  3. integration:
  4. rsocket:
  5. client:
  6. uri: "ws://example.org"

有关更多详细信息,请参见IntegrationAutoConfigurationIntegrationProperties类。
默认情况下,如果存在Micrometer meterRegistrybean,Spring Integration指标将由Micrometer管理。如果您希望使用旧版Spring Integration指标,请DefaultMetricsFactory在应用程序上下文中添加一个bean。

24.春季会议

Spring Boot为各种数据存储提供了Spring Session自动配置。构建Servlet Web应用程序时,可以自动配置以下存储:

  • JDBC
  • 雷迪斯
  • 淡褐色
  • MongoDB

Servlet自动配置取代了对use的需要@Enable*HttpSession
构建反应式Web应用程序时,可以自动配置以下存储:

  • 雷迪斯
  • MongoDB

反应式自动配置取代了使用的需要@Enable*WebSession
如果类路径上存在单个Spring Session模块,则Spring Boot会自动使用该存储实现。如果您有多个实现,则必须选择StoreType要用于存储会话的实现。例如,要将JDBC用作后端存储,可以按以下方式配置应用程序:
特性
Yaml

  1. spring:
  2. session:
  3. store-type: "jdbc"
您可以通过将设置为store-type来禁用Spring Session none

每个商店都有特定的其他设置。例如,可以为JDBC存储定制表的名称,如以下示例所示:
特性
Yaml

  1. spring:
  2. session:
  3. jdbc:
  4. table-name: "SESSIONS"

要设置会话超时,您可以使用spring.session.timeout属性。如果未通过Servlet Web应用程序设置该属性,则自动配置将回退到的值server.servlet.session.timeout
您可以使用@Enable*HttpSession(Servlet)或@Enable*WebSession(Reactive)来控制Spring Session的配置。这将导致自动配置退出。然后可以使用注释的属性而不是先前描述的配置属性来配置Spring Session。

25.通过JMX进行监视和管理

Java管理扩展(JMX)提供了监视和管理应用程序的标准机制。Spring Boot将最适合MBeanServer作为ID为的bean公开mbeanServer。您的任何豆被标注有春天JMX注释(@ManagedResource@ManagedAttribute,或@ManagedOperation)接触到它。
如果您的平台提供了标准MBeanServer,Spring Boot将使用该标准,并MBeanServer在必要时默认使用VM 。如果全部失败,MBeanServer将创建一个新的。
有关JmxAutoConfiguration更多详细信息,请参见课程。

26.测试

Spring Boot提供了许多实用程序和注释,可以在测试应用程序时提供帮助。测试支持由两个模块提供:spring-boot-test包含核心项,并spring-boot-test-autoconfigure支持测试的自动配置。
大多数开发人员使用spring-boot-starter-test“入门程序”,该程序同时导入Spring Boot测试模块以及JUnit Jupiter,AssertJ,Hamcrest和许多其他有用的库。

| | 如果您有使用JUnit 4的测试,则可以使用JUnit 5的老式引擎来运行它们。要使用老式引擎,请添加对的依赖junit-vintage-engine,如以下示例所示:```

org.junit.vintage junit-vintage-engine test org.hamcrest hamcrest-core

  1. |
  2. | :---: | --- |
  3. `hamcrest-core`被排除在外`org.hamcrest:hamcrest`,是的一部分`spring-boot-starter-test`
  4. <a name="boot-features-test-scope-dependencies"></a>
  5. ### 26.1。测试范围依赖性
  6. `spring-boot-starter-test`“入门”(中`test` `scope`)包含以下提供的库:
  7. - [JUnit 5](https://junit.org/junit5/):用于对Java应用程序进行单元测试的事实上的标准。<br />
  8. - [Spring测试](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#integration-testing)和Spring Boot测试:对Spring Boot应用程序的实用程序和集成测试支持。<br />
  9. - [AssertJ](https://assertj.github.io/doc/):流畅的断言库。<br />
  10. - [Hamcrest](https://github.com/hamcrest/JavaHamcrest):匹配对象库(也称为约束或谓词)。<br />
  11. - [Mockito](https://site.mockito.org/):一个Java[模拟](https://site.mockito.org/)框架。<br />
  12. - [JSONassert](https://github.com/skyscreamer/JSONassert):JSON的断言库。<br />
  13. - [JsonPath](https://github.com/jayway/JsonPath):JSON的XPath。<br />
  14. 通常,我们发现这些通用库在编写测试时很有用。如果这些库不适合您的需求,则可以添加自己的其他测试依赖项。
  15. <a name="boot-features-testing-spring-applications"></a>
  16. ### 26.2。测试Spring应用程序
  17. 依赖注入的主要优点之一是,它应该使您的代码更易于进行单元测试。您可以使用`new`运算符实例化对象,甚至不需要使用Spring。您还可以使用_模拟对象_而不是实际的依赖项。<br />通常,您需要超越单元测试并开始集成测试(使用Spring `ApplicationContext`)。能够进行集成测试而无需部署应用程序或连接到其他基础结构,这很有用。<br />Spring框架包括用于此类集成测试的专用测试模块。您可以直接向其声明依赖项,`org.springframework:spring-test`也可以使用`spring-boot-starter-test`“启动器”将其引入。<br />如果您以前没有使用过该`spring-test`模块,则应先阅读Spring Framework参考文档的[相关部分](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#testing)。
  18. <a name="boot-features-testing-spring-boot-applications"></a>
  19. ### 26.3。测试Spring Boot应用程序
  20. Spring Boot应用程序是Spring `ApplicationContext`,因此除了对普通Spring上下文进行常规测试以外,无需执行任何其他特殊操作即可对其进行测试。
  21. | | 默认情况下,Spring Boot的外部属性,日志记录和其他功能仅在`SpringApplication`用于创建时才安装在上下文中。 |
  22. | :---: | --- |
  23. Spring Boot提供了一个`@SpringBootTest`注释,`spring-test` `@ContextConfiguration`当您需要Spring Boot功能时,它可以用作标准注释的替代。注释通过[创建`ApplicationContext`在测试中使用的来`SpringApplication`](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-detecting-config)起作用。除了`@SpringBootTest`提供许多其他注释,还用于[测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests)应用程序的[更多特定](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests)部分。
  24. | | 如果使用的是JUnit 4,请不要忘记也将其添加`@RunWith(SpringRunner.class)`到测试中,否则注释将被忽略。如果您使用的是JUnit 5,则无需添加等价物`@ExtendWith(SpringExtension.class)``@SpringBootTest`并且其他`@…Test`注释已经使用它进行了注释。 |
  25. | :---: | --- |
  26. 默认情况下,`@SpringBootTest`不会启动服务器。您可以使用的`webEnvironment`属性`@SpringBootTest`进一步完善测试的运行方式:
  27. - `MOCK`(默认):加载Web`ApplicationContext`并提供模拟Web环境。使用此注释时,不会启动嵌入式服务器。如果您的类路径中没有网络环境,则此模式将透明地退回到创建常规非网络`ApplicationContext`。它可以与Web应用程序结合使用[`@AutoConfigureMockMvc``@AutoConfigureWebTestClient`](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-mock-environment)用于基于模拟的测试。<br />
  28. - `RANDOM_PORT`:加载`WebServerApplicationContext`并提供真实的网络环境。嵌入式服务器将启动并在随机端口上侦听。<br />
  29. - `DEFINED_PORT`:加载`WebServerApplicationContext`并提供真实的网络环境。嵌入式服务器将启动并在已定义的端口(来自`application.properties`)上或在的默认端口上进行侦听`8080`。<br />
  30. - `NONE``ApplicationContext`通过使用加载,`SpringApplication`但不提供_任何_网络环境(模拟或其他方式)。<br />
  31. | | 如果您的测试是`@Transactional`,则默认情况下它将在每个测试方法的末尾回滚事务。但是,由于将这种安排与一个`RANDOM_PORT`或多个`DEFINED_PORT`隐式提供真实的servlet环境一起使用,HTTP客户端和服务器在单独的线程中运行,因此在单独的事务中运行。在这种情况下,服务器上启动的任何事务都不会回滚。 |
  32. | :---: | --- |
  33. | | `@SpringBootTest``webEnvironment = WebEnvironment.RANDOM_PORT`如果您的应用程序对管理服务器使用其他端口,则with还将在单独的随机端口上启动管理服务器。 |
  34. | :---: | --- |
  35. <a name="boot-features-testing-spring-boot-applications-detecting-web-app-type"></a>
  36. #### 26.3.1。检测Web应用程序类型
  37. 如果Spring MVC可用,则配置基于常规MVC的应用程序上下文。如果您只有Spring WebFlux,我们将检测到该情况并配置基于WebFlux的应用程序上下文。<br />如果两者都存在,则Spring MVC优先。如果要在这种情况下测试反应式Web应用程序,则必须设置`spring.main.web-application-type`属性:

@SpringBootTest(properties = “spring.main.web-application-type=reactive”) class MyWebFluxTests { … }

  1. <a name="boot-features-testing-spring-boot-applications-detecting-config"></a>
  2. #### 26.3.2。检测测试配置
  3. 如果您熟悉Spring Test Framework,则可能习惯于使用`@ContextConfiguration(classes=…)`来指定`@Configuration`要加载哪个Spring 。另外,您可能经常`@Configuration`在测试中使用嵌套类。<br />在测试Spring Boot应用程序时,通常不需要这样做。`@*Test`只要您没有明确定义Spring Boot的注释,它就会自动搜索您的主要配置。<br />搜索算法从包含测试的程序包开始工作,直到找到带有`@SpringBootApplication`或注释的类`@SpringBootConfiguration`。只要您以合理的方式[对代码](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot-structuring-your-code)进行[结构化](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot-structuring-your-code),通常就可以找到您的主要配置。
  4. | | 如果使用[测试注释来测试应用程序的更特定的部分](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests),则应避免在[main方法的应用程序类](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-user-configuration)上添加特定于特定区域的配置设置。<br />define的基础组件扫描配置`@SpringBootApplication`排除了用于确保切片按预期工作的过滤器。如果`@ComponentScan`在`@SpringBootApplication`-annotated类上使用显式指令,请注意这些过滤器将被禁用。如果使用切片,则应重新定义它们。 |
  5. | :---: | --- |
  6. 如果要自定义主要配置,则可以使用嵌套`@TestConfiguration`类。与`@Configuration`将使用嵌套类代替应用程序的主要配置的嵌套`@TestConfiguration`类不同,除了应用程序的主要配置之外,还使用了嵌套类。
  7. | | Spring的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论如何发现),加载上下文的潜在耗时过程就只会发生一次。 |
  8. | :---: | --- |
  9. <a name="boot-features-testing-spring-boot-applications-excluding-config"></a>
  10. #### 26.3.3。排除测试配置
  11. 如果您的应用程序使用组件扫描(例如,如果使用`@SpringBootApplication`或`@ComponentScan`),则可能会偶然发现到处仅为特定测试创建的顶级配置类。<br />如我们[先前所见](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-detecting-config),`@TestConfiguration`可以在测试的内部类上使用来自定义主要配置。当放置在顶级类上时,`@TestConfiguration`指示`src/test/java`不应通过扫描来拾取其中的类。然后,可以在需要的位置显式导入该类,如以下示例所示:

@SpringBootTest @Import(MyTestsConfiguration.class) class MyTests { @Test void exampleTest() { … } }

  1. | | 如果您直接使用`@ComponentScan`(即不是通过`@SpringBootApplication`),则需要向其注册`TypeExcludeFilter`。有关详细信息,请参见[Javadoc](https://docs.spring.io/spring-boot/docs/2.4.3/api/org/springframework/boot/context/TypeExcludeFilter.html)。 |
  2. | :---: | --- |
  3. <a name="boot-features-testing-spring-boot-application-arguments"></a>
  4. #### 26.3.4。使用应用程序参数
  5. 如果您的应用程序需要[参数](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-application-arguments),则可以`@SpringBootTest`使用`args`属性注入它们。

@SpringBootTest(args = “—app.test=one”) class ApplicationArgumentsExampleTests { @Test void applicationArgumentsPopulated(@Autowired ApplicationArguments args) { assertThat(args.getOptionNames()).containsOnly(“app.test”); assertThat(args.getOptionValues(“app.test”)).containsOnly(“one”); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-with-mock-environment"></a>
  2. #### 26.3.5。在模拟环境中进行测试
  3. 默认情况下,`@SpringBootTest`不启动服务器。如果您有要在此模拟环境下进行测试的Web终结点,则可以另外配置[`MockMvc`](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#spring-mvc-test-framework),如以下示例所示:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc class MockMvcExampleTests { @Test void exampleTest(@Autowired MockMvc mvc) throws Exception { mvc.perform(get(“/“)).andExpect(status().isOk()).andExpect(content().string(“Hello World”)); } }

  1. | | 如果您只想专注于Web层而不希望开始完整工作`ApplicationContext`,请考虑[使用`@WebMvcTest`代替](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests)。 |
  2. | :---: | --- |
  3. 或者,您可以配置[`WebTestClient`](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#webtestclient-tests)如以下示例所示:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.reactive.server.WebTestClient; @SpringBootTest @AutoConfigureWebTestClient class MockWebTestClientExampleTests { @Test void exampleTest(@Autowired WebTestClient webClient) { webClient.get().uri(“/“).exchange().expectStatus().isOk().expectBody(String.class).isEqualTo(“Hello World”); } }

  1. | | 在模拟环境中进行测试通常比在完整的Servlet容器中运行更快。但是,由于模拟是在Spring MVC层进行的,因此无法使用MockMvc直接测试依赖于较低级别Servlet容器行为的代码。<br />例如,Spring Boot的错误处理基于Servlet容器提供的“错误页面”支持。这意味着,尽管您可以按预期测试MVC层引发并处理异常,但是您无法直接测试是否呈现了特定的[自定义错误页面](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-error-handling-custom-error-pages)。如果您需要测试这些较低级别的问题,则可以按照下一节中的描述启动一个完全运行的服务器。 |
  2. | :---: | --- |
  3. <a name="boot-features-testing-spring-boot-applications-testing-with-running-server"></a>
  4. #### 26.3.6。使用正在运行的服务器进行测试
  5. 如果需要启动完全运行的服务器,建议您使用随机端口。如果使用`@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)`,则每次运行测试时都会随机选择一个可用端口。<br />该`@LocalServerPort`注释可用于[注射使用的实际端口](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/howto.html#howto-discover-the-http-port-at-runtime)到您的测试。为了方便起见,需要对启动的服务器进行REST调用的测试可以另外`@Autowire`使用[`WebTestClient`](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#webtestclient-tests),它解析到正在运行的服务器的相对链接,并带有用于验证响应的专用API,如以下示例所示:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.web.reactive.server.WebTestClient; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class RandomPortWebTestClientExampleTests { @Test void exampleTest(@Autowired WebTestClient webClient) { webClient.get().uri(“/“).exchange().expectStatus().isOk().expectBody(String.class).isEqualTo(“Hello World”); } }

  1. 此设置需要`spring-webflux`在类路径上进行。如果您不能或不会添加webfluxSpring Boot还提供了以下`TestRestTemplate`功能:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class RandomPortTestRestTemplateExampleTests { @Test void exampleTest(@Autowired TestRestTemplate restTemplate) { String body = restTemplate.getForObject(“/“, String.class); assertThat(body).isEqualTo(“Hello World”); } }

  1. <a name="boot-features-testing-spring-boot-applications-customizing-web-test-client"></a>
  2. #### 26.3.7。自定义WebTestClient
  3. 要自定义`WebTestClient`Bean,请配置`WebTestClientBuilderCustomizer`Bean。`WebTestClient.Builder`会使用用于创建的任何此类bean进行调用`WebTestClient`。
  4. <a name="boot-features-testing-spring-boot-applications-jmx"></a>
  5. #### 26.3.8。使用JMX
  6. 由于测试上下文框架缓存上下文,因此默认情况下禁用JMX以防止相同组件在同一域上注册。如果此类测试需要访问`MBeanServer`,请考虑将其标记为脏:

@ExtendWith(SpringExtension.class) @SpringBootTest(properties = “spring.jmx.enabled=true”) @DirtiesContext class SampleJmxTests { @Autowired private MBeanServer mBeanServer; @Test void exampleTest() { // … } }

  1. <a name="boot-features-testing-spring-boot-applications-metrics"></a>
  2. #### 26.3.9。使用指标
  3. 无论使用哪种类路径,使用时都不会自动配置电表注册表(内存中支持的除外)`@SpringBootTest`。<br />如果您需要在集成测试中将指标导出到其他后端,请使用进行注释`@AutoConfigureMetrics`。
  4. <a name="boot-features-testing-spring-boot-applications-mocking-beans"></a>
  5. #### 26.3.10。模拟豆和间谍豆
  6. 运行测试时,有时有必要在应用程序上下文中模拟某些组件。例如,您可能在开发期间无法使用某些远程服务的外观。当您要模拟在实际环境中可能难以触发的故障时,模拟也很有用。<br />Spring Boot包含一个`@MockBean`注释,可用于为您的Bean中的bean定义Mockito模拟`ApplicationContext`。您可以使用注释添加新的bean或替换单个现有的bean定义。注释可以直接用于测试类,测试中的字段或`@Configuration`类和字段。当在字段上使用时,还将注入创建的模拟的实例。每种测试方法后,模拟豆都会自动重置。
  7. | | 如果您的测试使用Spring Boot的测试注释之一(例如`@SpringBootTest`),则此功能会自动启用。要以其他方式使用此功能,必须明确添加侦听器,如以下示例所示:

@TestExecutionListeners(MockitoTestExecutionListener.class)

  1. |
  2. | :---: | --- |
  3. 下面的示例用`RemoteService`模拟实现替换现有的bean

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.; import org.springframework.boot.test.context.; import org.springframework.boot.test.mock.mockito.; import static org.assertj.core.api.Assertions.; import static org.mockito.BDDMockito.*; @SpringBootTest class MyTests { @MockBean private RemoteService remoteService; @Autowired private Reverser reverser; @Test void exampleTest() { // RemoteService has been injected into the reverser bean given(this.remoteService.someCall()).willReturn(“mock”); String reverse = reverser.reverseSomeCall(); assertThat(reverse).isEqualTo(“kcom”); } }

  1. | | `@MockBean`不能用来模拟应用程序上下文刷新期间执行的bean的行为。在执行测试时,应用程序上下文刷新已完成,并且配置模拟行为为时已晚。我们建议`@Bean`在这种情况下使用一种方法来创建和配置模拟。 |
  2. | :---: | --- |
  3. 另外,您可以使用`@SpyBean`Mockito来包装任何现有的bean `spy`。有关完整的详细信息,请参见[Javadoc](https://docs.spring.io/spring-boot/docs/2.4.3/api/org/springframework/boot/test/mock/mockito/SpyBean.html)。
  4. | | CGLib代理(例如为范围内的bean创建的代理)将代理方法声明为`final`。这会阻止Mockito正常运行,因为它无法模拟或监视`final`其默认配置中的方法。如果要模拟或监视此类bean,请通过添加`org.mockito:mockito-inline`到应用程序的测试依赖项中,将Mockito配置为使用其内联模拟生成器。这允许Mockito模拟和监视`final`方法。 |
  5. | :---: | --- |
  6. | | Spring的测试框架在测试之间缓存应用程序上下文,并为共享相同配置的测试重用上下文,但是缓存密钥的使用`@MockBean``@SpyBean`影响缓存密钥,这很可能会增加上下文的数量。 |
  7. | :---: | --- |
  8. | | 如果您使用`@SpyBean`带有`@Cacheable`通过名称引用参数的方法来监视Bean,则必须使用编译应用程序`-parameters`。这样可以确保一旦侦察到bean,参数名称就可用于缓存基础结构。 |
  9. | :---: | --- |
  10. | | 当您`@SpyBean`用来监视由Spring代理的bean时,在某些情况下,例如使用`given`或设置期望值时,可能需要删除Spring的代理`when`。使用`AopTestUtils.getTargetObject(yourProxiedSpy)`这样做。 |
  11. | :---: | --- |
  12. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-tests"></a>
  13. #### 26.3.11。自动配置的测试
  14. Spring Boot的自动配置系统适用于应用程序,但有时对于测试来说可能有点过多。它通常仅有助于加载测试应用程序“切片”所需的配置部分。例如,您可能想要测试Spring MVC控制器是否正确映射了URL,并且您不想在这些测试中涉及数据库调用,或者您想要测试JPA实体,并且对那些JPA实体不感兴趣。测试运行。<br />该`spring-boot-test-autoconfigure`模块包括许多注释,可用于自动配置此类“切片”。它们中的每一个都以相似的方式工作,提供了一个`@…Test`加载的注释`ApplicationContext`以及一个或多个`@AutoConfigure…`可用于自定义自动配置设置的注释。
  15. | | 每个切片将组件扫描限制为适当的组件,并加载一组非常受限制的自动配置类。如果您需要排除其中之一,则大多数`@…Test`注释都提供一个`excludeAutoConfiguration`属性。或者,您可以使用`@ImportAutoConfiguration#exclude` |
  16. | :---: | --- |
  17. | | `@…Test`不支持在一个测试中 使用多个注释来包含多个“片段” 。如果需要多个“切片”,请选择其中一个`@…Test`注释,并`@AutoConfigure…`手动添加其他“切片”的注释。 |
  18. | :---: | --- |
  19. | | 也可以将`@AutoConfigure…`注释与标准`@SpringBootTest`注释一起使用。如果您对“切片”应用程序不感兴趣,但需要一些自动配置的测试bean,则可以使用此组合。 |
  20. | :---: | --- |
  21. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests"></a>
  22. #### 26.3.12。自动配置的JSON测试
  23. 要测试对象JSON序列化和反序列化是否按预期工作,可以使用`@JsonTest`批注。 `@JsonTest`自动配置可用的受支持的JSON映射器,该映射器可以是以下库之一:
  24. - 杰克逊`ObjectMapper`,任何`@JsonComponent`豆子和任何杰克逊`Module`的<br />
  25. - `Gson`<br />
  26. - `Jsonb`<br />
  27. | | 由启用了自动配置的列表`@JsonTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  28. | :---: | --- |
  29. 如果需要配置自动配置的元素,则可以使用`@AutoConfigureJsonTesters`注释。<br />Spring Boot包括基于AssertJ的助手,这些助手与JSONAssertJsonPath库一起使用,以检查JSON是否按预期方式显示。的`JacksonTester``GsonTester``JsonbTester`,和`BasicJsonTester`类可以分别用于杰克逊,GSONJsonb,和字符串。`@Autowired`使用时,可以在测试类上使用任何帮助程序字段`@JsonTest`。以下示例显示了Jackson的测试类:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.; import org.springframework.boot.test.autoconfigure.json.; import org.springframework.boot.test.context.; import org.springframework.boot.test.json.; import static org.assertj.core.api.Assertions.*; @JsonTest class MyJsonTests { @Autowired private JacksonTester json; @Test void testSerialize() throws Exception { VehicleDetails details = new VehicleDetails(“Honda”, “Civic”); // Assert against a .json file in the same package as the test assertThat(this.json.write(details)).isEqualToJson(“expected.json”); // Or use JSON path based assertions assertThat(this.json.write(details)).hasJsonPathStringValue(“@.make”); assertThat(this.json.write(details)).extractingJsonPathStringValue(“@.make”) .isEqualTo(“Honda”); } @Test void testDeserialize() throws Exception { String content = “{\”make\”:\”Ford\”,\”model\”:\”Focus\”}”; assertThat(this.json.parse(content)) .isEqualTo(new VehicleDetails(“Ford”, “Focus”)); assertThat(this.json.parseObject(content).getMake()).isEqualTo(“Ford”); } }

  1. | | JSON帮助程序类也可以直接在标准单元测试中使用。为此,如果不使用,请`initFields`在您的`@Before`方法中调用辅助方法`@JsonTest` |
  2. | :---: | --- |
  3. 如果您正在使用基于Spring Boot的基于AssertJ的助手来声明给定JSON路径上的数字值,则可能无法使用,`isEqualTo`具体取决于类型。相反,您可以使用AssertJ`satisfies`声明该值匹配给定条件。例如,以下示例断言实际数字是一个接近于`0.15`偏移量内的浮点值`0.01`

assertThat(json.write(message)) .extractingJsonPathNumberValue(“@.test.numberValue”) .satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests"></a>
  2. #### 26.3.13。自动配置的Spring MVC测试
  3. 要测试Spring MVC控制器是否按预期工作,请使用`@WebMvcTest`注释。 `@WebMvcTest`自动配置Spring MVC的基础设施和限制扫描豆`@Controller`,`@ControllerAdvice`,`@JsonComponent`,`Converter`,`GenericConverter`,`Filter`,`HandlerInterceptor`,`WebMvcConfigurer`,和`HandlerMethodArgumentResolver`。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@WebMvcTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  4. | | 的由启用了自动配置设置列表`@WebMvcTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. | | 如果需要注册其他组件,例如Jackson `Module`,则可以`@Import`在测试中使用来导入其他配置类。 |
  7. | :---: | --- |
  8. 通常,`@WebMvcTest`它仅限于单个控制器,并且与之结合使用`@MockBean`以为所需的协作者提供模拟实现。<br />`@WebMvcTest`也可以自动配置`MockMvc`。Mock MVC提供了一种强大的方法来快速测试MVC控制器,而无需启动完整的HTTP服务器。
  9. | | 您还可以通过使用注释`MockMvc`在非`@WebMvcTest`(例如`@SpringBootTest`)中进行自动配置`@AutoConfigureMockMvc`。以下示例使用`MockMvc`: |
  10. | :---: | --- |

import org.junit.jupiter.api.; import org.springframework.beans.factory.annotation.; import org.springframework.boot.test.autoconfigure.web.servlet.; import org.springframework.boot.test.mock.mockito.; import static org.assertj.core.api.Assertions.; import static org.mockito.BDDMockito.; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.; @WebMvcTest(UserVehicleController.class) class MyControllerTests { @Autowired private MockMvc mvc; @MockBean private UserVehicleService userVehicleService; @Test void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails(“sboot”)) .willReturn(new VehicleDetails(“Honda”, “Civic”)); this.mvc.perform(get(“/sboot/vehicle”).accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()).andExpect(content().string(“Honda Civic”)); } }

  1. | | 如果您需要配置自动配置的元素(例如,当应该应用servlet过滤器时),则可以在`@AutoConfigureMockMvc`注释中使用属性。 |
  2. | :---: | --- |
  3. 如果使用HtmlUnitSelenium,则自动配置还会提供HtmlUnit `WebClient`bean和/或Selenium `WebDriver`bean。以下示例使用HtmlUnit

import com.gargoylesoftware.htmlunit.; import org.junit.jupiter.api.; import org.springframework.beans.factory.annotation.; import org.springframework.boot.test.autoconfigure.web.servlet.; import org.springframework.boot.test.mock.mockito.; import static org.assertj.core.api.Assertions.; import static org.mockito.BDDMockito.*; @WebMvcTest(UserVehicleController.class) class MyHtmlUnitTests { @Autowired private WebClient webClient; @MockBean private UserVehicleService userVehicleService; @Test void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails(“sboot”)) .willReturn(new VehicleDetails(“Honda”, “Civic”)); HtmlPage page = this.webClient.getPage(“/sboot/vehicle.html”); assertThat(page.getBody().getTextContent()).isEqualTo(“Honda Civic”); } }

  1. | | 默认情况下,Spring Boot`WebDriver`bean放在一个特殊的“作用域”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不希望出现这种情况,可以将其添加`@Scope("singleton")``WebDriver` `@Bean`定义中。 |
  2. | :---: | --- |
  3. | | `webDriver`Spring Boot创建 的作用域将替换任何具有相同名称的用户定义的作用域。如果您定义自己的`webDriver`范围,则可能会发现它在使用时停止工作`@WebMvcTest` |
  4. | :---: | --- |
  5. 如果您在类路径上具有Spring Security`@WebMvcTest`还将扫描`WebSecurityConfigurer`bean。您可以使用Spring Security的测试支持,而不是完全禁用此类测试的安全性。有关如何使用Spring Security`MockMvc`支持的更多详细信息,请参见_[howto.html操作](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/howto.html#howto-use-test-with-spring-security)_方法部分。
  6. | | 有时编写Spring MVC测试是不够的。Spring Boot可以帮助您[使用实际服务器](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server)运行[完整的端到端测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server)。 |
  7. | :---: | --- |
  8. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-webflux-tests"></a>
  9. #### 26.3.14。自动配置的Spring WebFlux测试
  10. 要测试[Spring WebFlux](https://docs.spring.io/spring/docs/5.3.4/reference/html/web-reactive.html)控制器是否按预期工作,可以使用`@WebFluxTest`注释。 `@WebFluxTest`自动配置春季WebFlux基础设施和限制扫描豆`@Controller`,`@ControllerAdvice`,`@JsonComponent`,`Converter`,`GenericConverter`,`WebFilter`,和`WebFluxConfigurer`。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@WebFluxTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  11. | | 由启用了自动配置的列表`@WebFluxTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  12. | :---: | --- |
  13. | | 如果您需要注册其他组件,例如Jackson `Module`,则可以`@Import`在测试中使用导入其他配置类。 |
  14. | :---: | --- |
  15. 通常,`@WebFluxTest`它仅限于单个控制器,并且与`@MockBean`注释结合使用以为所需的协作者提供模拟实现。<br />`@WebFluxTest`还自动配置[`WebTestClient`](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#webtestclient),它提供了一种强大的方法来快速测试WebFlux控制器,而无需启动完整的HTTP服务器。
  16. | | 您还可以通过使用注释`WebTestClient`在非`@WebFluxTest`(例如`@SpringBootTest`)中进行自动配置`@AutoConfigureWebTestClient`。以下示例显示了同时使用`@WebFluxTest`和的类`WebTestClient` |
  17. | :---: | --- |

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; @WebFluxTest(UserVehicleController.class) class MyControllerTests { @Autowired private WebTestClient webClient; @MockBean private UserVehicleService userVehicleService; @Test void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails(“sboot”)) .willReturn(new VehicleDetails(“Honda”, “Civic”)); this.webClient.get().uri(“/sboot/vehicle”).accept(MediaType.TEXT_PLAIN) .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo(“Honda Civic”); } }

  1. | | WebFlux应用程序仅支持此设置,因为`WebTestClient`在模拟的Web应用程序中使用的设置目前仅适用于WebFlux |
  2. | :---: | --- |
  3. | | `@WebFluxTest`无法检测通过功能Web框架注册的路由。要`RouterFunction`在上下文中测试Bean,请考虑`RouterFunction`通过`@Import`或使用导入自己`@SpringBootTest` |
  4. | :---: | --- |
  5. | | `@WebFluxTest`无法检测到通过`@Bean`类型注册的自定义安全配置`SecurityWebFilterChain`。要将其包括在测试中,您将需要通过`@Import`或使用导入注册Bean的配置`@SpringBootTest` |
  6. | :---: | --- |
  7. | | 有时编写Spring WebFlux测试是不够的。Spring Boot可以帮助您[使用实际服务器](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server)运行[完整的端到端测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server)。 |
  8. | :---: | --- |
  9. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-cassandra-test"></a>
  10. #### 16.3.15。自动配置的数据Cassandra测试
  11. 您可以`@DataCassandraTest`用来测试Cassandra应用程序。默认情况下,它配置一个`CassandraTemplate`,扫描`@Table`类,并配置Spring Data Cassandra存储库。使用注解时,不会扫描Regular`@Component``@ConfigurationProperties`bean `@DataCassandraTest` `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。(有关在Spring Boot中结合使用Cassandra的更多信息,请参阅本章前面的“ [Cassandra](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-cassandra) ”。)
  12. | | 的由启用了自动配置设置列表`@DataCassandraTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  13. | :---: | --- |
  14. 以下示例显示了在Spring Boot中使用Cassandra测试的典型设置:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest; @DataCassandraTest class ExampleDataCassandraTests { @Autowired private YourRepository repository; // }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test"></a>
  2. #### 26.3.16。自动配置的数据JPA测试
  3. 您可以使用`@DataJpaTest`注释来测试JPA应用程序。默认情况下,它将扫描`@Entity`类并配置Spring Data JPA存储库。如果在类路径上有嵌入式数据库,它也会配置一个。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@DataJpaTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  4. | | 的由启用了自动配置设置列表`@DataJpaTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 默认情况下,数据JPA测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参见Spring Framework参考文档中的[相关部分](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#testcontext-tx-enabling-transactions)。如果这不是您想要的,则可以按以下方式禁用测试或整个类的事务管理:

import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @DataJpaTest @Transactional(propagation = Propagation.NOT_SUPPORTED) class ExampleNonTransactionalTests { }

  1. 数据JPA测试也可以注入[`TestEntityManager`](https://github.com/spring-projects/spring-boot/tree/v2.4.3/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestEntityManager.java)Bean,这`EntityManager`是专门为测试设计的标准JPA的替代方法。如果要`TestEntityManager`在`@DataJpaTest`实例外部使用,也可以使用`@AutoConfigureTestEntityManager`注释。`JdbcTemplate`如果需要,也可以使用A。以下示例显示了`@DataJpaTest`正在使用的注释:

import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.orm.jpa.; import static org.assertj.core.api.Assertions.; @DataJpaTest class ExampleRepositoryTests { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository repository; @Test void testExample() throws Exception { this.entityManager.persist(new User(“sboot”, “1234”)); User user = this.repository.findByUsername(“sboot”); assertThat(user.getUsername()).isEqualTo(“sboot”); assertThat(user.getVin()).isEqualTo(“1234”); } }

  1. 内存嵌入式数据库通常运行良好,不需要任何安装,因此通常可以很好地进行测试。但是,如果您希望对真实数据库运行测试,则可以使用`@AutoConfigureTestDatabase`注释,如以下示例所示:

@DataJpaTest @AutoConfigureTestDatabase(replace=Replace.NONE) class ExampleRepositoryTests { // … }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-jdbc-test"></a>
  2. #### 26.3.17。自动配置的JDBC测试
  3. `@JdbcTest`与相似,`@DataJpaTest`但适用于仅需使用`DataSource`并且不使用Spring Data JDBC的测试。默认情况下,它配置一个内存嵌入式数据库和一个`JdbcTemplate`。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@JdbcTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  4. | | 由启用了自动配置的列表`@JdbcTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 缺省情况下,JDBC测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参见Spring Framework参考文档中的[相关部分](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#testcontext-tx-enabling-transactions)。如果这不是您想要的,则可以为测试或整个类禁用事务管理,如下所示:

import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @JdbcTest @Transactional(propagation = Propagation.NOT_SUPPORTED) class ExampleNonTransactionalTests { }

  1. 如果您希望测试针对真实数据库运行,则可以使用`@AutoConfigureTestDatabase`与相同的注释方式`DataJpaTest`。(请参阅“[自动配置的数据JPA测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test)”。)
  2. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-data-jdbc-test"></a>
  3. #### 26.3.18。自动配置的数据JDBC测试
  4. `@DataJdbcTest`类似于`@JdbcTest`但适用于使用Spring Data JDBC存储库的测试。默认情况下,它配置一个内存嵌入式数据库,一个`JdbcTemplate`Spring Data JDBC存储库。使用注解时,不会扫描Regular`@Component``@ConfigurationProperties`bean `@DataJdbcTest` `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  5. | | 由启用了自动配置的列表`@DataJdbcTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  6. | :---: | --- |
  7. 默认情况下,Data JDBC测试是事务性的,并在每个测试结束时回滚。有关更多详细信息,请参见Spring Framework参考文档中的[相关部分](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#testcontext-tx-enabling-transactions)。如果这不是您想要的,则可以禁用测试或整个测试类的事务管理,如[JDBC示例所示](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jdbc-test)。<br />如果您希望测试针对真实数据库运行,则可以使用`@AutoConfigureTestDatabase`与相同的注释方式`DataJpaTest`。(请参阅“[自动配置的数据JPA测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test)”。)
  8. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-jooq-test"></a>
  9. #### 26.3.19。自动配置的jOOQ测试
  10. 您可以使用`@JooqTest``@JdbcTest`jOOQ相关的测试类似的方式进行测试。由于jOOQ严重依赖与数据库模式相对应的基于Java的模式,因此使用现有的模式`DataSource`。如果要用内存数据库替换它,可以使用`@AutoConfigureTestDatabase`覆盖这些设置。(有关将jOOQSpring Boot结合使用的更多信息,请参阅本章前面的“[使用jOOQ](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-jooq) ”。)使用注释时,不会扫描常规`@Component`和`@ConfigurationProperties`bean `@JooqTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  11. | | 由启用了自动配置的列表`@JooqTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  12. | :---: | --- |
  13. `@JooqTest`配置一个`DSLContext`。以下示例显示了`@JooqTest`正在使用的注释:

import org.jooq.DSLContext; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.jooq.JooqTest; @JooqTest class ExampleJooqTests { @Autowired private DSLContext dslContext; }

  1. JOOQ测试是事务性的,默认情况下会在每个测试结束时回滚。如果这不是您想要的,则可以禁用测试或整个测试类的事务管理,如[JDBC示例所示](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jdbc-test)。
  2. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-mongo-test"></a>
  3. #### 26.3.20。自动配置的数据MongoDB测试
  4. 您可以`@DataMongoTest`用来测试MongoDB应用程序。默认情况下,它配置内存嵌入式MongoDB(如果可用),配置`MongoTemplate`,扫描`@Document`类,并配置Spring Data MongoDB存储库。使用注解时,不会扫描Regular`@Component``@ConfigurationProperties`bean `@DataMongoTest` `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。(有关将MongoDBSpring Boot结合使用的更多信息,请参阅本章前面的“ [MongoDB](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-mongodb) ”。)
  5. | | 的由启用了自动配置设置列表`@DataMongoTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  6. | :---: | --- |
  7. 此类显示`@DataMongoTest`正在使用的注释:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.data.mongodb.core.MongoTemplate; @DataMongoTest class ExampleDataMongoTests { @Autowired private MongoTemplate mongoTemplate; // }

  1. 内存嵌入式MongoDB通常运行良好,不需要安装任何开发人员,因此通常可以很好地用于测试。但是,如果您希望对真实的MongoDB服务器运行测试,则应排除嵌入式MongoDB自动配置,如以下示例所示:

import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; @DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class) class ExampleDataMongoNonEmbeddedTests { }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-neo4j-test"></a>
  2. #### 26.3.21。自动配置的数据Neo4j测试
  3. 您可以`@DataNeo4jTest`用来测试Neo4j应用程序。默认情况下,它会扫描`@Node`类,并配置Spring Data Neo4j存储库。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@DataNeo4jTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。(有关将Neo4J与Spring Boot结合使用的更多信息,请参阅本章前面的“ [Neo4j](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-neo4j) ”。)
  4. | | 的由启用了自动配置设置列表`@DataNeo4jTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 以下示例显示了在Spring Boot中使用Neo4J测试的典型设置:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest; @DataNeo4jTest class ExampleDataNeo4jTests { @Autowired private YourRepository repository; // }

  1. 默认情况下,Data Neo4j测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参见Spring Framework参考文档中的[相关部分](https://docs.spring.io/spring/docs/5.3.4/reference/html/testing.html#testcontext-tx-enabling-transactions)。如果这不是您想要的,则可以为测试或整个类禁用事务管理,如下所示:

import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @DataNeo4jTest @Transactional(propagation = Propagation.NOT_SUPPORTED) class ExampleNonTransactionalTests { }

  1. | | 被动访问不支持事务测试。如果使用此样式,则必须`@DataNeo4jTest`如上所述配置测试。 |
  2. | :---: | --- |
  3. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-redis-test"></a>
  4. #### 26.3.22。自动配置的数据Redis测试
  5. 您可以`@DataRedisTest`用来测试Redis应用程序。默认情况下,它会扫描`@RedisHash`类并配置Spring Data Redis存储库。使用注解时,不会扫描Regular`@Component``@ConfigurationProperties`bean `@DataRedisTest` `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。(有关在Spring Boot中使用Redis的更多信息,请参阅本章前面的“ [Redis](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-redis) ”。)
  6. | | 的由启用了自动配置设置列表`@DataRedisTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  7. | :---: | --- |
  8. 以下示例显示了`@DataRedisTest`正在使用的注释:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest; @DataRedisTest class ExampleDataRedisTests { @Autowired private YourRepository repository; // }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-ldap-test"></a>
  2. #### 26.3.23。自动配置的数据LDAP测试
  3. 您可以`@DataLdapTest`用来测试LDAP应用程序。默认情况下,它配置内存嵌入式LDAP(如果可用),配置`LdapTemplate`,扫描`@Entry`类,并配置Spring Data LDAP存储库。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@DataLdapTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。(有关将LDAP与Spring Boot结合使用的更多信息,请参阅本章前面的“ [LDAP](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-ldap) ”。)
  4. | | 的由启用了自动配置设置列表`@DataLdapTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 以下示例显示了`@DataLdapTest`正在使用的注释:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest; import org.springframework.ldap.core.LdapTemplate; @DataLdapTest class ExampleDataLdapTests { @Autowired private LdapTemplate ldapTemplate; // }

  1. 内存嵌入式LDAP通常非常适合测试,因为它速度快并且不需要安装任何开发人员。但是,如果您希望对真实的LDAP服务器运行测试,则应排除嵌入式LDAP自动配置,如以下示例所示:

import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration; import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest; @DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class) class ExampleDataLdapNonEmbeddedTests { }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-client"></a>
  2. #### 26.3.24。自动配置的REST客户端
  3. 您可以使用`@RestClientTest`注释来测试REST客户端。默认情况下,它会自动配置Jackson,GSON和Jsonb支持,配置`RestTemplateBuilder`,并添加对的支持`MockRestServiceServer`。使用注解时,不会扫描Regular`@Component`和`@ConfigurationProperties`bean `@RestClientTest`。 `@EnableConfigurationProperties`可用于包括`@ConfigurationProperties`豆类。
  4. | | 的由启用了自动配置设置列表`@RestClientTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 应该使用的`value`或`components`属性来指定要测试的特定Bean `@RestClientTest`,如以下示例所示:

@RestClientTest(RemoteVehicleDetailsService.class) class ExampleRestClientTest { @Autowired private RemoteVehicleDetailsService service; @Autowired private MockRestServiceServer server; @Test void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() throws Exception { this.server.expect(requestTo(“/greet/details”)) .andRespond(withSuccess(“hello”, MediaType.TEXT_PLAIN)); String greeting = this.service.callRestService(); assertThat(greeting).isEqualTo(“hello”); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs"></a>
  2. #### 26.3.25。自动配置的Spring REST Docs测试
  3. 您可以在Mock MVC,REST Assured或WebTestClient的测试中使用`@AutoConfigureRestDocs`批注来使用[Spring REST Docs](https://spring.io/projects/spring-restdocs)。它消除了Spring REST Docs中对JUnit扩展的需求。<br />`@AutoConfigureRestDocs`可以用来覆盖默认的输出目录(`target/generated-snippets`如果您使用的是Maven或`build/generated-snippets`Gradle)。它也可以用于配置出现在任何记录的URI中的主机,方案和端口。
  4. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-mock-mvc"></a>
  5. ##### 使用Mock MVC自动配置的Spring REST Docs测试
  6. `@AutoConfigureRestDocs``MockMvc`在测试基于Servlet的Web应用程序时,将bean定制为使用Spring REST Docs。您可以`@Autowired`像在使用Mock MVC和Spring REST Docs时一样,通过在测试中使用和使用它来注入它,如以下示例所示:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(UserController.class) @AutoConfigureRestDocs class UserDocumentationTests { @Autowired private MockMvc mvc; @Test void listUsers() throws Exception { this.mvc.perform(get(“/users”).accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andDo(document(“list-users”)); } }

  1. 如果您需要对Spring REST Docs配置进行更多控制,而不是的属性所提供的控制`@AutoConfigureRestDocs`,则可以使用`RestDocsMockMvcConfigurationCustomizer`Bean,如以下示例所示:

@TestConfiguration static class CustomizationConfiguration implements RestDocsMockMvcConfigurationCustomizer { @Override public void customize(MockMvcRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }

  1. 如果要使用Spring REST Docs对参数化输出目录的支持,则可以创建一个`RestDocumentationResultHandler`bean`alwaysDo`使用此结果处理程序的自动配置调用,从而导致每个`MockMvc`调用自动生成默认片段。以下示例显示了一个`RestDocumentationResultHandler`正在定义的对象:

@TestConfiguration(proxyBeanMethods = false) static class ResultHandlerConfiguration { @Bean public RestDocumentationResultHandler restDocumentation() { return MockMvcRestDocumentation.document(“{method-name}”); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-web-test-client"></a>
  2. ##### 使用WebTestClient自动配置的Spring REST Docs测试
  3. `@AutoConfigureRestDocs`也可以`WebTestClient`在测试反应式Web应用程序时使用。您可以`@Autowired`像在使用`@WebFluxTest`Spring REST Docs时一样,通过在测试中使用和注入它来进行注入,如以下示例所示:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.test.web.reactive.server.WebTestClient; import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document; @WebFluxTest @AutoConfigureRestDocs class UsersDocumentationTests { @Autowired private WebTestClient webTestClient; @Test void listUsers() { this.webTestClient.get().uri(“/“).exchange().expectStatus().isOk().expectBody() .consumeWith(document(“list-users”)); } }

  1. 如果您需要对Spring REST Docs配置进行更多控制,而不是的属性所提供的控制`@AutoConfigureRestDocs`,则可以使用`RestDocsWebTestClientConfigurationCustomizer`Bean,如以下示例所示:

@TestConfiguration(proxyBeanMethods = false) public static class CustomizationConfiguration implements RestDocsWebTestClientConfigurationCustomizer { @Override public void customize(WebTestClientRestDocumentationConfigurer configurer) { configurer.snippets().withEncoding(“UTF-8”); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-docs-rest-assured"></a>
  2. ##### 具有REST保证的自动配置的Spring REST Docs测试
  3. `@AutoConfigureRestDocs`使`RequestSpecification`预配置为使用Spring REST Docs的bean可用于您的测试。您可以`@Autowired`像在使用REST Assured和Spring REST Docs时通常使用的那样在测试中使用和注入它,如以下示例所示:

import io.restassured.specification.RequestSpecification; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.web.server.LocalServerPort; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.is; import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @AutoConfigureRestDocs class UserDocumentationTests { @Test void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) { given(documentationSpec).filter(document(“list-users”)).when().port(port).get(“/“).then().assertThat() .statusCode(is(200)); } }

  1. 如果需要对Spring REST Docs配置进行更多控制,而不需要通过的属性提供更多控制`@AutoConfigureRestDocs``RestDocsRestAssuredConfigurationCustomizer`则可以使用Bean,如以下示例所示:

@TestConfiguration(proxyBeanMethods = false) public static class CustomizationConfiguration implements RestDocsRestAssuredConfigurationCustomizer { @Override public void customize(RestAssuredRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-autoconfigured-webservices"></a>
  2. #### 26.3.26。自动配置的Spring Web Services测试
  3. 您可以使用`@WebServiceClientTest`Spring Web Services项目来测试使用呼叫Web服务的应用程序。默认情况下,它会配置一个模拟`WebServiceServer`bean并自动自定义您的`WebServiceTemplateBuilder`。(有关在Spring Boot中结合使用Web服务的更多信息,请参阅本章前面的“ [Web服务](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-webservices)”。)
  4. | | 的由启用了自动配置设置列表`@WebServiceClientTest`可以[在附录中找到](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)。 |
  5. | :---: | --- |
  6. 以下示例显示了`@WebServiceClientTest`正在使用的注释:

@WebServiceClientTest(ExampleWebServiceClient.class) class WebServiceClientIntegrationTests { @Autowired private MockWebServiceServer server; @Autowired private ExampleWebServiceClient client; @Test void mockServerCall() { this.server.expect(payload(new StringSource(““))).andRespond( withPayload(new StringSource(“200“))); assertThat(this.client.test()).extracting(Response::getStatus).isEqualTo(200); } }

  1. <a name="boot-features-testing-spring-boot-applications-testing-auto-configured-additional-auto-config"></a>
  2. #### 26.3.27。额外的自动配置和切片
  3. 每个切片提供一个或多个`@AutoConfigure…`注释,这些注释即定义应包含在切片中的自动配置。可以通过创建自定义`@AutoConfigure…`批注或添加`@ImportAutoConfiguration`到测试中来逐个测试地添加其他自动配置,如以下示例所示:

@JdbcTest @ImportAutoConfiguration(IntegrationAutoConfiguration.class) class ExampleJdbcTests { }

  1. | | 确保不要使用常规`@Import`注释来导入自动配置,因为它们是由Spring Boot以特定方式处理的。 |
  2. | :---: | --- |
  3. 或者,可以通过`META-INF/spring.factories`以下示例中所示的注册方式为切片注释的任何使用添加其他自动配置:<br />org.springframework.boot.test.autoconfigure.jdbc.JdbcTest = com.example.IntegrationAutoConfiguration
  4. | | 只要切片或`@AutoConfigure…`注释使用meta注释,就可以通过这种方式进行自定义`@ImportAutoConfiguration` |
  5. | :---: | --- |
  6. <a name="boot-features-testing-spring-boot-applications-testing-user-configuration"></a>
  7. #### 26.3.28。用户配置和切片
  8. 如果您以合理的方式[组织代码](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot-structuring-your-code),`@SpringBootApplication`则[默认情况下](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-detecting-config)将[使用](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-detecting-config)类作为测试的配置。<br />因此,重要的是不要用特定于应用程序功能特定区域的配置设置来乱扔应用程序的主类。<br />假设您正在使用Spring Batch,并且依赖于它的自动配置。您可以定义`@SpringBootApplication`如下:

@SpringBootApplication @EnableBatchProcessing public class SampleApplication { … }

  1. 因为此类是测试的源配置,所以任何切片测试实际上都尝试启动Spring Batch,这绝对不是您想要执行的操作。建议的方法是将特定于区域的配置移到`@Configuration`与您的应用程序相同级别的单独的类,如以下示例所示:

@Configuration(proxyBeanMethods = false) @EnableBatchProcessing public class BatchConfiguration { … }

  1. | | 根据您应用程序的复杂性,您可以`@Configuration`为您的自定义设置一个类,也可以为每个域区域指定一个类。后一种方法使您可以在其中的一个测试中启用`@Import`注释(如有必要),并带有注释。 |
  2. | :---: | --- |
  3. 测试切片将`@Configuration`类别排除在扫描范围之外。例如,对于a `@WebMvcTest`,以下配置将`WebMvcConfigurer`在测试切片加载的应用程序上下文中不包括给定的bean

@Configuration public class WebConfiguration { @Bean public WebMvcConfigurer testConfigurer() { return new WebMvcConfigurer() { … }; } }

  1. 但是,以下配置将导致自定义`WebMvcConfigurer`由测试片加载。

@Component public class TestWebMvcConfigurer implements WebMvcConfigurer { … }

  1. 混乱的另一个来源是类路径扫描。假设在以合理的方式组织代码的同时,您需要扫描其他程序包。您的应用程序可能类似于以下代码:

@SpringBootApplication @ComponentScan({ “com.example.app”, “org.acme.another” }) public class SampleApplication { … }

  1. 这样做有效地覆盖了默认的组件扫描指令,并且具有扫描这两个软件包的副作用,而与您选择的切片无关。例如,`@DataJpaTest`似乎突然扫描了应用程序的组件和用户配置。同样,将自定义指令移至单独的类是解决此问题的好方法。
  2. | | 如果这不是您的选择,则可以`@SpringBootConfiguration`在测试层次结构中的某个位置创建一个位置,以便代替使用它。另外,您可以为测试指定一个源,从而禁用查找默认源的行为。 |
  3. | :---: | --- |
  4. <a name="boot-features-testing-spring-boot-applications-with-spock"></a>
  5. #### 26.3.29。使用Spock测试Spring Boot应用程序
  6. 如果您希望使用Spock测试Spring Boot应用程序,则应在`spock-spring`应用程序的构建中添加对Spock模块的依赖。 `spock-spring`Spring的测试框架集成到Spock中。建议您使用Spock 1.2或更高版本,以受益于SpockSpring框架和Spring Boot集成的许多改进。有关更多详细信息,请参见[SpockSpring模块的文档](http://spockframework.org/spock/docs/1.2/modules.html#_spring_module)。
  7. <a name="boot-features-test-utilities"></a>
  8. ### 26.4。测试工具
  9. 在测试应用程序时通常会有用的一些测试实用程序类作为打包在一起`spring-boot`
  10. <a name="boot-features-configfileapplicationcontextinitializer-test-utility"></a>
  11. #### 26.4.1。ConfigFileApplicationContextInitializer
  12. `ConfigFileApplicationContextInitializer`是一个`ApplicationContextInitializer`可以应用于测试以加载Spring Boot`application.properties`文件的工具。如不需要`@SpringBootTest`以下示例所示,可以在不需要由提供的全部功能时使用它:

@ContextConfiguration(classes = Config.class, initializers = ConfigFileApplicationContextInitializer.class)

  1. | | `ConfigFileApplicationContextInitializer`单独 使用不能为`@Value("${…}")`注射提供支持。唯一的工作是确保将`application.properties`文件加载到Spring的中`Environment`。为了获得`@Value`支持,您需要另外配置a`PropertySourcesPlaceholderConfigurer`或使用`@SpringBootTest`,后者会为您自动配置一个。 |
  2. | :---: | --- |
  3. <a name="boot-features-test-property-values"></a>
  4. #### 26.4.2。TestPropertyValues
  5. `TestPropertyValues`可让您快速将属性添加到`ConfigurableEnvironment``ConfigurableApplicationContext`。您可以使用`key=value`字符串来调用它,如下所示:

TestPropertyValues.of(“org=Spring”, “name=Boot”).applyTo(env);

  1. <a name="boot-features-output-capture-test-utility"></a>
  2. #### 26.4.3。OutputCapture
  3. `OutputCapture`是一个`Extension`可用于捕获`System.out`和`System.err`输出的JUnit 。要使用add`@ExtendWith(OutputCaptureExtension.class)`和ject`CapturedOutput`作为测试类构造函数或测试方法的参数,如下所示:

@ExtendWith(OutputCaptureExtension.class) class OutputCaptureTests { @Test void testName(CapturedOutput output) { System.out.println(“Hello World!”); assertThat(output).contains(“World”); } }

  1. <a name="boot-features-rest-templates-test-utility"></a>
  2. #### 26.4.4。TestRestTemplate
  3. `TestRestTemplate`是Spring的一种方便替代方法,`RestTemplate`在集成测试中很有用。您可以使用普通模板或发送基本HTTP身份验证(带有用户名和密码)的模板。在这两种情况下,模板都不会通过在服务器端错误上引发异常来以易于测试的方式运行。
  4. | | Spring Framework 5.0提供了一个新功能`WebTestClient`,可用于[WebFlux集成测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-webflux-tests)以及[WebFlux和MVC端到端测试](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server)。与相比,它为声明提供了流畅的API `TestRestTemplate`。 |
  5. | :---: | --- |
  6. 建议(但不是强制性的)使用Apache HTTP Client(版本4.3.2或更高版本)。如果您在类路径中具有该名称,则`TestRestTemplate`通过适当配置客户端来做出响应。如果确实使用Apache的HTTP客户端,则会启用一些其他易于测试的功能:
  7. - 不遵循重定向(因此您可以声明响应位置)。<br />
  8. - Cookies被忽略(因此模板是无状态的)。<br />
  9. `TestRestTemplate` 可以在集成测试中直接实例化,如以下示例所示:

public class MyTest { private TestRestTemplate template = new TestRestTemplate(); @Test public void testRequest() throws Exception { HttpHeaders headers = this.template.getForEntity( “https://myhost.example.com/example“, String.class).getHeaders(); assertThat(headers.getLocation()).hasHost(“other.example.com”); } }

  1. 另外,如果将`@SpringBootTest`注释与`WebEnvironment.RANDOM_PORT`或结合使用,则`WebEnvironment.DEFINED_PORT`可以注入完全配置的注释`TestRestTemplate`并开始使用它。如有必要,可以通过`RestTemplateBuilder`Bean应用其他定制。未指定主机和端口的所有URL都会自动连接到嵌入式服务器,如以下示例所示:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class SampleWebClientTests { @Autowired private TestRestTemplate template; @Test void testRequest() { HttpHeaders headers = this.template.getForEntity(“/example”, String.class).getHeaders(); assertThat(headers.getLocation()).hasHost(“other.example.com”); } @TestConfiguration(proxyBeanMethods = false) static class Config { @Bean RestTemplateBuilder restTemplateBuilder() { return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)) .setReadTimeout(Duration.ofSeconds(1)); } } }

  1. <a name="boot-features-websockets"></a>
  2. ## 27. WebSockets
  3. Spring Boot为嵌入式Tomcat,Jetty和Undertow提供了WebSockets自动配置。如果将war文件部署到独立容器,Spring Boot会假定该容器负责其WebSocket支持的配置。<br />Spring Framework为MVC Web应用程序提供了[丰富的WebSocket支持](https://docs.spring.io/spring/docs/5.3.4/reference/html/web.html#websocket),可以通过该`spring-boot-starter-websocket`模块轻松访问。<br />WebSocket支持也可用于[响应式Web应用程序,](https://docs.spring.io/spring/docs/5.3.4/reference/html/web-reactive.html#webflux-websocket)并且需要在以下位置包括WebSocket API `spring-boot-starter-webflux`:

javax.websocket javax.websocket-api

  1. <a name="boot-features-webservices"></a>
  2. ## 28.网络服务
  3. Spring Boot提供了Web服务自动配置,因此您所需要做的就是定义您的`Endpoints`。<br />在[春天的Web服务功能](https://docs.spring.io/spring-ws/docs/3.0.10.RELEASE/reference/)可以与轻松访问`spring-boot-starter-webservices`模块。<br />`SimpleWsdl11Definition`并且`SimpleXsdSchema`可以分别为您的WSDL和XSD自动创建bean。为此,请配置其位置,如以下示例所示:<br />特性<br />Yaml

spring: webservices: wsdl-locations: “classpath:/wsdl”

  1. <a name="boot-features-webservices-template"></a>
  2. ### 28.1。使用WebServiceTemplate调用Web服务
  3. 如果需要从应用程序调用远程Web服务,则可以使用[`WebServiceTemplate`](https://docs.spring.io/spring-ws/docs/3.0.10.RELEASE/reference/#client-web-service-template)该类。由于`WebServiceTemplate`实例在使用前通常需要自定义,因此Spring Boot不提供任何单个自动配置的`WebServiceTemplate`bean。但是,它会自动配置a `WebServiceTemplateBuilder`,可以`WebServiceTemplate`在需要时创建实例。<br />以下代码显示了一个典型示例:

@Service public class MyService { private final WebServiceTemplate webServiceTemplate; public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) { this.webServiceTemplate = webServiceTemplateBuilder.build(); } public DetailsResp someWsCall(DetailsReq detailsReq) { return (DetailsResp) this.webServiceTemplate.marshalSendAndReceive(detailsReq, new SoapActionCallback(ACTION)); } }

  1. 默认情况下,使用类路径上的可用HTTP客户端库来`WebServiceTemplateBuilder`检测基于HTTP的适当内容`WebServiceMessageSender`。您还可以如下自定义读取和连接超时:

@Bean public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) { return builder.messageSenders(new HttpWebServiceMessageSenderBuilder() .setConnectTimeout(5000).setReadTimeout(2000).build()).build(); }

  1. <a name="boot-features-developing-auto-configuration"></a>
  2. ## 29.创建自己的自动配置
  3. 如果您在开发共享库的公司中工作,或者在开源或商业库中工作,则可能要开发自己的自动配置。自动配置类可以捆绑在外部jar中,并且仍由Spring Boot拾取。<br />自动配置可以与“启动器”相关联,该“启动器”提供自动配置代码以及您将使用的典型库。我们首先介绍您构建自己的自动配置所需的知识,然后继续[进行创建自定义启动器所需](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-custom-starter)的[典型步骤](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-custom-starter)。
  4. | | 可以使用一个[演示项目](https://github.com/snicoll-demos/spring-boot-master-auto-configuration)来展示如何逐步创建入门程序。 |
  5. | :---: | --- |
  6. <a name="boot-features-understanding-auto-configured-beans"></a>
  7. ### 29.1。了解自动配置的Bean
  8. 在后台,自动配置是通过标准`@Configuration`类实现的。其他`@Conditional`注释用于约束何时应应用自动配置。通常,自动配置类使用`@ConditionalOnClass`和`@ConditionalOnMissingBean`注释。这样可以确保仅当找到相关的类并且没有声明自己的类时,自动配置才适用`@Configuration`。<br />您可以浏览的源代码[`spring-boot-autoconfigure`](https://github.com/spring-projects/spring-boot/tree/v2.4.3/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure)以查看`@Configuration`Spring提供的类(请参见[`META-INF/spring.factories`](https://github.com/spring-projects/spring-boot/tree/v2.4.3/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories)文件)。
  9. <a name="boot-features-locating-auto-configuration-candidates"></a>
  10. ### 29.2。查找自动配置候选人
  11. Spring Boot检查`META-INF/spring.factories`发布的jar中是否存在文件。该文件应在`EnableAutoConfiguration`键下列出您的配置类,如以下示例所示:<br />org.springframework.boot.autoconfigure.EnableAutoConfiguration = \<br />com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\<br />com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
  12. | | 自动配置_只能_以这种方式加载。确保在特定的程序包空间中定义它们,并且决不要将它们作为组件扫描的目标。此外,自动配置类不应启用组件扫描以查找其他组件。`@Import`应该使用特定的。 |
  13. | :---: | --- |
  14. 如果需要按特定顺序应用配置,则可以使用[`@AutoConfigureAfter`](https://github.com/spring-projects/spring-boot/tree/v2.4.3/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigureAfter.java)或[`@AutoConfigureBefore`](https://github.com/spring-projects/spring-boot/tree/v2.4.3/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigureBefore.java)注释。例如,如果您提供特定于Web的配置,则可能需要在之后应用类`WebMvcAutoConfiguration`。<br />如果您要订购某些彼此之间不具有直接了解的自动配置,则也可以使用`@AutoConfigureOrder`。该注释与常规注释具有相同的语义,`@Order`但为自动配置类提供了专用顺序。<br />与标准`@Configuration`类一样,自动配置类的应用顺序仅会影响其bean的定义顺序。随后创建这些bean的顺序不受影响,并由每个bean的依赖关系和任何`@DependsOn`关系确定。
  15. <a name="boot-features-condition-annotations"></a>
  16. ### 29.3。条件注释
  17. 您几乎总是希望`@Conditional`在自动配置类中包含一个或多个注释。该`@ConditionalOnMissingBean`注释是用来让开发者重写自动配置,如果他们不满意自己的缺省值一个常见的例子。<br />Spring Boot包含许多`@Conditional`注释,您可以通过注释`@Configuration`类或单个`@Bean`方法在您自己的代码中重用它们。这些注释包括:
  18. - [上课条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-class-conditions)<br />
  19. - [豆条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-bean-conditions)<br />
  20. - [物业条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-property-conditions)<br />
  21. - [资源条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-resource-conditions)<br />
  22. - [Web应用条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-web-application-conditions)<br />
  23. - [SpEL表达条件](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-spel-conditions)<br />
  24. <a name="boot-features-class-conditions"></a>
  25. #### 29.3.1。上课条件
  26. 的`@ConditionalOnClass`和`@ConditionalOnMissingClass`注解让`@Configuration`类基于特定类的存在或不存在被包括在内。由于注释元数据是使用[ASM](https://asm.ow2.io/)进行解析的`value`,因此即使该类实际上未真正出现在正在运行的应用程序类路径上,您也可以使用该属性来引用真实的类。`name`如果您更喜欢通过使用`String`值来指定类名称,则也可以使用该属性。<br />这种机制不适用于`@Bean`通常以返回类型为条件的目标的方法:在方法的条件适用之前,JVM将加载该类和可能处理的方法引用,如果该类不是当下。<br />要处理这种情况,`@Configuration`可以使用一个单独的类来隔离条件,如以下示例所示:

@Configuration(proxyBeanMethods = false) // Some conditions public class MyAutoConfiguration { // Auto-configured beans @Configuration(proxyBeanMethods = false) @ConditionalOnClass(EmbeddedAcmeService.class) static class EmbeddedConfiguration { @Bean @ConditionalOnMissingBean public EmbeddedAcmeService embeddedAcmeService() { … } } }

  1. | | 如果您使用元批注`@ConditionalOnClass``@ConditionalOnMissingClass`作为元批注的一部分来组成自己的组合批注,`name`则在不处理这种情况下,必须使用引用类。 |
  2. | :---: | --- |
  3. <a name="boot-features-bean-conditions"></a>
  4. #### 29.3.2。豆条件
  5. `@ConditionalOnBean``@ConditionalOnMissingBean`注解让豆基于特定豆的存在或不存在被包括在内。您可以使用该`value`属性按类型`name`指定bean或按名称指定bean。该`search`属性使您可以限制`ApplicationContext`搜索bean时应考虑的层次结构。<br />当放置在`@Bean`方法上时,目标类型默认为方法的返回类型,如以下示例所示:

@Configuration(proxyBeanMethods = false) public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService() { … } }

  1. 在前面的例子中,`myService`豆将被创建如果没有类型的豆`MyService`已经包含在所述`ApplicationContext`
  2. | | 您需要非常注意添加bean定义的顺序,因为这些条件是根据到目前为止已处理的内容来评估的。因此,我们建议在自动配置类上仅使用`@ConditionalOnBean``@ConditionalOnMissingBean`批注(因为保证在添加任何用户定义的Bean定义后即可加载它们)。 |
  3. | :---: | --- |
  4. | | `@ConditionalOnBean`并且`@ConditionalOnMissingBean`不要阻止`@Configuration`类的创建。在类级别使用这些条件`@Bean`与使用注释标记每个包含的方法之间的唯一区别是,`@Configuration`如果条件不匹配,则前者会阻止将该类注册为bean |
  5. | :---: | --- |
  6. | | 声明`@Bean`方法时,请在方法的返回类型中提供尽可能多的类型信息。例如,如果您的bean的具体类实现一个接口,则bean方法的返回类型应该是具体的类而不是接口。`@Bean`当使用bean条件时,在方法中提供尽可能多的类型信息尤为重要,因为它们的评估只能依赖于方法签名中可用的类型信息。 |
  7. | :---: | --- |
  8. <a name="boot-features-property-conditions"></a>
  9. #### 29.3.3。物业条件
  10. `@ConditionalOnProperty`注解让基于Spring的环境属性配置包括在内。使用`prefix``name`属性来指定应检查的属性。默认情况下,`false`匹配存在且不等于的任何属性。您还可以使用`havingValue``matchIfMissing`属性创建更高级的检查。
  11. <a name="boot-features-resource-conditions"></a>
  12. #### 29.3.4。资源条件
  13. `@ConditionalOnResource`注解让配置被包括仅当特定资源是否存在。资源可通过使用通常的弹簧约定来指定,如显示在下面的例子:`file:/home/user/test.dat`
  14. <a name="boot-features-web-application-conditions"></a>
  15. #### 29.3.5。Web应用条件
  16. `@ConditionalOnWebApplication``@ConditionalOnNotWebApplication`注释,让配置包含依赖于应用程序是否是一个“Web应用程序”。基于ServletWeb应用程序是使用Spring `WebApplicationContext`,定义`session`范围或具有的任何应用程序`ConfigurableWebEnvironment`。响应式Web应用程序是使用`ReactiveWebApplicationContext`或具有的任何应用程序`ConfigurableReactiveWebEnvironment`。<br />该`@ConditionalOnWarDeployment`注解让配置取决于应用是否是被部署到一个容器中的传统WAR应用程序被包括在内。对于嵌入式服务器运行的应用程序,此条件将不匹配。
  17. <a name="boot-features-spel-conditions"></a>
  18. #### 29.3.6。SpEL表达条件
  19. `@ConditionalOnExpression`注解让基于一个的结果配置被包括[使用SpEL表达](https://docs.spring.io/spring/docs/5.3.4/reference/html/core.html#expressions)。
  20. <a name="boot-features-test-autoconfig"></a>
  21. ### 29.4。测试您的自动配置
  22. 自动配置可能受许多因素影响:用户配置(`@Bean`定义和`Environment`自定义),条件评估(特定库的存在)以及其他因素。具体而言,每个测试都应创建一个定义良好的定义`ApplicationContext`,以代表这些定制的组合。 `ApplicationContextRunner`提供了实现此目标的好方法。<br />`ApplicationContextRunner`通常定义为测试类的一个字段,以收集基本的通用配置。以下示例确保`UserServiceAutoConfiguration`始终调用该示例:

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));

  1. | | 如果必须定义多个自动配置,则无需按与运行应用程序时完全相同的顺序调用它们的声明。 |
  2. | :---: | --- |
  3. 每个测试都可以使用运行器来表示特定的用例。例如,下面的示例调用一个用户配置(`UserConfiguration`),并检查自动配置是否正确退出。调用`run`提供了可与一起使用的回调上下文`AssertJ`

@Test void defaultServiceBacksOff() { this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> { assertThat(context).hasSingleBean(UserService.class); assertThat(context).getBean(“myUserService”).isSameAs(context.getBean(UserService.class)); }); } @Configuration(proxyBeanMethods = false) static class UserConfiguration { @Bean UserService myUserService() { return new UserService(“mine”); } }

  1. 也可以轻松自定义`Environment`,如以下示例所示:

@Test void serviceNameCanBeConfigured() { this.contextRunner.withPropertyValues(“user.name=test123”).run((context) -> { assertThat(context).hasSingleBean(UserService.class); assertThat(context.getBean(UserService.class).getName()).isEqualTo(“test123”); }); }

  1. 跑步者也可以用来显示`ConditionEvaluationReport`。可以按级别`INFO``DEBUG`水平打印报告。以下示例显示了如何`ConditionEvaluationReportLoggingListener`在自动配置测试中使用来打印报告。

@Test void autoConfigTest() { ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener( LogLevel.INFO); ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withInitializer(initializer).run((context) -> { // Do something… }); }

  1. <a name="simulating-a-web-context"></a>
  2. #### 29.4.1。模拟Web上下文
  3. 如果您需要测试仅在Servlet或Reactive Web应用程序上下文中运行的自动配置,请分别使用`WebApplicationContextRunner`或`ReactiveWebApplicationContextRunner`。
  4. <a name="overriding-the-classpath"></a>
  5. #### 29.4.2。覆盖类路径
  6. 还可以测试在运行时不存在特定的类和/或程序包时发生的情况。Spring Boot附带了一个`FilteredClassLoader`跑步者可以轻松使用的。在以下示例中,我们断言如果`UserService`不存在,则将自动禁用自动配置:

@Test void serviceIsIgnoredIfLibraryIsNotPresent() { this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class)) .run((context) -> assertThat(context).doesNotHaveBean(“userService”)); }

  1. <a name="boot-features-custom-starter"></a>
  2. ### 29.5。创建自己的入门
  3. 一个典型的Spring Boot启动器包含用于自动配置和自定义给定技术的基础结构的代码,我们称其为“ acme”。为了使其易于扩展,可以将专用命名空间中的许多配置密钥公开给环境。最后,提供了一个“启动程序”依赖项,以帮助用户尽可能轻松地入门。<br />具体而言,自定义启动器可以包含以下内容:
  4. - `autoconfigure`包含“ acme”的自动配置代码的模块。<br />
  5. - 将`starter`其提供给一个依赖模块`autoconfigure`模块以及“ACME”,并且通常是有用的任何附加的依赖性。简而言之,添加启动程序应提供开始使用该库所需的一切。<br />
  6. 完全没有必要将这两个模块分开。如果“ acme”具有多种功能,选项或可选功能,则最好将自动配置分开,因为您可以清楚地表示某些功能是可选的。此外,您还可以制作一个入门程序,以提供有关那些可选依赖项的意见。同时,其他人只能依靠该`autoconfigure`模块,并以不同的观点来设计自己的启动器。<br />如果自动配置相对简单并且不具有可选功能,则将两个模块合并在启动器中绝对是一种选择。
  7. <a name="boot-features-custom-starter-naming"></a>
  8. #### 29.5.1。命名
  9. 您应该确保为启动器提供适当的名称空间。`spring-boot`即使使用其他Maven,也不要以模块名称开头`groupId`。将来,我们可能会为您自动配置的内容提供官方支持。<br />根据经验,您应该在启动器后命名一个组合模块。例如,假设您要为“ acme”创建启动器,并命名自动配置模块`acme-spring-boot`和启动器`acme-spring-boot-starter`。如果只有一个将两者结合的模块,请命名为`acme-spring-boot-starter`。
  10. <a name="boot-features-custom-starter-configuration-keys"></a>
  11. #### 29.5.2。配置键
  12. 如果您的入门者提供了配置密钥,请为它们使用唯一的名称空间。特别是,不包括你的名字空间去春Boot使用键(如`server`,`management`,`spring`,等)。如果使用相同的名称空间,将来我们可能会以破坏模块的方式修改这些名称空间。根据经验,所有键都以您拥有的名称空间(例如`acme`)为前缀。<br />通过为每个属性添加字段javadoc来确保记录了配置键,如以下示例所示:

@ConfigurationProperties(“acme”) public class AcmeProperties { /**

  1. * Whether to check the location of acme resources.
  2. */
  3. private boolean checkLocation = true;
  4. /**
  5. * Timeout for establishing a connection to the acme server.
  6. */
  7. private Duration loginTimeout = Duration.ofSeconds(3);
  8. // getters & setters

}

  1. | | 您仅应将纯文本与`@ConfigurationProperties`Javadoc字段一起使用,因为在将纯文本添加到JSON之前不会对其进行处理。 |
  2. | :---: | --- |
  3. 以下是我们内部遵循的一些规则,以确保描述一致:
  4. - 请勿以“ The”或“ A”开头描述。<br />
  5. - 对于`boolean`类型,请从“是否”或“启用”开始描述。<br />
  6. - 对于基于集合的类型,请以“以逗号分隔的列表”开始描述<br />
  7. - 如果默认单位与毫秒不同,请使用`java.time.Duration`而不是`long`并描述默认单位,例如“如果未指定持续时间后缀,将使用秒”。<br />
  8. - 除非必须在运行时确定默认值,否则请不要在描述中提供默认值。<br />
  9. 确保[触发元数据生成,](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-configuration-metadata.html#configuration-metadata-annotation-processor)以便IDE协助也可用于您的密钥。您可能需要查看生成的元数据(`META-INF/spring-configuration-metadata.json`),以确保正确记录了您的密钥。在兼容的IDE中使用自己的启动程序也是验证元数据质量的好主意。
  10. <a name="boot-features-custom-starter-module-autoconfigure"></a>
  11. #### 29.5.3。“自动配置”模块
  12. `autoconfigure`模块包含开始使用该库所需的所有内容。它还可能包含配置键定义(例如`@ConfigurationProperties`)和可用于进一步自定义组件初始化方式的任何回调接口。
  13. | | 您应该将对库的依赖项标记为可选,以便可以`autoconfigure`更轻松地将模块包含在项目中。如果这样做,则不提供该库,并且默认情况下,Spring Boot会后退。 |
  14. | :---: | --- |
  15. Spring Boot使用注释处理器来收集元数据文件(`META-INF/spring-autoconfigure-metadata.properties`)中自动配置的条件。如果存在该文件,它将用于急切过滤不匹配的自动配置,这将缩短启动时间。建议在包含自动配置的模块中添加以下依赖项:

org.springframework.boot spring-boot-autoconfigure-processor true

  1. 如果您直接在应用程序中定义了自动配置,请确保配置,`spring-boot-maven-plugin`以防止`repackage`目标将依赖项添加到胖罐中:

org.springframework.boot spring-boot-maven-plugin org.springframework.boot spring-boot-autoconfigure-processor

  1. 对于Gradle 4.5和更早版本,应在`compileOnly`配置中声明依赖项,如以下示例所示:

dependencies { compileOnly “org.springframework.boot:spring-boot-autoconfigure-processor” }

  1. 对于Gradle 4.6和更高版本,应在`annotationProcessor`配置中声明依赖项,如以下示例所示:

dependencies { annotationProcessor “org.springframework.boot:spring-boot-autoconfigure-processor” }

  1. <a name="boot-features-custom-starter-module-starter"></a>
  2. #### 29.5.4。启动模块
  3. 起动器确实是一个空罐子。其唯一目的是提供必要的依赖关系以使用库。您可以将其视为对入门所需的看法。<br />不要对添加了启动器的项目做出假设。如果您要自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很高,则很难提供一组适当的_默认_依赖项,因为您应避免包括对于库的典型用法而言不必要的依赖项。换句话说,您不应包括可选的依赖项。
  4. | | 无论哪种方式,您的启动程序都必须`spring-boot-starter`直接或间接引用核心Spring Boot启动程序()(即,如果您的启动程序依赖于另一个启动程序,则无需添加它)。如果仅使用您的自定义启动程序创建项目,则通过使用核心启动程序将尊重Spring Boot的核心功能。 |
  5. | :---: | --- |
  6. <a name="boot-features-kotlin"></a>
  7. ## 30. Kotlin支持
  8. [Kotlin](https://kotlinlang.org/)是针对JVM(和其他平台)的静态类型的语言,它允许编写简洁明了的代码,同时提供与用Java编写的现有库的[互操作性](https://kotlinlang.org/docs/reference/java-interop.html)。<br />Spring Boot通过利用其他Spring项目(例如Spring Framework,Spring Data和Reactor)中的支持来提供Kotlin支持。有关更多信息,请参见[Spring Framework Kotlin支持文档](https://docs.spring.io/spring/docs/5.3.4/reference/html/languages.html#kotlin)。<br />开始使用Spring Boot和Kotlin的最简单方法是遵循[此综合教程](https://spring.io/guides/tutorials/spring-boot-kotlin/)。您可以通过[start.spring.io](https://start.spring.io/#!language=kotlin)创建新的Kotlin项目。如果需要支持,请随时加入[Kotlin Slack](https://slack.kotlinlang.org/)的#spring频道,或通过[Stack Overflow](https://stackoverflow.com/questions/tagged/spring+kotlin)上的`spring`and`kotlin`标签提问。
  9. <a name="boot-features-kotlin-requirements"></a>
  10. ### 30.1。要求
  11. Spring Boot支持Kotlin1.3.x。要使用Kotlin,`org.jetbrains.kotlin:kotlin-stdlib`并且`org.jetbrains.kotlin:kotlin-reflect`必须存在于类路径中。该`kotlin-stdlib`变种`kotlin-stdlib-jdk7`和`kotlin-stdlib-jdk8`也可以使用。<br />由于[默认情况下Kotlin类是final类](https://discuss.kotlinlang.org/t/classes-final-by-default/166),因此您可能需要配置[kotlin-spring](https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support)插件,以便自动打开[带有](https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support)Spring注释的类,以便对其进行代理。<br />[在Kotlin](https://github.com/FasterXML/jackson-module-kotlin)中序列化/反序列化JSON数据时,需要[Jackson的Kotlin模块](https://github.com/FasterXML/jackson-module-kotlin)。在类路径上找到它会自动注册。如果存在Jackson和Kotlin但不存在Jackson Kotlin模块,则会记录一条警告消息。
  12. | | 如果在[start.spring.io](https://start.spring.io/#!language=kotlin)上引导Kotlin项目,[则](https://start.spring.io/#!language=kotlin)默认情况下会提供这些依赖项和插件。 |
  13. | :---: | --- |
  14. <a name="boot-features-kotlin-null-safety"></a>
  15. ### 30.2。零安全
  16. Kotlin的主要功能之一是[null安全](https://kotlinlang.org/docs/reference/null-safety.html)。它`null`在编译时处理值,而不是将问题推迟到运行时并遇到`NullPointerException`。这有助于消除常见的bug来源,而无需支付诸如此类的包装器的费用`Optional`。Kotlin还允许使用具有可为空值的功能构造,如本[Kotlin中关于null安全的全面指南中所述](https://www.baeldung.com/kotlin-null-safety)。<br />尽管Java不允许人们在其类型系统中表达null安全性,但是Spring Framework,Spring Data和Reactor现在通过易于使用工具的注释为API提供了null安全性。默认情况下,将Kotlin中使用的Java API中的[类型](https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types)识别为放松了空检查的[平台类型](https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types)。 [Kotlin对JSR 305批注的支持](https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support)与可空性[批注](https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support)相结合,为Kotlin中的相关Spring API提供了空安全性。<br />的JSR 305检查可以通过添加被配置`-Xjsr305`具有以下选项的编译标志:`-Xjsr305={strict|warn|ignore}`。默认行为与相同`-Xjsr305=warn`。`strict`从Spring API推断得出的Kotlin类型中,必须考虑到该值的空安全性,但应使用该值,前提是即使在次要发行版之间,Spring API空性声明也可能会演变,并且将来可能会添加更多检查)。
  17. | | 尚不支持泛型类型参数,varargs和数组元素的可空性。有关最新信息,请参见[SPR-15942](https://jira.spring.io/browse/SPR-15942)。另外请注意,Spring Boot自己的API[尚未被注释](https://github.com/spring-projects/spring-boot/issues/10712)。 |
  18. | :---: | --- |
  19. <a name="boot-features-kotlin-api"></a>
  20. ### 30.3。Kotlin API
  21. <a name="boot-features-kotlin-api-runapplication"></a>
  22. #### 30.3.1。runApplication
  23. Spring Boot提供了一种惯用的方式来运行应用程序,`runApplication<MyApplication>(*args)`如下例所示:

import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication class MyApplication fun main(args: Array) { runApplication(*args) }

  1. 这是的直接替代`SpringApplication.run(MyApplication::class.java, *args)`。它还允许自定义应用程序,如以下示例所示:

runApplication(*args) { setBannerMode(OFF) }

  1. <a name="boot-features-kotlin-api-extensions"></a>
  2. #### 30.3.2。扩展名
  3. Kotlin[扩展](https://kotlinlang.org/docs/reference/extensions.html)提供了使用其他功能扩展现有类的功能。Spring Boot Kotlin API利用这些扩展为现有的API添加了新的Kotlin特定的便利。<br />`TestRestTemplate`提供了类似于Spring Framework`RestOperations`在Spring Framework中提供的扩展。除其他事项外,这些扩展使利用Kotlin修饰类型参数成为可能。
  4. <a name="boot-features-kotlin-dependency-management"></a>
  5. ### 30.4。依赖管理
  6. 为了避免在类路径中混合使用不同版本的Kotlin依赖项,Spring Boot会导入Kotlin BOM。<br />使用Maven,可以通过`kotlin.version`属性自定义Kotlin版本,并为提供插件管理`kotlin-maven-plugin`。使用Gradle,Spring Boot插件会自动将其`kotlin.version`与Kotlin插件的版本对齐。<br />Spring Boot还通过导入Kotlin Coroutines BOM管理Coroutines依赖项的版本。可以通过`kotlin-coroutines.version`属性自定义版本。
  7. | | `org.jetbrains.kotlinx:kotlinx-coroutines-reactor`如果一个引导程序对[start.spring.io](https://start.spring.io/#!language=kotlin)至少有一个反应依赖的Kotlin项目,则默认提供依赖。 |
  8. | :---: | --- |
  9. <a name="boot-features-kotlin-configuration-properties"></a>
  10. ### 30.5。@ConfigurationProperties
  11. `@ConfigurationProperties`当与[`@ConstructorBinding`](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-external-config-constructor-binding)具有不可变`val`属性的支持类结合使用时,如以下示例所示:

@ConstructorBinding @ConfigurationProperties(“example.kotlin”) data class KotlinExampleProperties( val name: String, val description: String, val myService: MyService) { data class MyService( val apiToken: String, val uri: URI ) }

  1. | | 要生成[自己的元数据](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-configuration-metadata.html#configuration-metadata-annotation-processor)使用注释处理器,[`kapt`应该配置](https://kotlinlang.org/docs/reference/kapt.html)与`spring-boot-configuration-processor`依赖。请注意,由于kapt提供的模型的限制,某些功能(例如检测默认值或不推荐使用的项目)无法正常工作。 |
  2. | :---: | --- |
  3. <a name="boot-features-kotlin-testing"></a>
  4. ### 30.6。测验
  5. 虽然可以使用JUnit 4测试Kotlin代码,但默认情况下建议使用JUnit 5JUnit 5使测试类可以实例化一次,并可以在该类的所有测试中重新使用。这样就可以在非静态方法上使用`@BeforeAll``@AfterAll`注释,这非常适合Kotlin。<br />要模拟Kotlin类,建议使用[MockK](https://mockk.io/)。如果需要`Mockk`Mockito特定于[`@MockBean`和`@SpyBean`注释](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-mocking-beans)的等效项,则可以使用[SpringMockK](https://github.com/Ninja-Squad/springmockk)提供类似的`@MockkBean`和`@SpykBean`注释。
  6. <a name="boot-features-kotlin-resources"></a>
  7. ### 30.7。资源
  8. <a name="boot-features-kotlin-resources-further-reading"></a>
  9. #### 30.7.1。进一步阅读
  10. - [Kotlin语言参考](https://kotlinlang.org/docs/reference/)<br />
  11. - [Kotlin Slack](https://kotlinlang.slack.com/)(带有专用的#spring频道)<br />
  12. - [带`spring``kotlin`标签的Stackoverflow](https://stackoverflow.com/questions/tagged/spring+kotlin)<br />
  13. - [在浏览器中尝试Kotlin](https://try.kotlinlang.org/)<br />
  14. - [Kotlin博客](https://blog.jetbrains.com/kotlin/)<br />
  15. - [很棒的科特林](https://kotlin.link/)<br />
  16. - [教程:使用Spring BootKotlin构建Web应用程序](https://spring.io/guides/tutorials/spring-boot-kotlin/)<br />
  17. - [使用Kotlin开发Spring Boot应用程序](https://spring.io/blog/2016/02/15/developing-spring-boot-applications-with-kotlin)<br />
  18. - [带有KotlinSpring BootPostgreSQL的地理空间Messenger](https://spring.io/blog/2016/03/20/a-geospatial-messenger-with-kotlin-spring-boot-and-postgresql)<br />
  19. - [在Spring Framework 5.0中引入Kotlin支持](https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0)<br />
  20. - [Spring Framework 5 Kotlin API的功能方式](https://spring.io/blog/2017/08/01/spring-framework-5-kotlin-apis-the-functional-way)<br />
  21. <a name="boot-features-kotlin-resources-examples"></a>
  22. #### 30.7.2。例子
  23. - [spring-boot-kotlin-demo](https://github.com/sdeleuze/spring-boot-kotlin-demo):常规Spring Boot + Spring Data JPA项目<br />
  24. - [mixit](https://github.com/mixitconf/mixit):Spring Boot 2 + WebFlux +响应式Spring Data MongoDB<br />
  25. - [spring-kotlin-fullstack](https://github.com/sdeleuze/spring-kotlin-fullstack):WebFlux Kotlin完整示例,其中Kotlin2js用于前端,而不是JavaScript或TypeScript<br />
  26. - [spring-petclinic-kotlin](https://github.com/spring-petclinic/spring-petclinic-kotlin):Spring PetClinic示例应用程序的Kotlin版本<br />
  27. - [spring-kotlin-deepdive](https://github.com/sdeleuze/spring-kotlin-deepdive):从Boot 1.0 + Java到Boot 2.0 + Kotlin的逐步迁移<br />
  28. - [spring-boot-coroutines-demo](https://github.com/sdeleuze/spring-boot-coroutines-demo):[协程](https://github.com/sdeleuze/spring-boot-coroutines-demo)示例项目<br />
  29. <a name="boot-features-container-images"></a>
  30. ## 31.容器图像
  31. 可以很容易地将Spring Boot胖罐打包为docker映像。但是,像在docker映像中一样,复制和运行胖子罐还有很多弊端。在不打开包装的情况下运行胖罐时,总会有一定的开销,在容器化环境中,这很明显。另一个问题是,将应用程序的代码及其所有依赖项放在Docker映像的一层是次优的。由于重新编译代码的频率可能比升级所用Spring Boot的版本的频率高,因此最好将代码分开一些。如果将jar文件放在应用程序类之前的层中,则Docker通常只需要更改最底层即可从其缓存中拾取其他文件。
  32. <a name="boot-layering-docker-images"></a>
  33. ### 31.1。分层Docker映像
  34. 为了使创建优化的Docker映像更加容易,Spring Boot支持将一个层索引文件添加到jar中。它提供了层的列表以及应包含在其中的罐子的各个部分。索引中的层列表是根据应将层添加到Docker / OCI映像的顺序来排序的。现成的,支持以下层:
  35. - `dependencies` (对于常规发布的依赖项)<br />
  36. - `spring-boot-loader`(适用于`org/springframework/boot/loader`)<br />
  37. - `snapshot-dependencies` (对于快照依赖性)<br />
  38. - `application` (用于应用程序类和资源)<br />
  39. 下面显示了一个`layers.idx`文件示例:
  • “dependencies”:
    • BOOT-INF/lib/library1.jar
    • BOOT-INF/lib/library2.jar
  • “spring-boot-loader”:
    • org/springframework/boot/loader/JarLauncher.class
    • org/springframework/boot/loader/jar/JarEntry.class
  • “snapshot-dependencies”:
    • BOOT-INF/lib/library3-SNAPSHOT.jar
  • “application”:
    • META-INF/MANIFEST.MF
    • BOOT-INF/classes/a/b/C.class ``` 此分层旨在根据应用程序构建之间更改的可能性来分离代码。库代码不太可能在内部版本之间进行更改,因此将其放置在自己的层中,以允许工具重新使用缓存中的层。应用程序代码更可能在内部版本之间进行更改,因此将其隔离在单独的层中。
      对于Maven,请参阅包装分层jar部分,以获取有关在jar中添加层索引的更多详细信息。对于Gradle,请参阅Gradle插件文档的包装分层jar部分

      31.2。建筑容器图像

      Spring Boot应用程序可以使用Dockerfile进行容器,也可以使用Cloud Native Buildpacks创建可在任何地方运行的Docker兼容容器映像

      31.2.1。Dockerfiles

      虽然可以在Dockerfile中仅几行就将Spring Boot胖子罐转换为docker映像,但我们将使用分层功能来创建优化的docker映像。创建包含图层索引文件的spring-boot-jarmode-layertoolsjar时,该jar将作为依赖项添加到jar中。将此jar放在类路径上,您可以在特殊模式下启动应用程序,该模式允许引导代码运行与应用程序完全不同的内容,例如,提取层的内容。
layertools模式不能与包含启动脚本的完全可执行的Spring Boot存档一起使用。构建旨在与一起使用的jar文件时,请禁用启动脚本配置layertools

您可以通过layertoolsjar模式启动jar:

  1. $ java -Djarmode=layertools -jar my-app.jar

这将提供以下输出:

  1. Usage:
  2. java -Djarmode=layertools -jar my-app.jar
  3. Available commands:
  4. list List layers from the jar that can be extracted
  5. extract Extracts layers from the jar for image creation
  6. help Help about any command

extract命令可用于轻松地将应用程序拆分为多个层,以添加到dockerfile中。这是使用的Dockerfile的示例jarmode

  1. FROM adoptopenjdk:11-jre-hotspot as builder
  2. WORKDIR application
  3. ARG JAR_FILE=target/*.jar
  4. COPY ${JAR_FILE} application.jar
  5. RUN java -Djarmode=layertools -jar application.jar extract
  6. FROM adoptopenjdk:11-jre-hotspot
  7. WORKDIR application
  8. COPY --from=builder application/dependencies/ ./
  9. COPY --from=builder application/spring-boot-loader/ ./
  10. COPY --from=builder application/snapshot-dependencies/ ./
  11. COPY --from=builder application/application/ ./
  12. ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

假设以上Dockerfile内容位于当前目录中,则可以使用构建docker映像docker build .,或者可以选择指定应用程序jar的路径,如以下示例所示:
docker build —build-arg JAR_FILE =路径/到/myapp.jar。
这是一个多阶段的dockerfile。构建器阶段提取以后需要的目录。每个COPY命令都与jarmode提取的层有关。
当然,无需使用jarmode即可编写Dockerfile。你可以使用一些组合unzipmv事物向右移动层,但jarmode简化了。

31.2.2。云原生构建包

Dockerfiles只是构建Docker镜像的一种方式。构建docker映像的另一种方法是直接从您的Maven或Gradle插件中使用buildpacks。如果您曾经使用过Cloud Foundry或Heroku等应用程序平台,那么您可能已经使用过buildpack。Buildpacks是平台的一部分,可接收您的应用程序并将其转换为平台可以实际运行的内容。例如,Cloud Foundry的Java buildpack将注意到您正在推送.jar文件并自动添加相关的JRE。
借助Cloud Native Buildpacks,您可以创建可在任何地方运行的Docker兼容映像。Spring Boot直接支持Maven和Gradle的buildpack。这意味着您只需键入一个命令,即可将明智的映像快速地导入本地运行的Docker守护程序。
请参阅各个插件文档,以了解如何将buildpacks与MavenGradle一起使用。

Paketo春季启动buildpack也已更新,以支持该layers.idx文件,以便适用于它的任何定制将由buildpack创建的映像中得到体现。
为了实现可复制的构建和容器图像缓存,Buildpacks可以操纵应用程序资源元数据(例如文件“最后修改的”信息)。您应该确保您的应用程序在运行时不依赖该元数据。在提供静态资源时,Spring Boot可以使用该信息,但是可以通过以下方式禁用该信息:spring.web.resources.cache.use-last-modified

32.下一步阅读

如果您想了解有关本节中讨论的任何类的更多信息,可以查看Spring Boot API文档直接浏览源代码。如果您有特定问题,请查看操作方法部分。
如果您熟悉Spring Boot的核心功能,则可以继续阅读有关准备就绪的功能的信息