Spring Boot Features
本节详细介绍Spring引导。在这里,您可以了解您可能想要使用和自定义的关键特性。如果您还没有这样做,那么您可能需要阅读入门和使用,使您有了良好的基础知识。
version 2.3.4.RELEASE GA
Spring应用程序
SpringApplication
类提供了一种方便的方法来引导从main()
方法启动的 Spring 应用程序。在许多情况下,您可以委派给静态SpringApplication.run
方法,如以下示例所示:
1 | public static void main(String[] args) { |
当您的应用程序启动时,您应该看到类似于以下输出的内容:
1 | . ____ _ __ _ _ |
默认情况下,显示INFO
级别日志记录消息,包括一些相关的启动详细信息,例如启动该应用程序的用户。如果您需要INFO
以外的其他日志级别,则可以按照第 26.4 节“日志级别”中的说明进行设置,
启动失败
如果您的应用程序无法启动,则已注册的FailureAnalyzers
有机会提供专用的错误消息和解决该问题的具体措施。例如,如果您在端口8080
上启动 Web 应用程序,并且该端口已在使用中,则应该看到类似于以下消息的内容:
1 | *************************** |
Note
Spring Boot 提供了众多的
FailureAnalyzer
实现,您可以添加自己的。
如果没有故障分析器能够处理该异常,您仍然可以显示完整情况报告,以更好地了解出了什么问题。为此,您需要org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
启用调试属性或启用调试日志记录。
例如,如果您使用java -jar
运行应用程序,则可以启用debug
属性,如下所示:
1 | $ java -jar myproject-0.0.1-SNAPSHOT.jar --debug |
自定义banner
可以通过将banner.txt
文件添加到 Classpath 或将spring.banner.location
属性设置为此类文件的位置来更改启动时打印的 banner。如果文件的编码不是 UTF-8,则可以设置spring.banner.charset
。除了文本文件之外,您还可以将banner.gif
,banner.jpg
或banner.png
图像文件添加到 Classpath 或设置spring.banner.image.location
属性。图像将转换为 ASCII 艺术作品并打印在任何文本 banner 上方。
在banner.txt
文件中,您可以使用以下任何占位符:
表 23.1 标语变量
Variable | Description |
---|---|
${application.version} |
MANIFEST.MF 中声明的应用程序的版本号。例如,Implementation-Version: 1.0 被打印为1.0 。 |
${application.formatted-version} |
您的应用程序的版本号,以MANIFEST.MF 声明,并设置为显示格式(用方括号括起来并以v 作为前缀)。例如(v1.0) 。 |
${spring-boot.version} |
您正在使用的 Spring Boot 版本。例如2.1.1.RELEASE 。 |
${spring-boot.formatted-version} |
您正在使用的 Spring Boot 版本,已格式化以用于显示(用方括号括起来,并以v 作为前缀)。例如(v2.1.1.RELEASE) 。 |
${Ansi.NAME} (或${AnsiColor.NAME} ,${AnsiBackground.NAME} ,${AnsiStyle.NAME} ) |
其中NAME 是 ANSI 转义代码的名称。有关详情,请参见AnsiPropertySource。 |
${application.title} |
MANIFEST.MF 中声明的应用程序标题。例如Implementation-Title: MyApp 被打印为MyApp 。 |
Tip
如果要以编程方式生成 banner,则可以使用
SpringApplication.setBanner(…)
方法。使用org.springframework.boot.Banner
接口并实现自己的printBanner()
方法。
您还可以使用spring.main.banner-mode
属性来确定 banner 是否必须打印在System.out
(console
)上,发送到配置的 Logger(log
)或根本不打印(off
)。
打印的 banner 以以下名称注册为单例 bean:springBootBanner
。
自定义SpringApplication
如果您不喜欢默认的SpringApplication
,则可以创建一个本地实例并对其进行自定义。例如,要关闭 banner,您可以编写:
1 | public static void main(String[] args) { |
Note
传递给
SpringApplication
的构造函数参数是 Spring bean 的配置源。在大多数情况下,这些是对@Configuration
类的引用,但它们也可以是对 XML 配置或应扫描的程序包的引用。
也可以通过使用application.properties
文件来配置SpringApplication
。有关详细信息,请参见 第 24 章,外部化配置 。
有关配置选项的完整列表,请参见SpringApplication Javadoc。
流式构建器API
如果您需要构建ApplicationContext
层次结构(具有父/子关系的多个上下文),或者您更喜欢使用“Fluent 的”构建器 API,则可以使用SpringApplicationBuilder
。
SpringApplicationBuilder
使您可以将多个方法调用链接在一起,并包括parent
和child
方法,这些方法使您可以创建层次结构,如以下示例所示:
1 | new SpringApplicationBuilder() |
Note
创建
ApplicationContext
层次结构时有一些限制。例如,Web 组件 必须 包含在子上下文中,并且相同的Environment
用于父上下文和子上下文。有关详细信息,请参见SpringApplicationBuilder Javadoc。
应用程序可用性
当部署在平台上时,应用程序可以使用Kubernetes探针等基础设施向平台提供关于其可用性的信息。Spring引导包括对常用的“活跃”和“准备就绪”可用状态的开箱即用支持。如果您正在使用Spring Boot的“actuator”支持,那么这些状态将作为运行状况端点组公开。
此外,您还可以通过将ApplicationAvailability
接口注入您自己的bean来获得可用性状态。
Liveness状态
应用程序的“活动”状态告诉它的内部状态是否允许它正确地工作,或者如果它当前失败了,它自己恢复。中断的“活动”状态意味着应用程序处于无法恢复的状态,基础设施应该重新启动应用程序。
通常,“活动”状态不应该基于外部检查,比如运行状况检查。如果是这样,失败的外部系统(数据库、Web API、外部缓存)将触发大规模重启和跨平台的级联故障。
Spring引导应用程序的内部状态主要由Spring ApplicationContext
表示。如果应用程序上下文已经成功启动,Spring Boot将假定应用程序处于有效状态。一旦上下文被刷新,应用程序就被认为是活动的,请参阅Spring Boot应用程序生命周期和相关应用程序事件。
Readiness状态
应用程序的“准备就绪”状态告诉应用程序是否准备好处理流量。失败的“准备就绪”状态告诉平台现在不应该将流量路由到应用程序。这通常发生在启动时,当CommandLineRunner
和ApplicationRunner
组件正在处理,或在任何时候,如果应用程序认为它处理额外的流量太忙。
一旦调用了应用程序和命令行运行器,就认为应用程序已经准备好了,请参阅Spring Boot应用程序生命周期和相关应用程序事件。
期望在启动期间运行的任务应该由
CommandLineRunner
和ApplicationRunner
组件执行,而不是使用Spring组件生命周期回调,如@PostConstruct
。
管理应用程序可用状态
通过注入ApplicationAvailability
接口并在其上调用方法,应用程序组件可以在任何时候检索当前的可用性状态。更常见的情况是,应用程序希望侦听状态更新或更新应用程序的状态。
例如,我们可以导出应用程序的“准备就绪”状态到一个文件,以便Kubernetes的“exec探针”可以查看这个文件:
1 |
|
我们也可以更新应用程序的状态,当应用程序中断,无法恢复:
1 |
|
Spring Boot为执行器运行状况端点的“活动”和“准备就绪”提供了Kubernetes HTTP探针。在专门的部分中,您可以获得关于在Kubernetes上部署Spring引导应用程序的更多指导。
应用程序事件和侦听器
除了通常的 Spring Framework 事件(例如ContextRefreshedEvent)之外,SpringApplication
还发送一些其他应用程序事件。
Note
有些事件实际上是在创建
ApplicationContext
之前触发的,因此您不能将这些事件注册为@Bean
。您可以使用SpringApplication.addListeners(…)
方法或SpringApplicationBuilder.listeners(…)
方法注册它们。
如果希望这些监听器自动注册,而不管创建应用程序的方式如何,都可以将META-INF/spring.factories
文件添加到项目中,并使用org.springframework.context.ApplicationListener
键引用您的监听器,如以下示例所示:
1 | com.example.project.MyListener = |
应用程序事件在您的应用程序运行时按以下顺序发送:
ApplicationStartingEvent
在运行开始时但在进行任何处理之前(侦听器和初始化器的注册除外)发送。ApplicationEnvironmentPreparedEvent
在上下文中使用的环境已知但在创建上下文之前发送。- 当准备好
ApplicationContext
并且调用了ApplicationContextInitializedEvent
,但在加载任何bean定义之前发送applicationcontextinitialalizer
。 ApplicationPreparedEvent
是在刷新启动之前但加载bean定义之后发送的。ApplicationStartedEvent
是在刷新上下文之后,在调用任何应用程序和命令行运行器之前发送的。- 然后用
AvailabilityChangeEvent
发送一个`LivenessState.CORRECT,表示应用程序是活动的。 - 在调用任何应用程序和
command-line runners
之后发送一个ApplicationReadyEvent
。 - 然后,
AvailabilityChangeEvent
发送一个ReadinessState.ACCEPTING_TRAFFIC
,表示应用程序已准备好为请求提供服务。 - 如果启动时出现异常,则发送
ApplicationFailedEvent
。
上面的列表只包含绑定到SpringApplication
的SpringApplicationEvents
。除此之外,以下事件也在ApplicationPreparedEvent
之后和ApplicationStartedEvent
之前发布:
WebServerInitializedEvent
在WebServer准备好之后发送。ServletWebServerInitializedEvent
和ReactiveWebServerInitializedEvent
分别是servlet和反应变量。- 当刷新
ApplicationContext
时发送ContextRefreshedEvent
。
您通常不需要使用应用程序事件,但是很容易知道它们的存在。在内部,Spring Boot 使用事件来处理各种任务。
应用程序事件是通过使用 Spring Framework 的事件发布机制发送的。此机制的一部分确保在子级上下文中发布给侦听器的事件也可以在任何祖先上下文中发布给侦听器。结果,如果您的应用程序使用SpringApplication
实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。
为了使您的侦听器能够区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware
来注入上下文,或者如果侦听器是 bean,则可以通过使用@Autowired
来注入上下文。
Web环境
SpringApplication
尝试代表您创建正确的ApplicationContext
类型。确定WebApplicationType
的算法非常简单:
- 如果存在 Spring MVC,则使用
AnnotationConfigServletWebServerApplicationContext
- 如果不存在Spring MVC且存在Spring WebFlux,则使用
AnnotationConfigReactiveWebServerApplicationContext
- 否则,使用
AnnotationConfigApplicationContext
这意味着,如果您在同一应用程序中使用 Spring MVC 和 Spring WebFlux 的新WebClient
,则默认使用 Spring MVC。您可以通过调用setWebApplicationType(WebApplicationType)
轻松覆盖它。
也可以完全控制通过调用setApplicationContextClass(…)
所使用的ApplicationContext
类型。
Tip
在 JUnit 测试中使用
SpringApplication
时,通常希望调用setWebApplicationType(WebApplicationType.NONE)
。
访问应用程序参数
如果您需要访问传递给SpringApplication.run(…)
的应用程序参数,则可以注入org.springframework.boot.ApplicationArguments
bean。 ApplicationArguments
接口提供对原始String[]
参数以及已解析的option
和non-option
参数的访问,如以下示例所示:
1 | import org.springframework.boot.*; |
Tip
Spring Boot 还向 Spring
Environment
注册了一个CommandLinePropertySource
。这样,您还可以使用@Value
注解注入单个应用程序参数。
使用ApplicationRunner或CommandLineRunner
如果在SpringApplication
启动后需要运行一些特定的代码,则可以实现ApplicationRunner
或CommandLineRunner
接口。两个接口以相同的方式工作,并提供一个run
方法,该方法在SpringApplication.run(…)
完成之前被调用。
CommandLineRunner
接口以简单的字符串数组提供对应用程序参数的访问,而ApplicationRunner
使用前面讨论的ApplicationArguments
接口。以下示例显示使用run
方法的CommandLineRunner
:
1 | import org.springframework.boot.*; |
如果定义了几个必须按特定顺序调用的CommandLineRunner
或ApplicationRunner
bean,则可以另外实现org.springframework.core.Ordered
接口或使用org.springframework.core.annotation.Order
注解。
应用退出
每个SpringApplication
向 JVM 注册一个关闭钩子,以确保ApplicationContext
在退出时正常关闭。可以使用所有标准的 Spring 生命周期回调(例如DisposableBean
接口或@PreDestroy
注解)。
另外,如果 bean 希望在调用SpringApplication.exit()
时返回特定的退出代码,则可以实现org.springframework.boot.ExitCodeGenerator
接口。然后可以将此退出代码传递给System.exit()
,以将其作为状态代码返回,如以下示例所示:
1 |
|
此外,ExitCodeGenerator
接口可能会通过异常实现。遇到此类异常时,Spring Boot 将返回已实现的getExitCode()
方法提供的退出代码。
管理员功能
通过指定spring.application.admin.enabled
属性,可以为应用程序启用与 Management 员相关的功能。这将在平台MBeanServer
上公开SpringApplicationAdminMXBean。您可以使用此功能来远程 Management Spring Boot 应用程序。对于任何服务包装器实现,此功能也可能很有用。
Tip
如果您想知道应用程序在哪个 HTTP 端口上运行,请使用
local.server.port
键获取属性。Warning
启用此功能时要小心,因为 MBean 公开了一种关闭应用程序的方法。
外部化配置
Spring Boot使您可以外部化配置,以便可以在不同环境中使用相同的应用程序代码。您可以使用属性文件,YAML文件,环境变量和命令行参数来外部化配置。可以使用@Value
注解将属性值直接注入到您的bean中,可以通过Spring的环境抽象进行访问,也可以通过@ConfigurationProperties
绑定到结构化对象。
Spring Boot使用一个非常特殊的PropertySource
顺序,该顺序旨在允许合理地覆盖值。按以下顺序考虑属性:
- 处于活动状态时,
$HOME/.config/spring-boot
目录中的Devtools
全局设置属性。 - 测试上的@TestPropertySource注解。
- 测试中的
properties
属性。在@SpringBootTest和测试注解上可用,用于测试应用程序的特定部分。 - 命令行参数。
- 来自
SPRING_APPLICATION_JSON
的属性(嵌入在环境变量或系统属性中的内联JSON)。 - ServletConfig
的初始化参数。
ServletContext
的初始化参数。- 来自
java:comp/env
的JNDI属性。 - Java系统属性(
System.getProperties()
)。 - 操作系统环境变量。
- 一个
RandomValuePropertySource
,仅具有random.*
属性。 - 打包的jar之外的特定于配置文件的应用程序属性(
application-{profile}.properties
和YAML变体)。 - 打包在jar中的特定于配置文件的应用程序属性(
application-{profile}.properties
和YAML变体)。 - 打包的jar之外的应用程序属性(
application.properties
和YAML变体)。 - 打包在jar中的应用程序属性(
application.properties
和YAML变体)。 @Configuration
类上的@PropertySource
注解。请注意,在刷新应用程序上下文之前,不会将此类属性源添加到环境中。现在配置某些属性(如logging.*
和spring.main.*
)为时已晚,这些属性在刷新开始之前就已读取。默认属性(通过设置
SpringApplication.setDefaultProperties`指定)。
为了提供一个具体的示例,假设您开发一个使用name
属性的@Component
,如以下示例所示:
1 | import org.springframework.stereotype.*; |
在您的应用程序 Classpath 上(例如,在 jar 内),您可以拥有一个application.properties
文件,该文件为name
提供了合理的默认属性值。在新环境中运行时,可以在 jar 外部提供application.properties
文件,该文件将覆盖name
。对于一次性测试,可以使用特定的命令行开关(例如java -jar app.jar --name="Spring"
)启动。
Tip
SPRING_APPLICATION_JSON
属性可以在命令行中提供环境变量。例如,您可以在UNIX shell中使用以下行:
1 SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar在前面的示例中,您在 Spring
Environment
中以acme.name=test
结尾。您还可以在 System 属性中以spring.application.json
的形式提供 JSON,如以下示例所示:
1 java -Dspring.application.json='{"name":"test"}' -jar myapp.jar您还可以使用命令行参数来提供 JSON,如以下示例所示:
1 java -jar myapp.jar --spring.application.json='{"name":"test"}'您还可以将 JSON 作为 JNDI 变量提供,如下所示:
java:comp/env/spring.application.json
。
配置随机值
RandomValuePropertySource
可用于注入随机值(例如,Importing 到机密或测试用例中)。它可以产生整数,longs,uuid 或字符串,如以下示例所示:
1 | my.secret=${random.value} |
random.int*
语法为OPEN value (,max) CLOSE
,其中OPEN,CLOSE
是任何字符,而value,max
是整数。如果提供max
,则value
是最小值,而max
是最大值(不包括)。
访问命令行属性
默认情况下,SpringApplication
将任何命令行选项参数(即以--
开头的参数,例如--server.port=9000
)转换为property
并将其添加到 Spring Environment
。如前所述,命令行属性始终优先于其他属性源。
如果您不想将命令行属性添加到Environment
,则可以使用SpringApplication.setAddCommandLineProperties(false)
禁用它们。
应用程序属性文件
SpringApplication
从以下位置的application.properties
文件中加载属性,并将它们添加到 Spring Environment
中:
- 当前目录的
/config
子目录 - 当前目录
- Classpath
/config
包 - Classpath 根
该列表按优先级排序(在列表较高位置定义的属性会覆盖在较低位置定义的属性)。
Note
您也可以使用 YAML(‘.yml’)文件替代“ .properties”。
如果您不喜欢application.properties
作为配置文件名,则可以通过指定spring.config.name
环境属性来切换到另一个文件名。您还可以使用spring.config.location
环境属性(这是目录位置或文件路径的逗号分隔列表)来引用显式位置。下面的示例演示如何指定其他文件名:
1 | java -jar myproject.jar --spring.config.name=myproject |
下面的示例演示如何指定两个位置:
1 | java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties |
Warning
spring.config.name
和spring.config.location
很早就用于确定必须加载哪些文件,因此必须将它们定义为环境属性(通常是 OS 环境变量,系统属性或命令行参数)。
如果spring.config.location
包含目录(而不是文件),则它们应以/
结尾(并且在运行时,应在加载之前附加从spring.config.name
生成的名称,包括特定于配置文件的文件名)。 spring.config.location
中指定的文件按原样使用,不支持特定于配置文件的变体,并且被任何特定于配置文件的属性覆盖。
配置位置以相反的顺序搜索。默认情况下,配置的位置是classpath:/,classpath:/config/,file:./,file:./config/
。结果搜索顺序如下:
file:./config/
file:./
classpath:/config/
classpath:/
使用spring.config.location
配置自定义配置位置后,它们将替换默认位置。例如,如果将spring.config.location
配置为值classpath:/custom-config/,file:./custom-config/
,则搜索顺序如下:
file:./custom-config/
classpath:custom-config/
或者,当使用spring.config.additional-location
配置自定义配置位置时,除默认位置外还使用它们。在默认位置之前搜索其他位置。例如,如果配置了classpath:/custom-config/,file:./custom-config/
的其他位置,则搜索顺序如下:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/
通过此搜索顺序,您可以在一个配置文件中指定默认值,然后在另一个配置文件中有选择地覆盖这些值。您可以在默认位置之一的application.properties
(或使用spring.config.name
选择的其他任何基本名称)中为应用程序提供默认值。然后,可以在运行时使用自定义位置之一中的其他文件覆盖这些默认值。
Note
如果使用环境变量而不是系统属性,则大多数操作系统都不允许使用句点分隔的键名,但可以使用下划线代替(例如,SPRING_CONFIG_NAME
代替spring.config.name
)。
Note
如果您的应用程序在容器中运行,则可以使用 JNDI 属性(在
java:comp/env
中)或 servlet 上下文初始化参数来代替环境变量或系统属性,也可以使用它们。
特定于配置文件的属性
除了application.properties
个文件之外,还可以使用以下命名约定来定义特定于配置文件的属性:application-{profile}.properties
。 Environment
具有一组默认配置文件(默认情况下为[default]
),如果未设置任何 Active 配置文件,则使用这些配置文件。换句话说,如果未显式激活任何配置文件,则将加载application-default.properties
中的属性。
特定于配置文件的属性是从与标准application.properties
相同的位置加载的,特定于配置文件的文件总是会覆盖非特定文件,无论特定于配置文件的文件是在打包 jar 的内部还是外部。
如果指定了多个配置文件,则采用后赢策略。例如,由spring.profiles.active
属性指定的配置文件将添加到通过SpringApplication
API 配置的配置文件之后,因此具有优先权。
Note
如果您在
spring.config.location
中指定了任何文件,则不会考虑这些文件的特定于配置文件的变体。如果您还想使用特定于配置文件的属性,请使用spring.config.location
中的目录。
属性中的占位符
application.properties
中的值在使用时会通过现有的Environment
进行过滤,因此您可以参考以前定义的值(例如,从“系统”属性中)。
1 | app.name=MyApp |
Tip
您还可以使用此技术来创建现有 Spring Boot 属性的“简短”变体。有关详细信息,请参见 “使用’短’命令行参数” 操作方法。
加密属性
Spring Boot 不提供对加密属性值的任何内置支持,但是,它确实提供了修改 Spring Environment
中包含的值所必需的钩子点。 EnvironmentPostProcessor
界面允许您在应用程序启动之前操纵Environment
。有关详情,请参见“在启动前自定义环境或 ApplicationContext”。
如果您正在寻找一种安全的方式来存储凭据和密码,则Spring Cloud Vault项目提供了对将外部化配置存储在HashiCorp Vault中的支持。
使用YAML代替属性
YAML是 JSON 的超集,因此是一种用于指定层次结构配置数据的便捷格式。只要在 Classpath 上具有SnakeYAML库,SpringApplication
类就会自动支持 YAML 作为属性的替代方法。
Note
如果您使用“Starter”,则
spring-boot-starter
自动提供 SnakeYAML。
加载YAML
Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 YamlPropertiesFactoryBean
将 YAML 加载为Properties
,而YamlMapFactoryBean
将 YAML 加载为Map
。
例如,考虑以下 YAML 文档:
1 | environments: |
前面的示例将转换为以下属性:
1 | http://dev.example.com = |
YAML 列表表示为带有[index]
解引用器的属性键。例如,考虑以下 YAML:
1 | my: |
前面的示例将转换为以下属性:
1 | dev.example.com = |
要使用 Spring Boot 的Binder
Util(即@ConfigurationProperties
所做的)绑定到类似的属性,您需要在java.util.List
(或Set
)类型的目标 bean 中具有一个属性,并且需要提供 setter 或使用 a 初始化它。可变值。例如,以下示例绑定到前面显示的属性:
1 |
|
在Spring环境中将YAML公开为属性
YamlPropertySourceLoader
类可用于在 Spring Environment
中将 YAML 公开为PropertySource
。这样做使您可以将@Value
注解与占位符语法一起使用以访问 YAML 属性。
多配置文件YAML文档
您可以使用spring.profiles
键在一个文件中指定多个特定于配置文件的 YAML 文档,以指示何时应用该文档,如以下示例所示:
1 | server: |
在前面的示例中,如果development
配置文件处于 Active 状态,则server.address
属性为127.0.0.1
。同样,如果production
和eu-central
配置文件处于 Active 状态,则server.address
属性为192.168.1.120
。如果development
,production
和eu-central
配置文件未启用,则该属性的值为192.168.1.100
。
Note
因此
spring.profiles
可以包含一个简单的配置文件名称(例如production
)或一个配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑,例如production & (eu-central | eu-west)
。查看reference guide以获取更多详细信息。
如果在启动应用程序上下文时未明确激活任何 Active,则会激活默认配置文件。因此,在以下 YAML 中,我们为spring.security.user.password
设置了一个值,该值仅在“默认”配置文件中可用:
1 | server: |
而在以下示例中,始终设置密码是因为该密码未附加到任何配置文件,并且必须根据需要在所有其他配置文件中将其显式重置:
1 | server: |
Spring配置文件可以被spring.profile
元素通过使用!
字符被随意否定。如果为单个文档同时指定了否定配置文件和非否定配置文件,则必须至少匹配一个非否定配置文件,并且不能匹配任何否定配置文件。
YAML缺点
无法使用@PropertySource
注解加载YAML文件。因此,在需要以这种方式加载值的情况下,需要使用属性文件。
类型安全的配置属性
使用@Value("${property}")
注解注入配置属性有时会很麻烦,尤其是当您使用多个属性或数据本质上是分层的时。 Spring Boot 提供了一种使用属性的替代方法,该方法使强类型的Bean可以管理和验证应用程序的配置。
JavaBean属性绑定
可以绑定声明标准JavaBean属性的bean,如下面的例子所示:
1 | package com.example; |
前面的 POJO 定义了以下属性:
acme.enabled
,默认值为false
。acme.remote-address
,其类型可以从String
强制转换。acme.security.username
,带有嵌套的“安全”对象,其名称由属性名称确定。特别是,返回类型在那里根本不使用,可能是SecurityProperties
。acme.security.password
.acme.security.roles
,集合为String
。
Note
映射到Spring Boot中可用的
@ConfigurationProperties
类的属性(通过属性文件、YAML文件、环境变量等配置)是公共API,但类本身的访问器(getter /setter)并不打算直接使用。Note
这种安排依赖于默认的空构造函数,getter和setter通常是强制的,因为绑定是通过标准的Java bean属性描述符进行的,就像Spring MVC中一样。在下列情况下,可省略setter:
- 映射,只要它们被初始化,就需要一个getter,但不一定是setter,因为它们可以被绑定器改变。
- 可以通过索引(通常使用YAML)或使用逗号分隔的值(属性)访问集合和数组。在后一种情况下,setter是必需的。我们建议始终为此类类型添加setter。如果初始化一个集合,请确保它不是不可变的(如前面的示例所示)。
- 如果初始化了嵌套的POJO属性(如前面示例中的
Security
字段),则不需要setter。如果希望绑定器使用其默认构造函数动态创建实例,则需要一个setter。有些人使用Project Lombok自动添加getter和setter。请确保Lombok不会为这样的类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。
最后,只考虑标准Java Bean属性,不支持绑定静态属性。
构造器绑定
上一节中的例子可以用不可变的方式重写,如下面的例子所示:
1 | package com.example; |
在这个设置中,@ConstructorBinding
注解用于指示应该使用构造函数绑定。这意味着绑定器将期望找到具有您希望绑定的参数的构造器。
@ConstructorBinding
类的嵌套成员(如上面示例中的Security)也将通过它们的构造函数绑定。
可以使用@DefaultValue
指定默认值,并且将应用相同的转换服务将字符串值强制转换为缺失属性的目标类型。默认情况下,如果没有属性绑定到安全性,则AcmeProperties
实例将包含用于安全性的null
。如果你希望你返回一个非空的安全实例,即使没有属性绑定到它,你可以使用一个空的@DefaultValue
注解这样做:
1 | package com.example; |
Note
要使用构造函数绑定,必须使用
@EnableConfigurationProperties
或配置属性扫描启用该类。不能使用构造函数绑定由常规Spring机制创建的bean(例如@Component
bean、通过@Bean
方法创建的bean或使用@Import
加载的bean)Tips
如果您的类有多个构造函数,您也可以在应该绑定的构造函数上直接使用
@ConstructorBinding
。Note
java.util.Optional
和@ConfigurationProperties
一块使用是不推荐使用,因为它主要用于作为返回类型。因此,它并不非常适合配置属性注入。为了与其他类型的属性保持一致,如果您声明了一个Optional
属性,但它没有值,那么将绑定null
而不是空Optional
属性。
开启ConfigurationProperties-annotated注解类型
Spring引导提供了绑定@ConfigurationProperties
类型并将其注册为bean的基础设施。您可以逐个类启用配置属性,也可以启用配置属性扫描,其工作方式类似于组件扫描。
有时候,用@ConfigurationProperties
注解的类可能不适合扫描,例如,如果您正在开发自己的自动配置,或者希望有条件地启用它们。在这些情况下,使用@EnableConfigurationProperties
注解指定要处理的类型列表。这可以在任何@Configuration
类上完成,如下面的例子所示:
1 |
|
要使用配置属性扫描,请在应用程序中添加@ConfigurationPropertiesScan
注解。通常,它被添加到用@SpringBootApplication
注解的主应用程序类中,但是它可以添加到任何@Configuration
类中。默认情况下,扫描将从声明注解的类的包中进行。如果您想要定义特定的包来扫描,您可以这样做,如下面的例子所示:
1 |
|
Note
当
@ConfigurationProperties
bean注册使用配置属性扫描或通过@EnableConfigurationProperties
bean有一个惯用名称:<prefix>-<fqn>
,<prefix>
是环境关键@ConfigurationProperties
注解中指定的前缀和< fqn >
是完全限定的bean的名称。如果注解不提供任何前缀,则只使用bean的完全限定名。上面示例中的bean名是
acme-com.example.AcmeProperties
。
我们建议@ConfigurationProperties
只处理环境,特别地,不要从上下文注入其他bean。对于特殊情况,可以使用setter注入或框架提供的任何*Aware
接口(例如,如果需要访问环境,可以使用EnvironmentAware
)。如果您仍然希望使用构造函数注入其他bean,则配置属性bean必须使用@Component
进行注解,并使用基于javabean的属性绑定。
使用ConfigurationProperties-annotated注解类型
这种配置风格在SpringApplication
的外部YAML配置中工作得特别好,如下面的示例所示:
1 | # application.yml |
要使用@ConfigurationProperties
bean,您可以使用与任何其他bean相同的方式注入它们,如下面的例子所示:
1 |
|
Note
使用
@ConfigurationProperties
还可以让您生成元数据文件,IDEs可以使用这些元数据文件为您自己的键提供自动完成功能。详见附录。
第三方配置
除了使用@ConfigurationProperties
注解类,您还可以在公共@Bean
方法上使用它。当您要将属性绑定到控件之外的第三方组件时,这样做特别有用。
要通过Environment
属性配置 bean,请将@ConfigurationProperties
添加到其 bean 注册中,如以下示例所示:
1 |
|
用another
前缀定义的任何属性都以类似于前面AcmeProperties
示例的方式 Map 到该AnotherComponent
bean。
宽松绑定
Spring Boot 使用一些宽松的规则将Environment
属性绑定到@ConfigurationProperties
bean,因此Environment
属性名称和 bean 属性名称之间不需要完全匹配。有用的常见示例包括破折号分隔的环境属性(例如context-path
绑定到contextPath
)和大写的环境属性(例如PORT
绑定到port
)。
例如,考虑以下@ConfigurationProperties
类:
1 |
|
在前面的示例中,可以全部使用以下属性名称:
表 24.1. Relaxed绑定
Property | Note |
---|---|
acme.my-project.person.first-name |
Kebab 情况,建议在.properties 和.yml 文件中使用。 |
acme.myProject.person.firstName |
标准驼峰式语法。 |
acme.my_project.person.first_name |
下划线表示法,是在.properties 和.yml 文件中使用的另一种格式。 |
ACME_MYPROJECT_PERSON_FIRSTNAME |
大写格式,使用系统环境变量时建议使用。 |
Note
注解*的
prefix
值必须为 kebab(小写并由-
分隔,例如acme.my-project.person
)。
表 24.2. 每个资源来源的宽松绑定规则
Property Source | Simple | List |
---|---|---|
Properties Files | 骆驼案,烤肉串案或下划线 | 使用[ ] 或逗号分隔值的标准列表语法 |
YAML Files | 骆驼案,烤肉串案或下划线 | 标准 YAML 列表语法或逗号分隔的值 |
Environment Variables | 以下划线作为定界符的大写格式。 _ 不应在属性名称中使用 |
带有下划线的数字值,例如MY_ACME_1_OTHER = my.acme[1].other |
System properties | 骆驼案,烤肉串案或下划线 | 使用[ ] 或逗号分隔值的标准列表语法 |
Tip
我们建议,如果可能的话,属性以小写的 kebab 格式存储,例如
my.property-name=acme
。
Binding Maps
绑定到Map
属性时,如果key
包含小写字母数字字符或-
以外的任何内容,则需要使用方括号表示法,以便保留原始值。如果键没有被[]
包围,则所有非字母数字或-
的字符都将被删除。例如,考虑将以下属性绑定到Map
:
1 | acme: |
上面的属性将绑定到Map
,其中/key1
,/key2
和key3
作为 Map 中的键。
从环境变量绑定
大多数操作系统对可用于环境变量的名称实施严格的规则。例如,Linux shell变量只能包含字母(a到z或a到z)、数字(0到9)或下划线字符(_)。按照惯例,Unix shell变量的名称也是大写的。
Spring Boot的宽松绑定规则被尽可能地设计为与这些命名限制兼容。
要将规范形式的属性名转换为环境变量名,可以遵循以下规则:
将点(.)替换为下划线(_)。
删除所有破折号(-)。
转换为大写。
例如,配置属性spring.main.log-startup-info
是一个名为SPRING_MAIN_LOGSTARTUPINFO
的环境变量。
Note
下划线不能用于替换属性名称中的破折号。如果您尝试在上面的示例中使用
SPRING_MAIN_LOG_STARTUP_INFO
,则不会绑定任何值。
在绑定到对象列表时,也可以使用环境变量。要绑定到列表,元素号应该在变量名中用下划线包围。
例如,配置属性my.acme[0].other
。other将使用名为MY_ACME_0_OTHER
的环境变量。
合并复杂类型
如果在多个位置配置了列表,则通过替换整个列表来进行覆盖。
例如,假设一个MyPojo
对象的name
和description
属性默认为null
。以下示例公开了AcmeProperties
中的MyPojo
个对象的列表:
1 |
|
考虑以下配置:
1 | acme: |
如果dev
配置文件无效,则AcmeProperties.list
包含一个MyPojo
条目,如先前所定义。但是,如果启用了dev
配置文件,则list
仍然仅包含一个条目(名称为my another name
和描述为null
)。此配置不会将第二个MyPojo
实例添加到列表中,并且不会合并项目。
在多个配置文件中指定List
时,将使用优先级最高的(并且只有该优先级)。考虑以下示例:
1 | acme: |
在前面的示例中,如果dev
配置文件处于 Active 状态,则AcmeProperties.list
包含 one MyPojo
条目(名称为my another name
且描述为null
)。对于 YAML,可以使用逗号分隔的列表和 YAML 列表来完全覆盖列表的内容。
对于Map
属性,您可以绑定从多个来源获取的属性值。但是,对于多个源中的同一属性,将使用优先级最高的属性。以下示例从AcmeProperties
公开Map<String, MyPojo>
:
1 |
|
考虑以下配置:
1 | acme: |
如果dev
配置文件未激活,则AcmeProperties.map
包含一个键为key1
的条目(名称为my name 1
和描述为my description 1
)。但是,如果启用了dev
配置文件,则map
包含两个条目,其中包含键key1
(名称为dev name 1
和my description 1
的描述)和key2
(名称为dev name 2
和dev description 2
的描述)。
Note
前述合并规则不仅适用于 YAML 文件,而且适用于所有属性源中的属性。
属性转换
当 Spring Boot 绑定到@ConfigurationProperties
bean 时,它尝试将外部应用程序属性强制为正确的类型。如果需要自定义类型转换,则可以提供ConversionService
bean(使用名为conversionService
的 bean)或自定义属性编辑器(通过CustomEditorConfigurer
bean)或自定义Converters
(将 bean 定义标注为@ConfigurationPropertiesBinding
)。
Note
由于在应用程序生命周期中非常早就请求了此 bean,因此请确保限制您的
ConversionService
使用的依赖项。通常,您需要的任何依赖项可能在创建时未完全初始化。如果配置键强制不需要自定义ConversionService
,而只依赖于具有@ConfigurationPropertiesBinding
限定的自定义转换器,则可能要重命名。
Convertingdurations
Spring Boot 为表达持续时间提供了专门的支持。如果公开java.time.Duration
属性,则应用程序属性中的以下格式可用:
- 常规
long
表示形式(使用毫秒作为默认单位,除非已指定@DurationUnit
) - 标准 ISO-8601 格式由 java.util.Duration 使用
- 值和单位相结合的更易读的格式(例如
10s
表示 10 秒)
考虑以下示例:
1 |
|
要指定 30 秒的会话超时,30
,PT30S
和30s
都是等效的。可以采用以下任何形式指定 500ms 的读取超时:500
,PT0.5S
和500ms
。
您也可以使用任何受支持的单位。这些是:
ns
纳秒us
微秒ms
毫秒s
秒m
分钟h
小时d
天
默认单位是毫秒,可以使用@DurationUnit
覆盖,如上面的示例所示。
Tip
如果要从仅使用
Long
表示持续时间的先前版本进行升级,请确保在切换到Duration
的时间不是毫秒的情况下(使用@DurationUnit
)定义单位。这样做可以提供透明的升级路径,同时支持更丰富的格式。
转换数据大小
Spring Framework 的DataSize
值类型允许以字节表示大小。如果公开DataSize
属性,则应用程序属性中的以下格式可用:
- 常规的
long
表示形式(除非已指定@DataSizeUnit
,否则使用字节作为默认单位) - 值和单位耦合在一起的更具可读性的格式(例如
10MB
表示 10 兆字节)
考虑以下示例:
1 |
|
要指定 10 MB 的缓冲区大小,10
和10MB
是等效的。可以将 256 个字节的大小阈值指定为256
或256B
。
您也可以使用任何受支持的单位。这些是:
B
个字节KB
千字节MB
代表兆字节GB
代表千兆字节TB
代表兆兆字节
默认单位是字节,可以使用@DataSizeUnit
覆盖,如上面的示例所示。
Tip
如果要从仅使用
Long
表示大小的先前版本进行升级,请确保在切换到DataSize
的旁边不是字节的情况下定义单位(使用@DataSizeUnit
)。这样做可以提供透明的升级路径,同时支持更丰富的格式。
ConfigurationProperties注解验证
每当使用 Spring 的@Validated
注解 进行注解时,Spring Boot 就会尝试验证@ConfigurationProperties
类。您可以在配置类上直接使用 JSR-303 javax.validation
约束注解。为此,请确保在 Classpath 上有兼容的 JSR-303 实现,然后将约束注解添加到字段中,如以下示例所示:
1 |
|
Tip
您还可以通过使用
@Validated
Comments 创建配置属性的@Bean
方法来触发验证。
尽管嵌套属性在绑定时也会被验证,但是最好将关联的字段注解为@Valid
。这样可以确保即使没有嵌套属性也可以触发验证。以下示例基于前面的AcmeProperties
示例:
1 |
|
您还可以通过创建名为configurationPropertiesValidator
的 bean 定义来添加自定义 Spring Validator
。 @Bean
方法应声明为static
。配置属性验证器是在应用程序生命周期的早期创建的,并且将@Bean
方法声明为静态方法可以使 Bean 得以创建而不必实例化@Configuration
类。这样做可以避免因早期实例化而引起的任何问题。有一个属性验证 samples显示了如何进行设置。
Tip
spring-boot-actuator
模块包含一个公开所有@ConfigurationProperties
bean 的端点。将您的 Web 浏览器指向/actuator/configprops
或使用等效的 JMX 端点。有关详细信息,请参见“ 生产就绪功能”部分。
ConfigurationProperties注解与Value注解
@Value
注解是核心容器功能,它没有提供与类型安全的配置属性相同的功能。下表总结了@ConfigurationProperties
和@Value
支持的功能:
Feature | @ConfigurationProperties |
@Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
SpEL 评估 |
No | Yes |
如果您为自己的组件定义了一组配置键,我们建议您将它们组合在以@ConfigurationProperties
注解的 POJO 中。您还应该意识到,由于@Value
不支持宽松的绑定,因此如果您需要使用环境变量来提供值,则它不是很好的选择。
最后,尽管您可以在@Value
中编写SpEL
表达式,但不会从应用程序属性文件处理此类表达式。
Profiles
Spring Profiles 提供了一种隔离应用程序配置的各部分并使之仅在某些环境中可用的方法。可以用@Profile
标记任何@Component
或@Configuration
以限制其什么时候被加载,如以下示例所示:
1 |
|
您可以使用spring.profiles.active
Environment
属性来指定哪些配置文件处于 Active 状态。您可以通过本章前面介绍的任何方式指定属性。例如,您可以将其包含在application.properties
中,如以下示例所示:
1 | spring.profiles.active=dev,hsqldb |
您还可以使用以下开关在命令行上指定它:--spring.profiles.active=dev,hsqldb
。
添加Active配置文件
spring.profiles.active
属性遵循与其他属性相同的排序规则:最高PropertySource
获胜。这意味着您可以在application.properties
中指定 Active 配置文件,然后使用命令行开关“替换”它们。
有时,将特定于配置文件的属性“添加”到 Active 配置文件而不是替换它们很有用。 spring.profiles.include
属性可用于无条件添加 Active 配置文件。 SpringApplication
入口点还具有 Java API,用于设置其他配置文件(即,在spring.profiles.active
属性激活的配置文件之上)。请参见SpringApplication中的setAdditionalProfiles()
方法。
例如,当使用开关--spring.profiles.active=prod
运行具有以下属性的应用程序时,还将激活proddb
和prodmq
配置文件:
1 |
|
Note
请记住,可以在
YAML
文档中定义spring.profiles
属性,以确定何时将该特定文档包括在配置中。有关更多详细信息,请参见“根据环境更改配置”。
以编程方式设置配置文件
您可以在应用程序运行之前通过调用SpringApplication.setAdditionalProfiles(…)
以编程方式设置 Active 配置文件。也可以使用 Spring 的ConfigurableEnvironment
界面激活配置文件。
特定于配置文件的配置文件
application.properties
(或application.yml
)和通过@ConfigurationProperties
引用的文件的特定于配置文件的变体都被视为文件并已加载。有关详细信息,请参见“ “特定于配置文件的属性””。
日志
Spring引导对所有内部日志使用Commons Logging,但保留底层日志实现。为Java Util 记录,Log4J2和Logback提供了默认配置。在每种情况下,Logger 都已预先配置为使用控制台输出,同时还提供可选文件输出。
默认情况下,如果使用“启动器”,则使用 Logback 进行日志记录。还包括适当的 Logback 路由,以确保使用 Java Util Logging,Commons Logging,Log4J 或 SLF4J 的从属库均能正常工作。
Tip
有许多可用于 Java 的日志记录框架。如果上面的列表看起来令人困惑,请不要担心。通常,您不需要更改日志记录依赖项,并且 Spring Boot 默认值可以正常工作。
日志格式
Spring Boot 的默认日志输出类似于以下示例:
1 | 2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52 |
输出以下项目:
- 日期和时间:毫秒精度,易于排序。
- 日志级别:
ERROR
,WARN
,INFO
,DEBUG
或TRACE
。 - Process ID.
---
分隔符用于区分实际日志消息的开始。- 线程名称:用方括号括起来(对于控制台输出可能会被截断)。
- Logger 名称:这通常是源类名称(通常缩写)。
- 日志消息。
Note
Logback 没有
FATAL
级别。它 Map 到ERROR
。
控制台输出
缺省日志配置在写入消息时将消息回显到控制台。默认情况下,将记录ERROR
级,WARN
级和INFO
级消息。您还可以通过使用--debug
标志启动应用程序来启用“调试”模式。
1 | java -jar myapp.jar --debug |
Note
您也可以在
application.properties
中指定debug=true
。
启用调试模式后,将配置一些核心 Logger(嵌入式容器,Hibernate 和 Spring Boot)以输出更多信息。启用调试模式不会不将您的应用程序配置为记录所有具有DEBUG
级的消息。
另外,您可以通过使用--trace
标志(或application.properties
中的trace=true
)启动应用程序来启用“跟踪”模式。这样做可以为某些核心 Logger(嵌入式容器,Hibernate 模式生成以及整个 Spring 产品组合)启用跟踪记录。
颜色编码的输出
如果您的终端支持 ANSI,则使用彩色输出来提高可读性。您可以将spring.output.ansi.enabled
设置为supported value以覆盖自动检测。
通过使用%clr
转换字来配置颜色编码。转换器以最简单的形式根据对数级别为输出着色,如以下示例所示:
1 | clr(%5p) |
下表描述了日志级别到颜色的 Map:
Level | Color |
---|---|
FATAL |
Red |
ERROR |
Red |
WARN |
Yellow |
INFO |
Green |
DEBUG |
Green |
TRACE |
Green |
另外,您可以通过将其提供为转换的选项来指定应使用的颜色或样式。例如,要使文本变黄,请使用以下设置:
1 | clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow} |
支持以下颜色和样式:
blue
cyan
faint
green
magenta
red
yellow
文件输出
默认情况下,Spring Boot 仅记录到控制台,不写日志文件。如果除了控制台输出外还想写入日志文件,则需要设置logging.file
或logging.path
属性(例如,在application.properties
中)。
下表显示了如何一起使用logging.*
属性:
表 26.1 记录属性
logging.file |
logging.path |
Example | Description |
---|---|---|---|
(none) | (none) | 仅控制台记录。 | |
Specific file | (none) | my.log |
写入指定的日志文件。名称可以是确切的位置,也可以相对于当前目录。 |
(none) | Specific directory | /var/log |
将spring.log 写入指定的目录。名称可以是确切的位置,也可以相对于当前目录。 |
日志文件达到 10 MB 时会旋转,并且与控制台输出一样,默认记录ERROR
-level,WARN
-level 和INFO
-level 消息。大小限制可以使用logging.file.max-size
属性更改。除非已设置logging.file.max-history
属性,否则以前旋转的文件将无限期存档。
Note
日志记录系统在应用程序生命周期的早期进行了初始化。因此,在通过
@PropertySource
注解加载的属性文件中找不到日志记录属性。Tip
日志记录属性与实际的日志记录基础结构无关。结果,Spring Boot 不会管理特定的配置密钥(例如 Log 的
logback.configurationFile
)。
日志级别
所有支持的日志记录系统都可以使用logging.level.<logger-name>=<level>
在 Spring Environment
(例如,在application.properties
)中设置 Logger 级别,其中level
是 TRACE,DEBUG,INFO,WARN,ERROR,FATAL 或 OFF 之一。可以使用logging.level.root
来配置root
Logger。
以下示例显示了application.properties
中的潜在日志记录设置:
1 | WARN = |
日志组
能够将相关 Logger 组合在一起通常很有用,以便可以同时配置它们。例如,您可能通常会更改与 Tomcat 相关的所有 Logger 的日志记录级别,但是您不容易记住顶级软件包。
为了解决这个问题,Spring Boot 允许您在 Spring Environment
中定义日志记录组。例如,这是通过将“ tomcat”组添加到application.properties
来定义它的方法:
1 | org.apache.catalina, org.apache.coyote, org.apache.tomcat = |
定义后,您可以使用一行更改该组中所有 Logger 的级别:
1 | TRACE = |
Spring Boot 包含以下 sched 义的日志记录组,它们可以直接使用:
Name | Loggers |
---|---|
web | org.springframework.core.codec , org.springframework.http , org.springframework.web |
sql | org.springframework.jdbc.core , org.hibernate.SQL |
自定义日志配置
可以通过在 Classpath 中包括适当的库来激活各种日志记录系统,并可以通过在 Classpath 的根目录中或在以下 Spring Environment
属性:logging.config
指定的位置中提供适当的配置文件来进一步自定义各种日志记录系统。
您可以通过使用org.springframework.boot.logging.LoggingSystem
system 属性来强制 Spring Boot 使用特定的日志记录系统。该值应该是LoggingSystem
实现的完全限定的类名。您还可以使用none
值完全禁用 Spring Boot 的日志记录配置。
Note
由于日志记录是在创建
ApplicationContext
之前**初始化的,因此无法从 Spring@Configuration
文件中的@PropertySources
控制日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。
根据您的日志系统,将加载以下文件:
Logging System | Customization |
---|---|
Logback | logback-spring.xml ,logback-spring.groovy ,logback.xml 或logback.groovy |
Log4j2 | log4j2-spring.xml 或log4j2.xml |
JDK(Java Util 日志记录) | logging.properties |
Note
如果可能,我们建议您将-spring
变体用于日志记录配置(例如logback-spring.xml
而不是logback.xml
)。如果使用标准配置位置,Spring 将无法完全控制日志初始化。
Warning
从“可执行 jar”运行时,Java Util Logging 存在一些已知的类加载问题,这些问题会引起问题。我们建议您尽可能从“可执行 jar”运行时避免使用它。
为了帮助进行自定义,如下表所述,一些其他属性从 Spring Environment
转移到 System 属性:
Spring Environment | System Property | Comments |
---|---|---|
logging.exception-conversion-word |
LOG_EXCEPTION_CONVERSION_WORD |
记录异常时使用的转换字。 |
logging.file |
LOG_FILE |
如果定义,它将在默认日志配置中使用。 |
logging.file.max-size |
LOG_FILE_MAX_SIZE |
最大日志文件大小(如果启用了 LOG_FILE)。 (仅默认登录设置支持.) |
logging.file.max-history |
LOG_FILE_MAX_HISTORY |
要保留的最大归档日志文件数(如果启用了 LOG_FILE)。 (仅默认登录设置支持.) |
logging.path |
LOG_PATH |
如果定义,它将在默认日志配置中使用。 |
logging.pattern.console |
CONSOLE_LOG_PATTERN |
在控制台上使用的日志模式(stdout)。 (仅默认登录设置支持.) |
logging.pattern.dateformat |
LOG_DATEFORMAT_PATTERN |
记录日期格式的附加模式。 (仅默认登录设置支持.) |
logging.pattern.file |
FILE_LOG_PATTERN |
文件中使用的日志模式(如果启用了LOG_FILE )。 (仅默认登录设置支持.) |
logging.pattern.level |
LOG_LEVEL_PATTERN |
渲染日志级别时使用的格式(默认为%5p )。 (仅默认登录设置支持.) |
PID |
PID |
当前进程 ID(如果可能,并且尚未将其定义为 OS 环境变量时发现)。 |
所有受支持的日志记录系统在解析其配置文件时都可以查阅系统属性。有关示例,请参见spring-boot.jar
中的默认配置:
Tip
如果要在日志记录属性中使用占位符,则应使用Spring Boot 的语法而不是基础框架的语法。值得注意的是,如果使用 Logback,则应使用:
作为属性名称与其默认值之间的分隔符,而不应使用:-
。
Tip
您可以通过仅覆盖LOG_LEVEL_PATTERN
(或使用 Logback 覆盖logging.pattern.level
)将 MDC 和其他临时内容添加到日志行。例如,如果使用logging.pattern.level=user:%X{user} %5p
,则默认日志格式包含“ user”的 MDC 条目(如果存在),如以下示例所示。
1 | 2015-09-30 12:30:04.031 user:someone INFO 22174 --- [ nio-8080-exec-0] demo.Controller |
Logback扩展
Spring Boot 包含许多 Logback 扩展,可以帮助进行高级配置。您可以在logback-spring.xml
配置文件中使用这些 extensions。
Note
由于标准
logback.xml
配置文件加载时间过早,因此无法在其中使用 extensions。您需要使用logback-spring.xml
或定义logging.config
属性。Warning
这些扩展不能与 Logback 的configuration scanning一起使用。如果尝试这样做,则对配置文件进行更改将导致类似于以下记录之一的错误记录:
1
2 ERROR in [emailprotected]:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in [emailprotected]:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
特定于配置文件的配置
<springProfile>
标签可让您根据有效的 Spring 配置文件有选择地包括或排除配置部分。 <configuration>
元素中任何位置都支持概要文件部分。使用name
属性指定哪个配置文件接受配置。 <springProfile>
标记可以包含一个简单的配置文件名称(例如staging
)或一个配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑,例如production & (eu-central | eu-west)
。查看reference guide以获取更多详细信息。以下 Lists 显示了三个 samples 概要文件:
1 | <springProfile name="staging"> |
环境属性
<springProperty>
标签可让您公开 Spring Environment
中的属性,以供在 Logback 中使用。如果要从 Logback 配置中访问application.properties
文件中的值,则这样做很有用。该标记的工作方式类似于 Logback 的标准<property>
标记。但是,不是指定直接的value
,而是指定属性的source
(来自Environment
)。如果需要将属性存储在local
范围以外的其他位置,则可以使用scope
属性。如果需要回退值(如果未在Environment
中设置该属性),则可以使用defaultValue
属性。以下示例显示如何公开用于 Logback 的属性:
1 | <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host" |
Note
source
必须在烤肉串情况下指定(例如my.property-name
)。但是,可以使用宽松规则将属性添加到Environment
。
国际化
Spring Boot支持本地化消息,这样您的应用程序就可以满足不同语言偏好的用户。默认情况下,Spring Boot在类路径的根查找是否存在消息资源束。
Note
当配置的资源包的默认属性文件可用时(默认
message.properties
),自动配置就会应用。如果资源包只包含特定于语言的属性文件,则需要添加缺省值。如果没有找到匹配任何配置的基本名称的属性文件,那么就不会有自动配置的MessageSource
。
资源包的基本名称以及其他几个属性可以使用spring配置。消息名称空间,如下面的示例所示:
1 | messages,config.i18n.messages = |
spring.messages.basename
支持以逗号分隔的位置列表,可以是包限定符,也可以是从类路径根解析出来的资源。
关更多受支持的选项,请参见MessageSourceProperties。
JSON
Spring Boot 提供了与三个 JSON Map 库的集成:
- Gson
- Jackson
- JSON-B
Jackson 是首选的默认库。
Jackson
提供了 Jackson 的自动配置功能,并且 Jackson 是spring-boot-starter-json
的一部分。当 Jackson 放在 Classpath 上时,会自动配置ObjectMapper
bean。为定制 ObjectMapper 的配置提供了几个配置属性。
Gson
提供了 Gson 的自动配置。当 Gson 在 Classpath 上时,会自动配置Gson
bean。提供了几个spring.gson.*
配置属性用于自定义配置。为了获得更多控制权,可以使用一个或多个GsonBuilderCustomizer
bean。
JSON-B
提供了 JSON-B 的自动配置。当 JSON-B API 和实现位于 Classpath 上时,将自动配置Jsonb
bean。首选的 JSON-B 实现是提供依赖 Management 的 Apache Johnzon。
开发Web应用程序
Spring Boot 非常适合 Web 应用程序开发。您可以使用嵌入式 Tomcat,Jetty,Undertow 或 Netty 创建独立的 HTTP 服务器。大多数 Web 应用程序都使用spring-boot-starter-web
模块来快速启动和运行。您还可以选择使用spring-boot-starter-webflux
模块来构建响应式 Web 应用程序。
如果尚未开发 Spring Boot Web 应用程序,则可以遵循“ Hello World!”。 Getting started部分中的示例。
SpringWebMVC框架
Spring Web MVC 框架(通常简称为“ Spring MVC”)是一个丰富的“模型视图控制器” Web 框架。 Spring MVC 使您可以创建特殊的@Controller
或@RestController
bean 来处理传入的 HTTP 请求。控制器中的方法通过使用@RequestMapping
注解Map 到 HTTP。
以下代码显示了提供 JSON 数据的典型@RestController
:
1 |
|
Spring MVC 是核心 Spring Framework 的一部分,有关详细信息,请参见reference documentation。 spring.io/guides提供了一些涵盖 Spring MVC 的指南。
SpringMVC自动配置
Spring Boot 为 Spring MVC 提供了自动配置,可与大多数应用程序完美配合。
自动配置在 Spring 的默认值之上添加了以下功能:
- 包括
ContentNegotiatingViewResolver
和BeanNameViewResolver
bean。 - 支持提供静态资源,包括对 WebJars 的支持(覆盖本文档后面。
- 自动注册
Converter
,GenericConverter
和Formatter
bean。 - 支持
HttpMessageConverters
(包含本文档后面。 - 自动注册
MessageCodesResolver
(已发现本文档后面。 - 静态
index.html
支持。 - 自定义
Favicon
支持(包含本文档后面。 - 自动使用
ConfigurableWebBindingInitializer
bean(包含本文档后面。
如果您想保留 Spring Boot MVC 功能,并且想要添加其他MVC configuration(拦截器,格式化程序,视图控制器和其他功能),则可以添加自己的@Configuration
类,类型为WebMvcConfigurer
,但是没有 @EnableWebMvc
。如果希望提供RequestMappingHandlerMapping
,RequestMappingHandlerAdapter
或ExceptionHandlerExceptionResolver
的自定义实例,则可以声明WebMvcRegistrationsAdapter
实例以提供此类组件。
如果要完全控制 Spring MVC,则可以添加自己的@Configuration
并以@EnableWebMvc
注解。
HttpMessageConverters
Spring MVC 使用HttpMessageConverter
接口转换 HTTP 请求和响应。开箱即用中包含明智的默认设置。例如,可以将对象自动转换为 JSON(通过使用 Jackson 库)或 XML(通过使用 Jackson XML 扩展(如果可用)或通过使用 JAXB(如果 Jackson XML 扩展不可用))。默认情况下,字符串以UTF-8
编码。
如果需要添加或定制转换器,则可以使用 Spring Boot 的HttpMessageConverters
类,如以下 Lists 所示:
1 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters; |
上下文中存在的任何HttpMessageConverter
bean 都将添加到转换器列表中。您也可以用相同的方法覆盖默认转换器。
自定义JSON序列化器和反序列化器
如果使用 Jackson 来序列化和反序列化 JSON 数据,则可能要编写自己的JsonSerializer
和JsonDeserializer
类。自定义序列化器通常是通过模块在 Jackson 注册,但是 Spring Boot 提供了@JsonComponent
Comments,这使得直接注册 Spring Bean 更加容易。
您可以直接在JsonSerializer
或JsonDeserializer
实现中使用@JsonComponent
注解。您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:
1 | import java.io.*; |
ApplicationContext
中的所有@JsonComponent
bean 都会自动向 Jackson 进行注册。因为@JsonComponent
是用@Component
进行元注解的,所以通常的组件扫描规则适用。
Spring Boot 还提供了JsonObjectSerializer和JsonObjectDeserializerBase Class,这些 Base Class 在序列化对象时为标准 Jackson 版本提供了有用的替代方法。有关详细信息,请参见 Javadoc 中的JsonObjectSerializer和JsonObjectDeserializer。
MessageCodesResolver
Spring MVC 有一种生成错误代码的策略,该错误代码用于从绑定错误MessageCodesResolver
渲染错误消息。如果设置spring.mvc.message-codes-resolver.format
属性PREFIX_ERROR_CODE
或POSTFIX_ERROR_CODE
,Spring Boot 会为您创建一个(请参见DefaultMessageCodesResolver.Format中的枚举)。
静态内容
默认情况下,Spring Boot 从 Classpath 中名为/static
(或/public
或/resources
或/META-INF/resources
)的目录或ServletContext
的根目录中提供静态内容。它使用 Spring MVC 中的ResourceHttpRequestHandler
,因此您可以通过添加自己的WebMvcConfigurer
并覆盖addResourceHandlers
方法来修改该行为。
在独立的 Web 应用程序中,还启用了容器中的默认 servlet,并将其用作后备,如果 Spring 决定不处理ServletContext
的根,则从ServletContext
的根开始提供内容。在大多数情况下,这不会发生(除非您修改默认的 MVC 配置),因为 Spring 始终可以通过DispatcherServlet
处理请求。
默认情况下,资源 Map 在/**
上,但是您可以使用spring.mvc.static-path-pattern
属性对其进行调整。例如,将所有资源重定位到/resources/**
可以实现如下:
1 | /resources/** = |
您还可以使用spring.resources.static-locations
属性来自定义静态资源位置(用目录位置列表替换默认值)。根 Servlet 上下文路径"/"
也会自动添加为位置。
除了前面提到的“标准”静态资源位置以外,还对Webjars content进行了特殊处理。如果 jar 文件以 Webjars 格式打包,则从 jar 文件提供带有/webjars/**
路径的任何资源。
Tip
如果您的应用程序打包为 jar,则不要使用
src/main/webapp
目录。尽管此目录是一个通用标准,但它仅在 war 打包中有效,并且在生成 jar 时,大多数构建工具都将其忽略。
Spring Boot 还支持Spring MVC提供的高级资源处理功能,允许使用案例,例如缓存清除静态资源或对 Webjars 使用版本无关的 URL。
要对 Webjar 使用版本无关的 URL,请添加webjars-locator-core
依赖项。然后声明您的 Webjar。以 jQuery
为例,在"/webjars/jquery/x.y.z/jquery.min.js"
中添加"/webjars/jquery/jquery.min.js"
结果。其中x.y.z
是 Webjar 版本。
Note
如果使用 JBoss,则需要声明
webjars-locator-jboss-vfs
依赖性而不是webjars-locator-core
。否则,所有 Webjar 都解析为404
。
要使用缓存清除,以下配置为所有静态资源配置了缓存清除解决方案,从而有效地在 URL 中添加了内容哈希,例如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
:
1 | true = |
Note
得益于为 Thymeleaf 和 FreeMarker 自动配置的
ResourceUrlEncodingFilter
,在运行时将资源链接重写为模板。使用 JSP 时,您应该手动声明此过滤器。当前不自动支持其他模板引擎,但可以与自定义模板宏/帮助器一起使用,并可以使用ResourceUrlProvider。
例如,当使用 JavaScript 模块加载器动态加载资源时,不能重命名文件。这就是为什么其他策略也受支持并且可以组合的原因。 “固定”策略在 URL 中添加静态版本字符串,而不会更改文件名,如以下示例所示:
1 | true = |
通过这种配置,位于"/js/lib/"
下的 JavaScript 模块使用固定的版本控制策略("/v12/js/lib/mymodule.js"
),而其他资源仍使用内容版本(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
)。
有关更多受支持的选项,请参见ResourceProperties。
Tip
此功能已在专用的blog post和 Spring Framework 的reference documentation中进行了详细描述。
欢迎页面
Spring Boot 支持静态和模板欢迎页面。它首先在配置的静态内容位置中查找index.html
文件。如果未找到,则它将寻找index
模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。
自定义图标
Spring Boot 在配置的静态内容位置和 Classpath 的根目录(按此 Sequences)中查找favicon.ico
。如果存在这样的文件,它将自动用作应用程序的收藏夹图标。
路径匹配和内容协商
Spring MVC 可以通过查看请求路径并将其匹配到应用程序中定义的Map(例如 Controller 方法上的@GetMapping
注解),将传入的 HTTP 请求 Map 到处理程序。
Spring Boot 默认选择禁用后缀模式匹配,这意味着诸如"GET /projects/spring-boot.json"
之类的请求将不会与@GetMapping("/projects/spring-boot")
Map 相匹配。这被视为Spring MVC 应用程序的最佳实践。过去,此功能主要用于未发送正确的“ Accept”请求 Headers 的 HTTP Client 端。我们需要确保将正确的 Content Type 发送给 Client 端。如今,内容协商已变得更加可靠。
还有其他处理 HTTP Client 端的方法,这些方法不能始终发送正确的“ Accept”请求 Headers。除了使用后缀匹配,我们还可以使用查询参数来确保将"GET /projects/spring-boot?format=json"
之类的请求 Map 到@GetMapping("/projects/spring-boot")
:
1 | true = |
如果您了解了注意事项,但仍希望您的应用程序使用后缀模式匹配,则需要以下配置:
1 | spring.mvc.contentnegotiation.favor-path-extension=true |
另外,与其打开所有后缀模式,不如只支持注册的后缀模式,这是更安全的:
1 | true = |
ConfigurableWebBindingInitializer
Spring MVC 使用WebBindingInitializer
来为特定请求初始化WebDataBinder
。如果创建自己的ConfigurableWebBindingInitializer
@Bean
,Spring Boot 会自动将 Spring MVC 配置为使用它。
模板引擎
除了 REST Web 服务之外,您还可以使用 Spring MVC 来提供动态 HTML 内容。 Spring MVC 支持各种模板技术,包括 Thymeleaf,FreeMarker 和 JSP。同样,许多其他模板引擎包括他们自己的 Spring MVC 集成。
Spring Boot 包括对以下模板引擎的自动配置支持:
Tip
如果可能,应避免使用
JSP
。与嵌入式servlet
容器一起使用时,有多个known limitations。当您使用默认配置的这些模板引擎之一时,将从
src/main/resources/templates
自动拾取模板。Tip
根据您运行应用程序的方式,
IntelliJ
IDEA 对Classpath
的排序方式不同。与使用Maven
或Gradle
或从打包的 jar 运行应用程序时,从IDE
的 Main 方法运行应用程序的 Sequences 会有所不同。这可能会导致 Spring Boot 无法在Classpath
上找到模板。如果遇到此问题,则可以在IDE
中重新排序Classpath
,以首先放置模块的类和资源。另外,您可以配置模板前缀以搜索Classpath
上的每个templates
目录,如下所示:classpath*:/templates/
。
错误处理
默认情况下,Spring Boot 提供了一个/error
Map,可以明智地处理所有错误,并且已在 servlet
容器中注册为“全局”错误页面。对于机器 Client 端,它将生成 JSON
响应,其中包含错误,HTTP 状态和异常消息的详细信息。对于浏览器 Client 端,存在一个“ whitelabel”错误视图,该视图以 HTML 格式渲染相同的数据(要对其进行自定义,请添加解析为error
的View
)。要完全替换默认行为,可以实现ErrorController
并注册该类型的 Bean 定义,或添加ErrorAttributes
类型的 Bean 以使用现有机制但替换其内容。
Tip
BasicErrorController
可用作自定义ErrorController
的 Base Class。如果要为新的 Content Type 添加处理程序(默认是专门处理text/html
并为其他所有内容提供后备功能),则此功能特别有用。为此,扩展BasicErrorController
,添加具有produces
属性的@RequestMapping
的公共方法,并创建新类型的 bean。
您还可以定义带有@ControllerAdvice
注解的类,以自定义 JSON 文档以针对特定的控制器和/或异常类型返回,如以下示例所示:
1 |
|
在前面的示例中,如果在与AcmeController
相同的程序包中定义的控制器抛出YourException
,则使用CustomErrorType
POJO 的 JSON 表示代替ErrorAttributes
表示。
自定义错误页面
如果要显示给定状态代码的自定义 HTML 错误页面,可以将文件添加到/error
文件夹。错误页面可以是静态 HTML(即添加到任何静态资源文件夹下),也可以使用模板来构建。文件名应为确切的状态代码或系列掩码。
例如,要将404
Map 到静态 HTML 文件,您的文件夹结构如下:
1 | src/ |
要使用 FreeMarker 模板 Map 所有5xx
错误,您的文件夹结构如下:
1 | src/ |
对于更复杂的 Map,还可以添加实现ErrorViewResolver
接口的 bean,如以下示例所示:
1 | public class MyErrorViewResolver implements ErrorViewResolver { |
您还可以使用常规的 Spring MVC 功能,例如@ExceptionHandler methods和@ControllerAdvice。 ErrorController
然后接收任何未处理的异常。
MapSpringMVC之外的错误页面
对于不使用 Spring MVC 的应用程序,可以使用ErrorPageRegistrar
接口直接注册ErrorPages
。此抽象直接与基础嵌入式 servlet 容器一起使用,即使您没有 Spring MVC DispatcherServlet
,也可以使用。
1 |
|
Note
如果您注册的
ErrorPage
的路径最终由Filter
处理(这在某些非 Spring Web 框架(如 Jersey 和 Wicket)中很常见),则必须将Filter
明确注册为ERROR
调度程序,如图所示。下面的例子:
1 |
|
请注意,默认的FilterRegistrationBean
不包括ERROR
调度程序类型。
注意:Spring Boot 部署到 servlet 容器时,将使用其错误页面过滤器将具有错误状态的请求转发到相应的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0 和更高版本在成功完成 servlet 的服务方法后提交响应。您应该通过将com.ibm.ws.webcontainer.invokeFlushAfterService
设置为false
来禁用此行为。
Spring HATEOAS
如果您开发使用超媒体的 RESTful API,Spring Boot 将为 Spring HATEOAS 提供自动配置,该配置可与大多数应用程序很好地配合使用。自动配置取代了使用@EnableHypermediaSupport
的需要,并注册了许多 Bean 以简化基于超媒体的应用程序的构建,包括LinkDiscoverers
(用于 Client 端支持)和ObjectMapper
,这些ObjectMapper
被配置为将响应正确地编组为所需的表示形式。 ObjectMapper
是通过设置各种spring.jackson.*
属性来定制的,或者通过设置Jackson2ObjectMapperBuilder
bean 来定制(如果存在)。
您可以使用@EnableHypermediaSupport
来控制 Spring HATEOAS 的配置。请注意,这样做会禁用前面介绍的ObjectMapper
自定义。
CORS支持
跨域资源共享(CORS)是由most browsers实现的W3C specification,可让您灵活地指定授权哪种类型的跨域请求,而不是使用一些安全性和功能不强的方法(例如 IFRAME 或 JSONP)。
从 4.2 版本开始,Spring MVC supports CORS。在 Spring Boot 应用程序中使用控制器方法 CORS 配置和@CrossOrigin注解不需要任何特定的配置。可以通过使用自定义的addCorsMappings(CorsRegistry)
方法注册WebMvcConfigurer
bean 来定义全局 CORS 配置,如以下示例所示:
1 |
|
SpringWebFlux框架
Spring WebFlux 是 Spring Framework 5.0 中引入的新的响应式 Web 框架。与 Spring MVC 不同,它不需要 Servlet API,是完全异步和非阻塞的,并通过Reactor Project实现Reactive Streams规范。
Spring WebFlux 有两种形式:功能性的和基于注解的。基于注解的模型非常类似于 Spring MVC 模型,如以下示例所示:
1 |
|
功能变量“ WebFlux.fn”将路由配置与请求的实际处理分开,如以下示例所示:
1 |
|
WebFlux 是 Spring Framework 的一部分,其reference documentation中提供了详细信息。
Tip
您可以根据需要定义尽可能多的
RouterFunction
bean,以对 Router 的定义进行模块化。如果需要应用优先级,可以 Order Bean。
首先,将spring-boot-starter-webflux
模块添加到您的应用程序中。
Note
在应用程序中同时添加
spring-boot-starter-web
和spring-boot-starter-webflux
模块会导致 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。之所以选择这种行为,是因为许多 Spring 开发人员将spring-boot-starter-webflux
添加到他们的 Spring MVC 应用程序中以使用 ReactiveWebClient
。您仍然可以通过将选定的应用程序类型设置为SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)
来强制执行选择。
SpringWebFlux自动配置
Spring Boot 为 Spring WebFlux 提供了自动配置,可与大多数应用程序完美配合。
自动配置在 Spring 的默认值之上添加了以下功能:
如果您想保留 Spring Boot WebFlux 功能,并且想要添加其他WebFlux configuration,则可以添加自己的@Configuration
类,类型为WebFluxConfigurer
,但 没有 @EnableWebFlux
。
如果要完全控制 Spring WebFlux,则可以添加带有@EnableWebFlux
注解的自己的@Configuration
。
带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器
Spring WebFlux 使用HttpMessageReader
和HttpMessageWriter
接口转换 HTTP 请求和响应。通过查看 Classpath 中可用的库,将它们配置为CodecConfigurer
以具有合理的默认值。
Spring Boot 通过使用CodecCustomizer
实例应用进一步的自定义。例如,将spring.jackson.*
配置密钥应用于 Jackson 编解码器。
如果需要添加或自定义编解码器,则可以创建自定义CodecCustomizer
组件,如以下示例所示:
1 | import org.springframework.boot.web.codec.CodecCustomizer; |
您还可以使用Boot 的自定义 JSON 序列化器和反序列化器。
静态内容
默认情况下,Spring Boot 从 Classpath 中名为/static
(或/public
或/resources
或/META-INF/resources
)的目录中提供静态内容。它使用 Spring WebFlux 中的ResourceWebHandler
,以便您可以通过添加自己的WebFluxConfigurer
并覆盖addResourceHandlers
方法来修改该行为。
默认情况下,资源 Map 在/**
上,但是您可以通过设置spring.webflux.static-path-pattern
属性对其进行调整。例如,将所有资源重定位到/resources/**
可以实现如下:
1 | /resources/** = |
您还可以使用spring.resources.static-locations
自定义静态资源位置。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果启动时您的任何位置都存在index.html
,则它是应用程序的主页。
除了前面列出的“标准”静态资源位置之外,Webjars content也是一种特殊情况。如果 jar 文件以 Webjars 格式打包,则从 jar 文件提供带有/webjars/**
路径的任何资源。
Tip
Spring WebFlux 应用程序不严格依赖 Servlet API,因此不能将它们部署为 war 文件,也不使用
src/main/webapp
目录。
模板引擎
除了 REST Web 服务之外,您还可以使用 Spring WebFlux 来提供动态 HTML 内容。 Spring WebFlux 支持多种模板技术,包括 Thymeleaf,FreeMarker 和 Mustache。
Spring Boot 包括对以下模板引擎的自动配置支持:
当您使用默认配置的这些模板引擎之一时,将从src/main/resources/templates
自动拾取模板。
错误处理
Spring Boot 提供了一个WebExceptionHandler
,可以明智地处理所有错误。它在处理 Sequences 中的位置紧靠 WebFlux 提供的处理程序之前,该处理程序被认为是最后一个。对于机器 Client 端,它将生成 JSON 响应,其中包含错误,HTTP 状态和异常消息的详细信息。对于浏览器 Client 端,有一个“ whitelabel”错误处理程序,以 HTML 格式渲染相同的数据。您还可以提供自己的 HTML 模板来显示错误(请参见next section。
定制此功能的第一步通常涉及使用现有机制,但替换或增加错误内容。为此,您可以添加ErrorAttributes
类型的 bean。
要更改错误处理行为,可以实现ErrorWebExceptionHandler
并注册该类型的 bean 定义。由于WebExceptionHandler
的级别很低,因此 Spring Boot 还提供了一个方便的AbstractErrorWebExceptionHandler
,让您以 WebFlux 功能方式处理错误,如以下示例所示:
1 | public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { |
要获得更完整的图片,您还可以直接继承DefaultErrorWebExceptionHandler
并重写特定方法。
自定义错误页面
如果要显示给定状态代码的自定义 HTML 错误页面,可以将文件添加到/error
文件夹。错误页面可以是静态 HTML(即添加到任何静态资源文件夹下),也可以使用模板构建。文件名应为确切的状态代码或系列掩码。
例如,要将404
Map 到静态 HTML 文件,您的文件夹结构如下:
1 | src/ |
要使用 Mustache 模板 Map 所有5xx
错误,您的文件夹结构如下:
1 | src/ |
Web过滤器
Spring WebFlux提供了一个WebFilter接口,可以实现该接口来过滤HTTP请求-响应交换。 在应用程序上下文中找到的WebFilter bean将自动用于过滤每个交换。
如果过滤器的顺序很重要,则可以实现Ordered
或使用@Order
进行注解。 Spring Boot自动配置可能会为您配置Web过滤器。 这样做时,将使用下表中显示的顺序:
Web Filter | Order |
---|---|
MetricsWebFilter |
Ordered.HIGHEST_PRECEDENCE + 1 |
WebFilterChainProxy (Spring Security 性) |
-100 |
HttpTraceWebFilter |
Ordered.LOWEST_PRECEDENCE - 10 |
JAX-RS和Jersey
如果您更喜欢 REST 端点的 JAX-RS 编程模型,则可以使用可用的实现之一来代替 Spring MVC。 Jersey和Apache CXF开箱即用。 CXF 要求您在应用程序上下文中将其Servlet
或Filter
注册为@Bean
。Jersey(Jersey)有一些本机 Spring 支持,因此我们在 Spring Boot 中还与启动程序一起为其提供了自动配置支持。
要开始使用 Jersey,请将spring-boot-starter-jersey
作为依赖项,然后需要一个ResourceConfig
类型的@Bean
,在其中注册所有端点,如以下示例所示:
1 |
|
Warning
Jersey 对扫描可执行归档文件的支持非常有限。例如,在运行可执行的 war 文件时,它无法扫描在完全可执行的 jar 文件或
WEB-INF/classes
中找到的程序包中的端点。为避免此限制,不应使用packages
方法,并且应使用register
方法分别注册端点,如前面的示例所示。
对于更高级的定制,您还可以注册实现ResourceConfigCustomizer
的任意数量的 bean。
所有注册的端点都应为@Components
,并带有 HTTP 资源 Comments(@GET
和其他 Comments),如以下示例所示:
1 |
|
由于Endpoint
是 Spring @Component
,其生命周期由 Spring Management,因此您可以使用@Autowired
注解注入依赖项,并使用@Value
注解注入外部配置。默认情况下,Jersey servlet 已注册并 Map 到/*
。您可以通过将@ApplicationPath
添加到ResourceConfig
来更改 Map。
默认情况下,Jersey 在名为jerseyServletRegistration
的ServletRegistrationBean
类型的@Bean
中设置为 Servlet。默认情况下,该 Servlet 延迟初始化,但是您可以通过设置spring.jersey.servlet.load-on-startup
来自定义该行为。您可以通过使用相同的名称创建自己的一个来禁用或覆盖该 bean。您还可以通过设置spring.jersey.type=filter
(在这种情况下,要替换或覆盖的@Bean
是jerseyFilterRegistration
)来使用过滤器而不是 Servlet。过滤器具有@Order
,您可以使用spring.jersey.filter.order
进行设置。可以使用spring.jersey.init.*
指定属性 Map,从而为 servlet 和过滤器注册都赋予 init 参数。
有一个Jersey sample,以便您可以了解如何进行设置。
嵌入式Servlet容器支持
Spring Boot 包含对嵌入式Tomcat,Jetty和Undertow服务器的支持。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080
上侦听 HTTP 请求。
Warning
如果选择在CentOS上使用 Tomcat,请注意,默认情况下,将使用一个临时目录来存储编译的 JSP,文件上载等等。您的应用程序运行时,此目录可能被tmpwatch
删除,从而导致失败。为避免这种情况,您可能需要自定义tmpwatch
配置,以使tomcat.*
目录不会被删除,或配置server.tomcat.basedir
,以使嵌入式 Tomcat 使用其他位置。
Servlet,过滤器和侦听器
使用嵌入式 Servlet 容器时,可以通过使用 Spring bean 或扫描 Servlet 组件来注册 Servlet 规范中的 Servlet,过滤器和所有侦听器(例如HttpSessionListener
)。
将Servlet,过滤器和侦听器注册为SpringBean
任何作为 Spring bean 的Servlet
,Filter
或 servlet *Listener
实例都向嵌入式容器注册。如果要在配置过程中引用application.properties
中的值,这可能特别方便。
默认情况下,如果上下文仅包含单个 Servlet,则将其 Map 到/
。对于多个 servlet bean,bean 名称用作路径前缀。过滤器 Map 到/*
。
如果基于约定的 Map 不够灵活,则可以使用ServletRegistrationBean
,FilterRegistrationBean
和ServletListenerRegistrationBean
类进行完全控制。
Spring Boot 附带了许多可能定义 Filter bean 的自动配置。以下是过滤器及其各自 Sequences 的一些示例(较低的 Sequences 值表示较高的优先级):
Servlet Filter | Order |
---|---|
OrderedCharacterEncodingFilter |
Ordered.HIGHEST_PRECEDENCE |
WebMvcMetricsFilter |
Ordered.HIGHEST_PRECEDENCE + 1 |
ErrorPageFilter |
Ordered.HIGHEST_PRECEDENCE + 1 |
HttpTraceFilter |
Ordered.LOWEST_PRECEDENCE - 10 |
通常可以使无序滤 bean 处于无序状态。
如果需要特定的 Sequences,则应避免配置一个在Ordered.HIGHEST_PRECEDENCE
读取请求正文的过滤器,因为它可能与应用程序的字符编码配置不符。如果 Servlet 过滤器包装了请求,则应以小于或等于OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER
的 Sequences 对其进行配置。
Servlet上下文初始化
嵌入式 Servlet 容器不会直接执行 Servlet 3.0 javax.servlet.ServletContainerInitializer
接口或 Spring 的org.springframework.web.WebApplicationInitializer
接口。这是一个有意设计的决定,目的是减少旨在在 War 中运行的第三方库可能破坏 Spring Boot 应用程序的风险。
如果需要在 Spring Boot 应用程序中执行 servlet 上下文初始化,则应该注册一个实现org.springframework.boot.web.servlet.ServletContextInitializer
接口的 bean。单个onStartup
方法提供对ServletContext
的访问,并且在必要时可以轻松地用作现有WebApplicationInitializer
的适配器。
扫描Servlet,过滤器和侦听器
使用嵌入式容器时,可以通过使用@ServletComponentScan
来启用自动注册带有@WebServlet
,@WebFilter
和@WebListener
Comments 的类。
Tip
@ServletComponentScan
在独立容器中无效,而是使用该容器的内置发现机制。
ServletWebServerApplicationContext
在后台,Spring Boot 使用另一种类型的ApplicationContext
来支持嵌入式 servlet 容器。 ServletWebServerApplicationContext
是WebApplicationContext
的一种特殊类型,它通过搜索单个ServletWebServerFactory
bean 来进行自我引导。通常TomcatServletWebServerFactory
,JettyServletWebServerFactory
或UndertowServletWebServerFactory
已被自动配置。
Note
通常,您不需要了解这些实现类。大多数应用程序都是自动配置的,并且代表您创建了相应的
ApplicationContext
和ServletWebServerFactory
。
自定义嵌入式Servlet容器
可以使用 Spring Environment
属性来配置常见的 servlet 容器设置。通常,您将在application.properties
文件中定义属性。
常用服务器设置包括:
- 网络设置:侦听传入 HTTP 请求的端口(
server.port
),绑定到server.address
的接口地址,等等。 - 会话设置:会话是否持久(
server.servlet.session.persistence
),会话超时(server.servlet.session.timeout
),会话数据的位置(server.servlet.session.store-dir
)和会话 cookie 配置(server.servlet.session.cookie.*
)。 - 错误 Management:错误页面的位置(
server.error.path
),依此类推。 - SSL
- HTTP compression
Spring Boot 尝试尽可能多地公开通用设置,但这并不总是可能的。在这种情况下,专用名称空间提供服务器特定的自定义项(请参见server.tomcat
和server.undertow
)。例如,access logs可以配置有嵌入式 Servlet 容器的特定功能。
Tip
有关完整列表,请参见ServerProperties类。
程序定制
如果需要以编程方式配置嵌入式 servlet 容器,则可以注册一个实现WebServerFactoryCustomizer
接口的 Spring bean。 WebServerFactoryCustomizer
提供对ConfigurableServletWebServerFactory
的访问,其中包括许多自定义设置方法。以下示例显示以编程方式设置端口:
1 | import org.springframework.boot.web.server.WebServerFactoryCustomizer; |
Note
TomcatServletWebServerFactory
,JettyServletWebServerFactory
和UndertowServletWebServerFactory
是ConfigurableServletWebServerFactory
的专用变体,分别具有针对 Tomcat,Jetty 和 Undertow 的其他自定义设置方法。
直接自定义ConfigurableServletWebServerFactory
如果上述定制技术太有限,则可以自己注册TomcatServletWebServerFactory
,JettyServletWebServerFactory
或UndertowServletWebServerFactory
bean。
1 |
|
提供了许多配置选项的设置器。如果您需要做一些更奇特的操作,还提供了几种受保护的方法“钩子”。有关详情,请参见源代码文档。
JSP限制
当运行使用嵌入式 servlet 容器(并打包为可执行归档文件)的 Spring Boot 应用程序时,JSP 支持存在一些限制。
- 对于 Jetty 和 Tomcat,如果使用 War 包装,它应该可以工作。与
java -jar
一起启动时,可执行的 War 将起作用,并且也可部署到任何标准容器中。使用可执行 jar 时,不支持 JSP。 - Undertow 不支持 JSP。
- 创建自定义
error.jsp
页面不会覆盖error handling的默认视图。应该改用自定义错误页面。
有一个JSP sample,以便您可以了解如何进行设置。
嵌入式反应式服务器支持
Spring Boot 包含对以下嵌入式反应式 Web 服务器的支持:Reactor Netty,Tomcat,Jetty 和 Undertow。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在端口 8080 上侦听 HTTP 请求。
Reactive服务器资源配置
当自动配置 Reactor Netty 或 Jetty 服务器时,Spring Boot 将创建特定的 bean,这些 bean 将为服务器实例提供 HTTP 资源:ReactorResourceFactory
或JettyResourceFactory
。
默认情况下,在以下情况下,这些资源还将与 Reactor Netty 和 Jetty Client 端共享,以实现最佳性能:
- 服务器和 Client 端使用相同的技术
- Client 端实例是使用 Spring Boot 自动配置的
WebClient.Builder
bean 构建的
通过提供自定义的ReactorResourceFactory
或JettyResourceFactory
bean,开发人员可以覆盖 Jetty 和 Reactor Netty 的资源配置-这将同时应用于 Client 端和服务器。
您可以在WebClient 运行时部分中了解有关 Client 端资源配置的更多信息。
正常关机
所有4个嵌入式web服务器(Jetty、Reactor Netty、Tomcat和Undertow)以及响应式和基于servlet的web应用程序都支持优雅的关机。它是关闭应用程序上下文的一部分,在停止SmartLifecycle
bean的最初阶段执行。此停止处理使用了一个超时,该超时提供了一个宽限期,在此期间允许现有请求完成,但不允许新请求。不允许新请求的确切方式取决于所使用的web服务器。Jetty、Reactor Netty和Tomcat将停止在网络层接受请求。Undertow将接受请求,但立即响应一个服务不可用(503)响应。
使用Tomcat优雅地关机需要Tomcat 9.0.33或更高版本。
要启用优雅的关机,请配置服务器。关机属性,如下例所示:
1 | graceful = |
要配置超时时间,请配置spring.lifecycle
。每关闭阶段超时属性,如下例所示:
1 | 20s = |
Important
如果IDE无法发送正确的
SIGTERM
信号,则在其IDE中使用正常关机可能无法正常工作。 有关更多详细信息,请参阅IDE的文档。
RSocket
RSocket是用于字节流传输的二进制协议。 它通过通过单个连接传递的异步消息来启用对称交互模型。
Spring框架的spring-messaging
模块在客户端和服务器端都支持RSocket请求者和响应者。 有关更多详细信息,请参见Spring Framework参考中的RSocket部分,其中包括RSocket协议的概述。
RSocket策略自动配置
Spring Boot自动配置一个RSocketStrategies
bean,该bean提供用于编码和解码RSocket有效负载的所有必需的基础结构。默认情况下,自动配置将尝试按顺序配置以下内容:
- Jackson的CBOR编解码器
- Jackson的JSON编解码器
spring-boot-starter-rocket
启动器提供了两种依赖关系。查阅Jackson支持部分,以了解有关定制可能性的更多信息。
开发人员可以通过创建实现RSocketStrategiesCustomizer
接口的bean来自定义RSocketStrategies
组件。请注意,它们的@Order
很重要,因为它确定编解码器的顺序。
RSocket服务器自动配置
Spring Boot提供了RSocket服务器自动配置。所需的依赖关系由spring-boot-starter-rsocket
提供。
Spring Boot允许通过WebFlux服务器通过WebSocket公开RSocket,或支持独立的RSocket服务器。这取决于应用程序的类型及其配置。
对于WebFlux应用程序(即类型为WebApplicationType.REACTIVE
的应用程序),仅当以下属性匹配时,RSocket服务器才会插入Web服务器:
1 | /rsocket # a mapping path is defined = |
Note
由于RSocket本身是使用该库构建的,因此只有Reactor Netty支持将RSocket插入Web服务器。
另外,RSocket TCP或Websocket服务器也可以作为独立的嵌入式服务器启动。 除了依赖性要求之外,唯一需要的配置是为该服务器定义端口:
1 | 9898 # the only required configuration = |
Spring Messaging RSocket支持
Spring Boot将为RSocket自动配置Spring Messaging基础结构。
这意味着Spring Boot将创建一个RSocketMessageHandler
bean,该bean将处理对您的应用程序的RSocket请求。
使用RSocketRequester调用RSocket服务
在服务器和客户端之间建立RSocket通道后,任何一方都可以向另一方发送或接收请求。
作为服务器,您可以在RSocket @Controller
的任何处理程序方法上注入RSocketRequester
实例。作为客户端,您需要首先配置和建立RSocket连接。在这种情况下,Spring Boot会使用预期的编解码器自动配置RSocketRequester.Builder
。
RSocketRequester.Builder
实例是一个原型bean,这意味着每个注入点将为您提供一个新实例。这样做是有目的的,因为此构建器是有状态的,因此您不应使用相同的实例创建具有不同设置的请求者。
以下代码显示了一个典型示例:
1 |
|
Security
如果Spring Security在 Classpath
上,则默认情况下将保护 Web 应用程序的安全。 Spring Boot 依靠 Spring Security 的内容协商策略来确定使用httpBasic
还是formLogin
。要将方法级安全性添加到 Web 应用程序,您还可以使用所需的设置添加@EnableGlobalMethodSecurity
。其他信息可以在Spring Security 参考指南中找到。
默认的UserDetailsService
有一个用户。用户名为user
,密码为随机密码,并在应用程序启动时以 INFO 级别显示,如下例所示:
1 | Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35 |
Note
如果您微调日志记录配置,请确保将
org.springframework.boot.autoconfigure.security
类别设置为记录INFO
级消息。否则,不会打印默认密码。
您可以通过提供spring.security.user.name
和spring.security.user.password
来更改用户名和密码。
默认情况下,您在 Web 应用程序中获得的基本功能是:
- 具有内存存储的
UserDetailsService
(或 WebFlux 应用程序为ReactiveUserDetailsService
)bean 和具有生成的密码的单个用户(有关用户的属性,请参见SecurityProperties.User)。 - 整个应用程序的基于表单的登录或 HTTP 基本安全性(取决于 Content-Type)(如果 Actuator 位于 Classpath 上,则包括 Actuator 端点)。
DefaultAuthenticationEventPublisher
用于发布身份验证事件。
您可以通过添加一个 Bean 来提供另一个AuthenticationEventPublisher
。
MVC安全性
默认的安全配置在SecurityAutoConfiguration
和UserDetailsServiceAutoConfiguration
中实现。 SecurityAutoConfiguration
导入SpringBootWebSecurityConfiguration
以获得 Web 安全性,并且UserDetailsServiceAutoConfiguration
配置身份验证,这也与非 Web 应用程序相关。要完全关闭默认的 Web 应用程序安全性配置,可以添加类型为WebSecurityConfigurerAdapter
的 bean(这样做不会禁用UserDetailsService
配置或 Actuator 的安全性)。
要也关闭UserDetailsService
配置,可以添加UserDetailsService
,AuthenticationProvider
或AuthenticationManager
类型的 Bean。 Spring Bootsample中有几个安全的应用程序,可帮助您开始使用常见的用例。
通过添加自定义WebSecurityConfigurerAdapter
可以覆盖访问规则。 Spring Boot 提供了便利的方法,可用于覆盖 Actuator 端点和静态资源的访问规则。 EndpointRequest
可用于创建基于management.endpoints.web.base-path
属性的RequestMatcher
。 PathRequest
可用于为常用位置的资源创建RequestMatcher
。
WebFlux安全性
与 Spring MVC 应用程序类似,您可以通过添加spring-boot-starter-security
依赖项来保护 WebFlux 应用程序。默认的安全配置在ReactiveSecurityAutoConfiguration
和UserDetailsServiceAutoConfiguration
中实现。 ReactiveSecurityAutoConfiguration
导入WebFluxSecurityConfiguration
以获得 Web 安全性,并且UserDetailsServiceAutoConfiguration
配置身份验证,这也与非 Web 应用程序相关。要完全关闭默认的 Web 应用程序安全性配置,可以添加类型为WebFilterChainProxy
的 bean(这样做不会禁用UserDetailsService
配置或 Actuator 的安全性)。
要也关闭UserDetailsService
配置,可以添加ReactiveUserDetailsService
或ReactiveAuthenticationManager
类型的 Bean。
可以通过添加自定义SecurityWebFilterChain
来配置访问规则。 Spring Boot 提供了便利的方法,可用于覆盖 Actuator 端点和静态资源的访问规则。 EndpointRequest
可用于创建基于management.endpoints.web.base-path
属性的ServerWebExchangeMatcher
。
PathRequest
可用于为常用位置的资源创建ServerWebExchangeMatcher
。
例如,您可以通过添加以下内容来自定义安全配置:
1 |
|
OAuth2
OAuth2是 Spring 支持的广泛使用的授权框架。
Client
如果您的 Classpath 上有spring-security-oauth2-client
,则可以利用一些自动配置功能来轻松设置 OAuth2/Open ID Connect Client 端。此配置使用OAuth2ClientProperties
下的属性。相同的属性适用于 servlet 和反应式应用程序。
您可以使用spring.security.oauth2.client
前缀注册多个 OAuth2 Client 端和提供者,如以下示例所示:
1 | abcd = |
对于支持OpenID Connect 发现的 OpenID Connect 提供程序,可以进一步简化配置。提供者需要配置一个issuer-uri
,这是它声明为其发布者标识符的 URI。例如,如果提供的issuer-uri
是“ https://example.com”,则将对“ https://example.com/.well-known/openid-configuration”设置`OpenID Provider Configuration Request。结果预期为
OpenID Provider Configuration Response。以下示例显示了如何使用
issuer-uri`配置 OpenID Connect 提供程序:
1 | https://dev-123456.oktapreview.com/oauth2/default/ = |
默认情况下,Spring Security 的OAuth2LoginAuthenticationFilter
只处理与/login/oauth2/code/*
匹配的 URL。如果要定制redirect-uri
以使用其他模式,则需要提供配置以处理该定制模式。例如,对于 servlet 应用程序,您可以添加自己的WebSecurityConfigurerAdapter
,其类似于以下内容:
1 | public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter { |
通用提供商的OAuth2Client端注册
对于常见的 OAuth2 和 OpenID 提供程序,包括 Google,Github,Facebook 和 Okta,我们提供了一组提供程序默认值(分别为google
,github
,facebook
和okta
)。
如果不需要自定义这些提供程序,则可以将provider
属性设置为您需要为其推断默认值的属性。另外,如果用于 Client 端注册的密钥与默认支持的提供程序匹配,则 Spring Boot 也会进行推断。
换句话说,以下示例中的两种配置都使用 Google 提供程序:
1 | abcd = |
资源服务器
如果您的 Classpath 上有spring-security-oauth2-resource-server
,则只要指定了 JWK Set URI 或 OIDC Issuer URI,Spring Boot 就可以设置 OAuth2 资源服务器,如以下示例所示:
1 | https://example.com/oauth2/default/v1/keys = |
相同的属性适用于 servlet 和反应式应用程序。
另外,您可以为 Servlet 应用程序定义自己的JwtDecoder
bean 或为 Reactive 应用程序定义ReactiveJwtDecoder
。
授权服务器
当前,Spring Security 不提供对实现 OAuth 2.0 授权服务器的支持。但是,此功能可从Spring Security OAuth项目获得,最终将被 Spring Security 完全取代。在此之前,您可以使用spring-security-oauth2-autoconfigure
模块轻松设置 OAuth 2.0 授权服务器;有关说明,请参见其documentation。
Actuator安全性
为了安全起见,默认禁用除/health
和/info
以外的所有 Actuator。 management.endpoints.web.exposure.include
属性可用于启用 Actuator。
如果 Spring Security 位于 Classpath 上,并且不存在其他 WebSecurityConfigurerAdapter,则通过 Spring Boot 自动配置来保护/health
和/info
以外的所有 Actuator。如果您定义一个自定义WebSecurityConfigurerAdapter
,Spring Boot 自动配置将退出,您将完全控制 Actuator 访问规则。
Note
在设置
management.endpoints.web.exposure.include
之前,请确保裸露的 Actuator 不包含敏感信息和/或通过将它们放置在防火墙后面或通过诸如 Spring Security 之类的东西进行保护。
跨站点请求伪造保护
由于 Spring Boot 依赖于 Spring Security 的默认值,因此默认情况下 CSRF 保护是打开的。这意味着在使用默认安全性配置时,需要POST
的 Actuator 端点(关机和 Logger 端点),PUT
或DELETE
将收到 403 禁止错误。
Note
我们建议仅在创建非浏览器 Client 端使用的服务时完全禁用 CSRF 保护。
有关 CSRF 保护的其他信息可以在Spring Security 参考指南中找到。
使用SQL数据库
Spring Framework为使用 SQL 数据库提供了广泛的支持,从使用JdbcTemplate
的直接 JDBC 访问到完整的“对象关系 Map”技术(例如 Hibernate)。 Spring Data提供了更高级别的功能:直接从接口创建Repository
实现,并使用约定从您的方法名称生成查询。
配置数据源
Java 的javax.sql.DataSource
接口提供了使用数据库连接的标准方法。传统上,“数据源”使用URL
以及一些凭据来构建数据库连接。
Tip
有关更高级的示例,请参见“操作方法”部分,通常可以完全控制 DataSource 的配置。
嵌入式数据库支持
通过使用内存嵌入式数据库来开发应用程序通常很方便。显然,内存数据库不提供持久存储。您需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。
Tip
“操作方法”部分包括关于如何初始化数据库的部分。
Spring Boot 可以自动配置嵌入式H2,HSQL和Derby数据库。您无需提供任何连接 URL。您只需要包含要使用的嵌入式数据库的构建依赖项即可。
Note
如果在测试中使用此功能,则可能会注意到,整个测试套件将重用同一数据库,而不管您使用的应用程序上下文的数量如何。如果要确保每个上下文都有一个单独的嵌入式数据库,则应将
spring.datasource.generate-unique-name
设置为true
。
例如,典型的 POM 依赖关系如下:
1 | <dependency> |
Note
您需要依赖
spring-jdbc
才能自动配置嵌入式数据库。在此示例中,它通过spring-boot-starter-data-jpa
暂时拉入。Tip
如果出于某种原因确实为嵌入式数据库配置了连接 URL,请确保确保禁用了数据库的自动关闭功能。如果使用 H2,则应使用
DB_CLOSE_ON_EXIT=FALSE
。如果使用 HSQLDB,则应确保不使用shutdown=true
。通过禁用数据库的自动关闭功能,Spring Boot 可以控制何时关闭数据库,从而确保一旦不再需要访问数据库时就可以执行该操作。
连接到生产数据库
生产数据库连接也可以使用池DataSource
进行自动配置。 Spring Boot 使用以下算法来选择特定的实现:
- 我们更喜欢HikariCP的性能和并发性。如果 HikariCP 可用,我们总是选择它。
- 否则,如果 Tomcat 池
DataSource
可用,我们将使用它。 - 如果 HikariCP 和 Tomcat 池数据源都不可用,并且Commons DBCP2可用,我们将使用它。
如果使用spring-boot-starter-jdbc
或spring-boot-starter-data-jpa
“启动器”,则会自动获得HikariCP
的依赖项。
Note
您可以完全绕过该算法,并通过设置
spring.datasource.type
属性来指定要使用的连接池。如果您在 Tomcat 容器中运行应用程序,这一点尤其重要,因为默认情况下提供tomcat-jdbc
。Tip
其他连接池始终可以手动配置。如果定义自己的
DataSource
bean,则不会进行自动配置。
数据源配置由spring.datasource.*
中的外部配置属性控制。例如,您可以在application.properties
中声明以下部分:
1 | jdbc:mysql://localhost/test = |
Note
您至少应通过设置
spring.datasource.url
属性来指定 URL。否则,Spring Boot 会尝试自动配置嵌入式数据库。Tip
您通常不需要指定
driver-class-name
,因为 Spring Boot 可以从url
推导大多数数据库。Note
对于要创建的池
DataSource
,我们需要能够验证一个有效的Driver
类是否可用,因此我们在进行任何操作之前都要进行检查。换句话说,如果设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver
,则该类必须是可加载的。
有关更多受支持的选项,请参见DataSourceProperties。这些是与实际实现无关的标准选项。也可以使用它们各自的前缀(spring.datasource.hikari.*
,spring.datasource.tomcat.*
和spring.datasource.dbcp2.*
)微调实现特定的设置。有关更多详细信息,请参考所用连接池实现的文档。
例如,如果您使用Tomcat 连接池,则可以自定义许多其他设置,如以下示例所示:
1 | # Number of ms to wait before throwing an exception if no connection is available. |
连接到JNDI数据源
如果您将 Spring Boot 应用程序部署到 Application Server,则可能需要使用 Application Server 的内置功能来配置和 Management DataSource,并使用 JNDI 对其进行访问。
spring.datasource.jndi-name
属性可以替代spring.datasource.url
,spring.datasource.username
和spring.datasource.password
属性,以从特定的 JNDI 位置访问DataSource
。例如,application.properties
中的以下部分显示了如何访问 JBoss AS 定义的DataSource
:
1 | java:jboss/datasources/customers = |
使用JdbcTemplate
Spring 的JdbcTemplate
和NamedParameterJdbcTemplate
类是自动配置的,您可以@Autowire
直接将它们@Autowire
放入自己的 bean 中,如以下示例所示:
1 | import org.springframework.beans.factory.annotation.Autowired; |
您可以使用spring.jdbc.template.*
属性来自定义模板的某些属性,如以下示例所示:
1 | 500 = |
Note
NamedParameterJdbcTemplate
在后台重复使用相同的JdbcTemplate
实例。如果定义了多个JdbcTemplate
并且不存在主要候选对象,则不会自动配置NamedParameterJdbcTemplate
。
JPA和SpringDataJPA
Java Persistence API 是一种标准技术,可让您将对象“Map”到关系数据库。 spring-boot-starter-data-jpa
POM 提供了一种快速的 Starter 方法。它提供以下关键依赖性:
- Hibernate:最流行的 JPA 实现之一。
- Spring Data JPA:使基于 JPA 的存储库的实现变得容易。
- Spring ORM:Spring Framework 提供的核心 ORM 支持。
Tip
在这里,我们不会过多讨论 JPA 或Spring Data的细节。您可以按照spring.io中的“使用 JPA 访问数据”指南进行操作,并阅读Spring Data JPA和Hibernate参考文档。
实体类
传统上,JPA
“实体”类是在persistence.xml
文件中指定的。对于 Spring Boot,此文件不是必需的,而是使用“实体扫描”。默认情况下,将搜索主配置类(用@EnableAutoConfiguration
或@SpringBootApplication
注解的软件包)下的所有软件包。
任何带有@Entity
,@Embeddable
或@MappedSuperclass
注解的类。典型的实体类类似于以下示例:
1 | package com.example.myapp.domain; |
Tip
您可以使用
@EntityScan
注解来自定义实体扫描位置。请参阅“ 第 84.4 节“将@Entity 定义与 Spring 配置分开””方法。
SpringDataJPA存储库
Spring Data JPA存储库是您可以定义以访问数据的接口。 JPA 查询是根据您的方法名称自动创建的。例如,一个CityRepository
接口可能声明findAllByState(String state)
方法来查找给定 State 的所有城市。
对于更复杂的查询,您可以使用 Spring Data 的Query注解对方法进行注解。
Spring Data 存储库通常从Repository或CrudRepository接口扩展。如果使用自动配置,则会从包含主配置类(用@EnableAutoConfiguration
或@SpringBootApplication
注解的主配置类)的包中搜索存储库。
以下示例显示了典型的 Spring Data 存储库接口定义:
1 | package com.example.myapp.domain; |
Spring Data JPA存储库支持三种不同的引导模式:default
,deferred
和lazy
。 要启用deferred
或lazy
,请将spring.data.jpa.repositories.bootstrap-mode
属性分别设置为推迟或懒惰。 使用deferred
或lazy
时,自动配置的EntityManagerFactoryBuilder
将使用上下文的AsyncTaskExecutor
(如果有)作为引导执行器。 如果存在多个,则将使用一个名为applicationTaskExecutor
的应用程序。
Tip
我们几乎没有刮过 Spring Data JPA 的表面。有关完整的详细信息,请参见Spring Data JPA 参考文档。
创建和删除JPA数据库
默认情况下,您不使用嵌入式数据库(H2,HSQL或Derby),JPA数据库自动创建。 您可以使用spring.jpa.*
属性显式配置JPA设置。 例如,要创建和删除表,可以将以下行添加到application.properties
:
1 | create-drop = |
Note
Hibernate 自己的内部属性名称是
hibernate.hbm2ddl.auto
(如果您记得更好的话)。您可以使用spring.jpa.properties.*
来设置它以及其他 Hibernate 本机属性(将前缀添加到实体 Management 器之前,前缀会被删除)。下面的行显示了为 Hibernate 设置 JPA 属性的示例:
1 | true = |
前面示例中的行将hibernate.globally_quoted_identifiers
属性的值true
传递给 Hibernate 实体 Management 器。
默认情况下,DDL 执行(或验证)被推迟到ApplicationContext
开始。还有一个spring.jpa.generate-ddl
标志,但是如果 Hibernate 自动配置处于 Active 状态,则不使用它,因为ddl-auto
设置更细粒度。
在视图中打开EntityManager
如果您正在运行 Web 应用程序,则默认情况下,Spring Boot 注册OpenEntityManagerInViewInterceptor以应用“在视图中打开 EntityManager”模式,以允许在 Web 视图中进行延迟加载。如果您不希望出现这种情况,则应在application.properties
中将spring.jpa.open-in-view
设置为false
。
Spring Data JDBC
Spring Data 包括对 JDBC
的存储库支持,并将自动为CrudRepository
上的方法生成 SQL
。对于更高级的查询,提供了@Query
Comments。
当必要的依赖项位于 Classpath
上时,Spring Boot 将自动配置 Spring Data 的 JDBC 存储库。只需依赖spring-boot-starter-data-jdbc
即可将它们添加到您的项目中。如有必要,您可以通过向应用程序中添加@EnableJdbcRepositories
注解或JdbcConfiguration
子类来控制 Spring Data JDBC 的配置。
Tip
有关 Spring Data JDBC 的完整详细信息,请参阅reference documentation。
使用H2的Web 控制台
H2 database提供了browser-based console,Spring Boot 可以为您自动配置browser-based console。满足以下条件时,将自动配置控制台:
- 您正在开发基于 servlet 的 Web 应用程序。
com.h2database:h2
在 Classpath 上。- 您正在使用Spring Boot 的开发人员工具。
Tip
如果您不使用 Spring Boot 的开发人员工具,但仍想使用 H2 的控制台,则可以将
spring.h2.console.enabled
属性配置为true
。Note
H2 控制台仅在开发期间使用,因此您应确保在 Producing 不要将
spring.h2.console.enabled
设置为true
。
更改H2控制台的路径
默认情况下,控制台位于/h2-console
。您可以使用spring.h2.console.path
属性来自定义控制台的路径。
使用jOOQ
面向 Java 对象的查询(jOOQ)是Data Geekery的流行产品,它可以从数据库中生成 Java 代码,并允许您通过其流畅的 API 构建类型安全的 SQL 查询。商业版和开源版都可以与 Spring Boot 一起使用。
代码生成
为了使用 jOOQ 类型安全查询,您需要从数据库架构中生成 Java 类。您可以按照jOOQ 用户手册中的说明进行操作。如果您使用jooq-codegen-maven
插件,并且还使用spring-boot-starter-parent
“父 POM”,则可以安全地忽略该插件的<version>
标签。您还可以使用 Spring Boot 定义的版本变量(例如h2.version
)来声明插件的数据库依赖关系。以下 Lists 显示了一个示例:
1 | <plugin> |
使用DSLContext
jOOQ 提供的流畅的 API 是通过org.jooq.DSLContext
接口启动的。 Spring Boot 将DSLContext
自动配置为 Spring Bean,并将其连接到应用程序DataSource
。要使用DSLContext
,您可以@Autowire
,如以下示例所示:
1 |
|
Tip
jOOQ 手册倾向于使用名为
create
的变量来保存DSLContext
。
然后,您可以使用DSLContext
构造查询,如以下示例所示:
1 | public List<GregorianCalendar> authorsBornAfter1980() { |
jOOQSQL方言
除非已配置spring.jooq.sql-dialect
属性,否则 Spring Boot 会确定要用于数据源的 SQL 方言。如果 Spring Boot 无法检测到方言,则使用DEFAULT
。
Note
Spring Boot 只能自动配置开源版本的 jOOQ 支持的方言。
自定义jOOQ
通过定义自己的@Bean
定义(可以在创建 jOOQ Configuration
时使用)可以实现更高级的自定义。您可以为以下 jOOQ 类型定义 bean:
ConnectionProvider
ExecutorProvider
TransactionProvider
RecordMapperProvider
RecordUnmapperProvider
RecordListenerProvider
ExecuteListenerProvider
VisitListenerProvider
TransactionListenerProvider
如果要完全控制 jOOQ 配置,也可以创建自己的org.jooq.Configuration
@Bean
。
使用NoSQL技术
Spring Data 提供了其他项目,可帮助您访问各种 NoSQL 技术,包括:MongoDB,Neo4J,Elasticsearch,Solr,Redis,Gemfire,Cassandra,Couchbase和LDAP。 Spring Boot 为 Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase 和 LDAP 提供自动配置。您可以使用其他项目,但是必须自己配置它们。请参考projects.spring.io/spring-data的相应参考文档。
Redis
Redis是缓存,消息代理和功能丰富的键值存储。 Spring Boot 为Lettuce和JedisClient 端库提供了基本的自动配置,以及Spring Data Redis提供的对它们的抽象。
有一个spring-boot-starter-data-redis
“启动程序”,以方便的方式收集依赖项。默认情况下,它使用Lettuce。该启动程序可以处理传统应用程序和响应式应用程序。
Tip
我们还提供
spring-boot-starter-data-redis-reactive
“Starter”,以与其他具有 Reactive 支持的 Store 保持一致。
连接到Redis
您可以像注入其他任何 Spring Bean 一样注入自动配置的RedisConnectionFactory
,StringRedisTemplate
或香草RedisTemplate
实例。默认情况下,该实例尝试连接到localhost:6379
的 Redis 服务器。下面的 Lists 显示了这种 Bean 的示例:
1 |
|
Tip
您还可以注册任意数量的实现
LettuceClientConfigurationBuilderCustomizer
的 bean,以进行更高级的自定义。如果您使用 Jedis,则JedisClientConfigurationBuilderCustomizer
也可用。
如果添加自己的任何自动配置类型的@Bean
,它将替换默认值(除非RedisTemplate
,但排除基于 Bean 名称redisTemplate
而不是其类型,则除外)。默认情况下,如果commons-pool2
在 Classpath 上,则将得到一个池化连接工厂。
MongoDB
MongoDB是一个开源 NoSQL 文档数据库,它使用类似 JSON 的架构而不是传统的基于表的关系数据。 Spring Boot 为使用 MongoDB 提供了许多便利,包括spring-boot-starter-data-mongodb
和spring-boot-starter-data-mongodb-reactive
“启动器”。
连接到MongoDB数据库
要访问 Mongo 数据库,您可以注入自动配置的org.springframework.data.mongodb.MongoDbFactory
。默认情况下,该实例尝试连接到mongodb://localhost/test
的 MongoDB 服务器。以下示例显示如何连接到 MongoDB 数据库:
1 | import org.springframework.data.mongodb.MongoDbFactory; |
您可以设置spring.data.mongodb.uri
属性来更改 URL 并配置其他设置,例如 replica set ,如以下示例所示:
1 | spring.data.mongodb.uri=mongodb://user:[emailprotected]:12345,mongo2.example.com:23456/test |
另外,只要您使用 Mongo 2.x,就可以指定host
/port
。例如,您可以在application.properties
中声明以下设置:
1 | mongoserver = |
如果您定义了自己的MongoClient
,它将用于自动配置合适的MongoDbFactory
。 com.mongodb.MongoClient
和com.mongodb.client.MongoClient
均受支持。
Note
如果使用 Mongo 3.0 Java 驱动程序,则不支持
spring.data.mongodb.host
和spring.data.mongodb.port
。在这种情况下,应使用spring.data.mongodb.uri
提供所有配置。Tip
如果未指定
spring.data.mongodb.port
,则使用默认值27017
。您可以从前面显示的示例中删除此行。Tip
如果您不使用 Spring Data Mongo,则可以注入
com.mongodb.MongoClient
bean 而不是MongoDbFactory
。如果要完全控制构建 MongoDB 连接的方式,则还可以声明自己的MongoDbFactory
或MongoClient
bean。Note
如果使用 Reactive 驱动程序,则 SSL 需要 Netty。如果 Netty 可用并且尚未自定义要使用的工厂,则自动配置会自动配置该工厂。
MongoTemplate
Spring Data MongoDB提供的MongoTemplate类的设计与 Spring 的JdbcTemplate
非常相似。与JdbcTemplate
一样,Spring Boot 为您自动配置一个 Bean 来注入模板,如下所示:
1 | import org.springframework.beans.factory.annotation.Autowired; |
有关完整的详细信息,请参见MongoOperations Javadoc。
SpringDataMongoDB存储库
Spring Data 包括对 MongoDB 的存储库支持。与前面讨论的 JPA 存储库一样,基本原理是根据方法名称自动构造查询。
实际上,Spring Data JPA 和 Spring Data MongoDB 共享相同的通用基础架构。您可以从前面的 JPA 示例开始,并假设City
现在是 Mongo 数据类而不是 JPA @Entity
,它的工作方式相同,如以下示例所示:
1 | package com.example.myapp.domain; |
Tip
您可以使用
@EntityScan
Comments 来自定义文档扫描位置。Tip
有关 Spring Data MongoDB 的完整详细信息,包括其丰富的对象 Map 技术,请参阅其reference documentation。
嵌入式Mongo
Spring Boot 为Embedded Mongo提供自动配置。要在您的 Spring Boot 应用程序中使用它,请在de.flapdoodle.embed:de.flapdoodle.embed.mongo
上添加一个依赖项。
可以通过设置spring.data.mongodb.port
属性来配置 Mongo 侦听的端口。要使用随机分配的空闲端口,请使用 0 值。由MongoAutoConfiguration
创建的MongoClient
自动配置为使用随机分配的端口。
Note
如果未配置自定义端口,则默认情况下,嵌入式支持使用随机端口(而不是 27017)。
如果 Classpath 上有 SLF4J,则 Mongo 产生的输出将自动路由到名为org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo
的 Logger。
您可以声明自己的IMongodConfig
和IRuntimeConfig
bean 来控制 Mongo 实例的配置和日志记录路由。
Neo4j
Neo4j是一个开源 NoSQL 图形数据库,它使用通过一级关系连接的节点的丰富数据模型,比传统的 RDBMS 方法更适合于连接的大数据。 Spring Boot 为 Neo4j 的使用提供了许多便利,包括spring-boot-starter-data-neo4j
“ Starter”。
连接到Neo4j数据库
要访问 Neo4j 服务器,您可以注入自动配置的org.neo4j.ogm.session.Session
。默认情况下,该实例尝试使用 Bolt 协议连接到localhost:7687
处的 Neo4j 服务器。以下示例显示如何注入 Neo4j Session
:
1 |
|
您可以通过设置spring.data.neo4j.*
属性来配置要使用的 uri 和凭据,如以下示例所示:
1 | bolt://my-server:7687 = |
您可以通过添加org.neo4j.ogm.config.Configuration
@Bean
来完全控制会话的创建。另外,添加类型为SessionFactory
的@Bean
会禁用自动配置,并提供完全控制权。
使用嵌入式模式
如果您将org.neo4j:neo4j-ogm-embedded-driver
添加到应用程序的依赖项中,则 Spring Boot 将自动配置 Neo4j 的进程内嵌入式实例,该实例在应用程序关闭时不会保留任何数据。
Note
由于嵌入式 Neo4j OGM 驱动程序本身不提供 Neo4j 内核,因此您必须自己声明
org.neo4j:neo4j
作为依赖项。有关兼容版本的列表,请参考Neo4j OGM 文档。
当 Classpath 上有多个驱动程序时,嵌入式驱动程序优先于其他驱动程序。您可以通过设置spring.data.neo4j.embedded.enabled=false
显式禁用嵌入式模式。
如上所述,如果嵌入式驱动程序和 Neo4j 内核位于 Classpath 中,则数据 Neo4j 测试自动使用嵌入式 Neo4j 实例。
Note
您可以通过在配置中提供数据库文件的路径来启用嵌入式模式的持久性。
spring.data.neo4j.uri=file://var/tmp/graph.db
。
Neo4jSession
默认情况下,如果您正在运行 Web 应用程序,则会话将绑定到线程以进行请求的整个处理(即,它使用“在视图中打开会话”模式)。如果您不希望出现这种情况,请将以下行添加到您的application.properties
文件中:
1 | false = |
SpringDataNeo4j存储库
Spring Data 包括对 Neo4j 的存储库支持。
Spring Data Neo4j 与许多其他 Spring Data 模块一样,与 Spring Data JPA 共享公共基础结构。您可以使用前面的 JPA 示例,并将City
定义为 Neo4j OGM @NodeEntity
而不是 JPA @Entity
,并且存储库抽象以相同的方式工作,如以下示例所示:
1 | package com.example.myapp.domain; |
spring-boot-starter-data-neo4j
“启动器”启用存储库支持以及事务 Management。您可以通过分别在@Configuration
-bean 上使用@EnableNeo4jRepositories
和@EntityScan
来定制位置以查找存储库和实体。
Tip
有关 Spring Data Neo4j 的完整详细信息,包括其对象 Map 技术,请参阅reference documentation。
Gemfire
Spring Data Gemfire提供了方便使用 Spring 的便捷工具,用于访问Pivotal Gemfire数据 Management 平台。有一个spring-boot-starter-data-gemfire
“启动器”,用于以方便的方式收集依赖项。 Gemfire 当前没有自动配置支持,但是您可以使用单个 Comments:@EnableGemfireRepositories启用 Spring Data Repositories。
Solr
Apache Solr是搜索引擎。 Spring Boot 为 Solr 5 Client 端库提供了基本的自动配置,并由Spring Data Solr提供了对它的抽象。有一个spring-boot-starter-data-solr
“启动程序”,用于以方便的方式收集依赖项。
连接到Solr
您可以像注入其他任何 Spring bean 一样注入自动配置的SolrClient
实例。默认情况下,该实例尝试连接到localhost:8983/solr
处的服务器。下面的示例显示如何注入 Solr bean:
1 |
|
如果添加自己的SolrClient
类型的@Bean
,它将替换默认值。
SpringDataSolr存储库
Spring Data 包括对 Apache Solr 的存储库支持。与前面讨论的 JPA 存储库一样,基本原理是根据方法名称自动为\构造查询。
实际上,Spring Data JPA 和 Spring Data Solr 共享相同的通用基础结构。您可以从以前的 JPA 示例开始,并假设City
现在是@SolrDocument
类而不是 JPA @Entity
,它的工作方式相同。
Tip
有关 Spring Data Solr 的完整详细信息,请参阅reference documentation。
Elasticsearch
Elasticsearch是开源,分布式,RESTful 搜索和分析引擎。 Spring Boot 为 Elasticsearch 提供了基本的自动配置。
Spring Boot 支持多个 HTTP Client 端:
- 官方 Java“低级”和“高级” REST Client 端
- Jest
Spring Data Elasticsearch仍在使用传输 Client 端,您可以从spring-boot-starter-data-elasticsearch
“ Starter”开始使用。
通过 RESTClient端连接到Elasticsearch
Elasticsearch 附带了两个不同的 REST Client 端,可用于查询集群:“低级”Client 端和“高级”Client 端。
如果您对 Classpath 具有org.elasticsearch.client:elasticsearch-rest-client
依赖关系,Spring Boot 将自动配置并注册一个RestClient
bean,默认情况下它针对localhost:9200
。您可以进一步调整RestClient
的配置方式,如以下示例所示:
1 | http://search.example.com:9200 = |
您还可以注册任意数量的实现RestClientBuilderCustomizer
的 bean,以进行更高级的自定义。要完全控制注册,请定义一个RestClient
bean。
如果您对 Classpath 具有org.elasticsearch.client:elasticsearch-rest-high-level-client
依赖性,则 Spring Boot 将自动配置RestHighLevelClient
,该_包装任何现有的RestClient
bean,并重新使用其 HTTP 配置。
使用Jest连接到Elasticsearch
如果您在 Classpath 上有Jest
,则可以注入自动配置的JestClient
,默认情况下以localhost:9200
为目标。您可以进一步调整 Client 端的配置方式,如以下示例所示:
1 | http://search.example.com:9200 = |
您还可以注册任意数量的实现HttpClientConfigBuilderCustomizer
的 bean,以进行更高级的自定义。以下示例调整其他 HTTP 设置:
1 | static class HttpSettingsCustomizer implements HttpClientConfigBuilderCustomizer { |
要完全控制注册,请定义一个JestClient
bean。
使用Spring数据连接到Elasticsearch
要连接到 Elasticsearch,您必须提供一个或多个集群节点的地址。可以通过将spring.data.elasticsearch.cluster-nodes
属性设置为逗号分隔的host:port
列表来指定地址。有了此配置后,就可以像其他任何 Spring bean 一样注入ElasticsearchTemplate
或TransportClient
,如以下示例所示:
1 | spring.data.elasticsearch.cluster-nodes=localhost:9300 |
如果添加自己的ElasticsearchTemplate
或TransportClient
@Bean
,它将替换默认值。
SpringDataElasticsearch存储库
Spring Data 包括对 Elasticsearch 的存储库支持。与前面讨论的 JPA 存储库一样,基本原理是根据方法名称自动为您构造查询。
实际上,Spring Data JPA 和 Spring Data Elasticsearch 共享相同的通用基础架构。您可以从前面的 JPA 示例开始,并假设City
现在是 Elasticsearch @Document
类而不是 JPA @Entity
,它的工作方式相同。
Tip
有关 Spring Data Elasticsearch 的完整详细信息,请参阅reference documentation。
Cassandra
Cassandra是一个开放源代码的分布式数据库 Management 系统,旨在处理许多商品服务器上的大量数据。 Spring Boot 为 Cassandra 提供自动配置,并由Spring Data Cassandra提供最高级的抽象。有一个spring-boot-starter-data-cassandra
“启动程序”,用于以方便的方式收集依赖项。
连接到Cassandra
您可以像使用其他任何 Spring Bean 一样注入自动配置的CassandraTemplate
或 Cassandra Session
实例。 spring.data.cassandra.*
属性可用于自定义连接。通常,您提供keyspace-name
和contact-points
属性,如以下示例所示:
1 | mykeyspace = |
您还可以注册任意数量的实现ClusterBuilderCustomizer
的 bean,以进行更高级的自定义。
以下代码 Lists 显示了如何注入 Cassandra bean:
1 |
|
如果添加自己的CassandraTemplate
类型的@Bean
,它将替换默认值。
SpringDataCassandra存储库
Spring Data 包括对 Cassandra 的基本存储库支持。当前,这比前面讨论的 JPA 存储库受到更多限制,并且需要使用@Query
Comments finder 方法。
Tip
有关 Spring Data Cassandra 的完整详细信息,请参阅reference documentation。
Couchbase
Couchbase是开放源代码,分布式,多模型的 NoSQL 面向文档的数据库,已针对交互式应用程序进行了优化。 Spring Boot 为 Couchbase 提供自动配置,并由Spring Data Couchbase提供最高级的抽象。有spring-boot-starter-data-couchbase
和spring-boot-starter-data-couchbase-reactive
个“启动程序”,以方便的方式收集依赖项。
连接到Couchbase
您可以通过添加 Couchbase SDK 和一些配置来获得Bucket
和Cluster
。 spring.couchbase.*
属性可用于自定义连接。通常,您提供引导主机,存储桶名称和密码,如以下示例所示:
1 | my-host-1,192.168.1.123 = |
Tip
您至少需要提供*引导主机,在这种情况下,存储区名称为
default
,密码为空字符串。另外,您可以定义自己的org.springframework.data.couchbase.config.CouchbaseConfigurer
@Bean
来控制整个配置。
还可以自定义某些CouchbaseEnvironment
设置。例如,以下配置更改了用于打开新的Bucket
的超时并启用了 SSL 支持:
1 | 3000 = |
查看spring.couchbase.env.*
属性以获取更多详细信息。
SpringDataCouchbase存储库
Spring Data 包括对 Couchbase 的存储库支持。有关 Spring Data Couchbase 的完整详细信息,请参阅reference documentation。
您可以像使用任何其他 Spring Bean 一样注入自动配置的CouchbaseTemplate
实例,前提是 default CouchbaseConfigurer
可用(如前所述,启用 Couchbase 支持时会发生这种情况)。
以下示例显示了如何注入 Couchbase bean:
1 |
|
您可以在自己的配置中定义一些 Bean,以覆盖自动配置提供的那些:
- 名称为
couchbaseTemplate
的CouchbaseTemplate
@Bean
。 - 名为
couchbaseIndexManager
的IndexManager
@Bean
。 - 名称为
couchbaseCustomConversions
的CustomConversions
@Bean
。
为了避免在您自己的配置中对这些名称进行硬编码,您可以重复使用 Spring Data Couchbase 提供的BeanNames
。例如,您可以自定义要使用的转换器,如下所示:
1 |
|
Tip
如果您想完全绕过 Spring Data Couchbase 的自动配置,请提供自己的
org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration
实现。
LDAP
LDAP(轻型目录访问协议)是一种开放的,与供应商无关的行业标准应用程序协议,用于通过 IP 网络访问和维护分布式目录信息服务。 Spring Boot 为任何兼容的 LDAP 服务器提供自动配置,并从UnboundID支持嵌入式内存 LDAP 服务器。
Spring Data LDAP提供 LDAP 抽象。有一个spring-boot-starter-data-ldap
“启动程序”,以方便的方式收集依赖项。
连接到LDAP服务器
要连接到 LDAP 服务器,请确保声明对spring-boot-starter-data-ldap
“ Starter”或spring-ldap-core
的依赖关系,然后在 application.properties 中声明服务器的 URL,如以下示例所示:
1 | ldap://myserver:1235 = |
如果需要自定义连接设置,则可以使用spring.ldap.base
和spring.ldap.base-environment
属性。
LdapContextSource
是根据这些设置自动配置的。如果您需要对其进行自定义(例如使用PooledContextSource
),则仍可以注入自动配置的LdapContextSource
。确保将自定义的ContextSource
标记为@Primary
,以便自动配置的LdapTemplate
使用它。
SpringDataLDAP存储库
Spring Data 包括对 LDAP 的存储库支持。有关 Spring Data LDAP 的完整详细信息,请参阅reference documentation。
您还可以像使用其他任何 Spring Bean 一样注入自动配置的LdapTemplate
实例,如以下示例所示:
1 |
|
嵌入式内存LDAP服务器
出于测试目的,Spring Boot 支持从UnboundID自动配置内存中的 LDAP 服务器。要配置服务器,请将依赖项添加到com.unboundid:unboundid-ldapsdk
并声明base-dn
属性,如下所示:
1 | dc=spring,dc=io = |
Note
可以定义多个 base-dn 值,但是,由于可分辨的名称通常包含逗号,因此必须使用正确的符号来定义它们。
在 yaml 文件中,您可以使用 yaml 列表符号:
1 | : |
在属性文件中,必须将索引包括在属性名称中:
1 | dc=spring,dc=io = |
默认情况下,服务器在随机端口上启动并触发常规 LDAP 支持。无需指定spring.ldap.urls
属性。
如果您的 Classpath 上有一个schema.ldif
文件,它将用于初始化服务器。如果要从其他资源加载初始化脚本,则也可以使用spring.ldap.embedded.ldif
属性。
默认情况下,使用标准架构来验证LDIF
个文件。您可以通过设置spring.ldap.embedded.validation.enabled
属性完全关闭验证。如果您具有自定义属性,则可以使用spring.ldap.embedded.validation.schema
定义您的自定义属性类型或对象类。
InfluxDB
InfluxDB是开放源代码的时间序列数据库,已优化用于在操作监视,应用程序度量,物联网传感器数据和实时分析等领域中快速,高可用性地存储和检索时间序列数据。
连接到nfluxDB
只要influxdb-java
Client 端位于 Classpath 上并且设置了数据库的 URL,Spring Boot 就会自动配置InfluxDB
实例,如以下示例所示:
1 | http://172.0.0.1:8086 = |
如果与 InfluxDB 的连接需要用户和密码,则可以相应地设置spring.influx.user
和spring.influx.password
属性。
InfluxDB 依赖 OkHttp。如果需要在后台调整 http Client 端InfluxDB
的使用,则可以注册InfluxDbOkHttpClientBuilderProvider
bean。
Caching
Spring 框架提供了对向应用程序透明添加缓存的支持。从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。缓存逻辑是透明应用的,不会对调用者造成任何干扰。只要通过@EnableCaching
Comments 启用了缓存支持,Spring Boot 就会自动配置缓存基础结构。
Note
查看 Spring 框架参考的relevant section以获得更多详细信息。
简而言之,将缓存添加到服务的操作就像将相关 Comments 添加到其方法一样容易,如以下示例所示:
1 | import org.springframework.cache.annotation.Cacheable; |
本示例说明了在可能耗资巨大的操作上使用缓存的方法。在调用computePiDecimal
之前,抽象将在piDecimals
缓存中查找与i
参数匹配的条目。如果找到条目,则高速缓存中的内容会立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。
Warning
您还可以透明地使用标准 JSR-107(JCache)注解(例如
@CacheResult
)。但是,我们强烈建议您不要混合使用 Spring Cache 和 JCache 注解。如果您不添加任何特定的缓存库,Spring Boot 会自动配置一个使用内存中并发 Map 的simple provider。需要缓存时(例如上例中的
piDecimals
),此提供程序将为您创建它。实际上,不建议将简单提供程序用于生产用途,但是它对于 Starter 并确保您了解功能非常有用。确定要使用的缓存提供程序后,请确保阅读其文档,以了解如何配置应用程序使用的缓存。几乎所有提供程序都要求您显式配置在应用程序中使用的每个缓存。有些提供了一种自定义spring.cache.cache-names
属性定义的默认缓存的方法。Tip
支持的缓存提供程序
缓存抽象不提供实际的存储,而是依赖于org.springframework.cache.Cache
和org.springframework.cache.CacheManager
接口实现的抽象。
如果尚未定义类型CacheManager
或名为cacheResolver
的CacheResolver
(请参见CachingConfigurer),则 Spring Boot 尝试检测以下提供程序(按指示的 Sequences):
- Generic
- JCache (JSR-107))(EhCache 3,Hazelcast,Infinispan 等)
- EhCache 2.x
- Hazelcast
- Infinispan
- Couchbase
- Redis
- Caffeine
- Simple
Tip
也可以通过设置
spring.cache.type
属性来“强制”特定的缓存提供程序。如果需要在某些环境(例如测试)中完全禁用缓存,请使用此属性。Tip
使用
spring-boot-starter-cache
“Starter”快速添加基本的缓存依赖项。启动器带来spring-context-support
。如果手动添加依赖项,则必须包含spring-context-support
才能使用 JCache,EhCache 2.x 或 Guava 支持。
如果CacheManager
是由 Spring Boot 自动配置的,则可以通过公开实现CacheManagerCustomizer
接口的 bean,在完全初始化之前进一步调整其配置。下面的示例设置一个标志,指示应该将空值向下传递到基础 Map:
1 |
|
Note
在前面的示例中,应使用自动配置的
ConcurrentMapCacheManager
。如果不是这种情况(您提供了自己的配置,或者自动配置了其他缓存提供程序),则根本不会调用定制程序。您可以根据需要拥有任意数量的定制程序,也可以使用@Order
或Ordered
对其进行排序。
Generic
如果上下文至少定义了一个org.springframework.cache.Cache
bean,则使用通用缓存。创建一个CacheManager
包装该类型的所有 bean。
JCache(JSR-107)
JCache通过 Classpath 上存在javax.cache.spi.CachingProvider
进行引导(即,Classpath 上存在符合 JSR-107 的缓存库),并且JCacheCacheManager
由spring-boot-starter-cache
“启动程序”提供。提供了各种兼容的库,Spring Boot 为 Ehcache 3,Hazelcast 和 Infinispan 提供了依赖 Management。也可以添加任何其他兼容的库。
可能会出现多个提供者,在这种情况下,必须明确指定提供者。即使 JSR-107 标准没有强制采用标准化的方式来定义配置文件的位置,Spring Boot 也会尽其所能以设置具有实现细节的缓存,如以下示例所示:
1 | # Only necessary if more than one provider is present |
Note
当缓存库同时提供本机实现和 JSR-107 支持时,Spring Boot 会首选 JSR-107 支持,因此,如果您切换到其他 JSR-107 实现,则可以使用相同的功能。
Tip
Spring Boot 具有对 Hazelcast 的常规支持。如果有一个
HazelcastInstance
可用,则除非指定spring.cache.jcache.config
属性,否则它也会自动为CacheManager
重用。
自定义基础javax.cache.cacheManager
的方法有两种:
- 可以在启动时通过设置
spring.cache.cache-names
属性来创建缓存。如果定义了自定义javax.cache.configuration.Configuration
bean,则将其用于自定义它们。 org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer
bean 与CacheManager
的引用一起调用以进行完全自定义。
Tip
如果定义了一个标准的
javax.cache.CacheManager
bean,它将自动包装在抽象期望的org.springframework.cache.CacheManager
实现中。不再对其应用定制。
EhCache2.x
如果可以在 Classpath 的根目录下找到名为ehcache.xml
的文件,则使用EhCache2.x。如果找到 EhCache 2.x,则使用spring-boot-starter-cache
“启动程序”提供的EhCacheCacheManager
来引导缓存 Management 器。也可以提供备用配置文件,如以下示例所示:
1 | classpath:config/another-config.xml = |
Hazelcast缓存
Spring Boot 具有对 Hazelcast 的常规支持。如果已自动配置HazelcastInstance
,则会自动将其包装在CacheManager
中。
Infinispan
Infinispan没有默认配置文件位置,因此必须明确指定。否则,将使用默认的引导程序。
1 | infinispan.xml = |
可以在启动时通过设置spring.cache.cache-names
属性来创建缓存。如果定义了自定义ConfigurationBuilder
bean,则用于自定义缓存。
Note
Spring Boot 对 Infinispan 的支持仅限于嵌入式模式,并且非常基础。如果您需要更多选择,则应该使用官方的 Infinispan Spring Boot 启动程序。有关更多详细信息,请参见Infinispan’s documentation。
Couchbase
如果Couchbase Java Client 端和couchbase-spring-cache
实现可用且 Couchbase 为configured,则将自动配置CouchbaseCacheManager
。也可以通过设置spring.cache.cache-names
属性在启动时创建其他缓存。这些缓存在自动配置的Bucket
上运行。您还可以*使用定制程序在另一个Bucket
上创建其他缓存。假设您在“主” Bucket
上需要两个缓存(cache1
和cache2
),在(另一个)Bucket
上需要一个缓存(cache3
)的自定义时间为 2 秒。您可以通过配置创建前两个缓存,如下所示:
1 | cache1,cache2 = |
然后,您可以定义一个@Configuration
类来配置额外的Bucket
和cache3
缓存,如下所示:
1 |
|
此示例配置重复使用通过自动配置创建的Cluster
。
Redis
如果Redis可用并已配置,则将自动配置RedisCacheManager
。可以通过设置spring.cache.cache-names
属性在启动时创建其他缓存,并且可以使用spring.cache.redis.*
属性配置缓存默认值。例如,以下配置创建了“生存时间”为 10 分钟的cache1
和cache2
缓存:
1 | cache1,cache2 = |
Note
默认情况下,添加密钥前缀,以便如果两个单独的缓存使用相同的密钥,则 Redis 不会有重叠的密钥,并且不能返回无效值。如果您创建自己的
RedisCacheManager
,强烈建议您启用此设置。Tip
您可以添加自己的
RedisCacheConfiguration
@Bean
,从而完全控制配置。如果您要自定义序列化策略,这将很有用。
Caffeine
Caffeine是对 Guava 缓存的 Java 8 重写,取代了对 Guava 的支持。如果存在 Caffeine,则会自动配置CaffeineCacheManager
(由spring-boot-starter-cache
“Starter”提供)。缓存可以在启动时通过设置spring.cache.cache-names
属性来创建,并且可以通过以下方式之一自定义(按指示的 Sequences):
spring.cache.caffeine.spec
定义的缓存规范- 定义了一个
com.github.benmanes.caffeine.cache.CaffeineSpec
bean - 定义了一个
com.github.benmanes.caffeine.cache.Caffeine
bean
例如,以下配置创建cache1
和cache2
缓存,最大大小为 500,并且生存时间为 10 分钟
1 | cache1,cache2 = |
如果定义了com.github.benmanes.caffeine.cache.CacheLoader
bean,它将自动与CaffeineCacheManager
关联。由于CacheLoader
将与由缓存 Management 器 Management 的 all 缓存相关联,因此必须将其定义为CacheLoader<Object, Object>
。自动配置将忽略任何其他通用类型。
Simple
如果找不到其他提供者,则配置使用ConcurrentHashMap
作为缓存存储区的简单实现。如果您的应用程序中不存在任何缓存库,则这是默认设置。默认情况下,将根据需要创建缓存,但是您可以通过设置cache-names
属性来限制可用缓存的列表。例如,如果只需要cache1
和cache2
缓存,则按如下所示设置cache-names
属性:
1 | cache1,cache2 = |
如果这样做,并且您的应用程序使用了未列出的缓存,那么当需要该缓存时,它将在运行时失败,但不会在启动时失败。这类似于使用未声明的缓存时“实际”缓存提供程序的行为。
None
当您的配置中包含@EnableCaching
时,也需要合适的缓存配置。如果需要在某些环境中完全禁用缓存,请强制将缓存类型设置为none
以使用无操作实现,如以下示例所示:
1 | none = |
消息
Spring 框架为与消息传递系统集成提供了广泛的支持,从简化使用JmsTemplate
的 JMS API 的使用到完整的异步接收消息的基础结构。 Spring AMQP 为高级消息队列协议提供了类似的功能集。 Spring Boot 还为RabbitTemplate
和 RabbitMQ 提供了自动配置选项。 Spring WebSocket 本身就包含对 STOMP 消息的支持,而 Spring Boot 通过启动程序和少量的自动配置对此提供了支持。 Spring Boot 还支持 Apache Kafka。
JMS
javax.jms.ConnectionFactory
接口提供了创建javax.jms.Connection
与 JMS 代理进行交互的标准方法。尽管 Spring 需要ConnectionFactory
才能与 JMS 一起使用,但是您通常不需要自己直接使用它,而是可以依靠更高级别的消息抽象。 (有关详细信息,请参见 Spring Framework 参考文档的relevant section。)Spring Boot 还自动配置必要的基础结构来发送和接收消息。
ActiveMQ支持
当ActiveMQ在 Classpath 上可用时,Spring Boot 也可以配置ConnectionFactory
。如果存在代理,则将自动启动和配置嵌入式代理(前提是未通过配置指定代理 URL)。
Note
如果使用
spring-boot-starter-activemq
,则将提供连接或嵌入 ActiveMQ 实例所需的依赖关系,以及与 JMS 集成的 Spring 基础结构。
ActiveMQ 配置由spring.activemq.*
中的外部配置属性控制。例如,您可以在application.properties
中声明以下部分:
1 | tcp://192.168.1.210:9876 = |
默认情况下,CachingConnectionFactory
使用可以由spring.jms.*
中的外部配置属性控制的明智设置来包装本机ConnectionFactory
:
1 | 5 = |
如果您想使用本机池,则可以通过向org.messaginghub:pooled-jms
添加依赖项并相应地配置JmsPoolConnectionFactory
来实现,如下例所示:
1 | true = |
Tip
有关更多受支持的选项,请参见ActiveMQProperties。您还可以注册任意数量的实现
ActiveMQConnectionFactoryCustomizer
的 bean,以进行更高级的自定义。
默认情况下,ActiveMQ 将创建一个目的地(如果目的地尚不存在),以便根据其提供的名称来解析目的地。
Artemis支持
当 Spring Boot 检测到Artemis在 Classpath 中可用时,它可以自动配置ConnectionFactory
。如果存在代理,则将自动启动和配置嵌入式代理(除非已明确设置 mode 属性)。支持的模式为embedded
(以明确要求使用嵌入式代理,并且如果代理在 Classpath 上不可用,则会发生错误)和native
(使用netty
传输协议连接到代理)。配置后者后,Spring Boot 将使用默认设置配置一个ConnectionFactory
,该ConnectionFactory
连接到在本地计算机上运行的代理。
Note
如果使用
spring-boot-starter-artemis
,则将提供连接到现有 Artemis 实例所需的依赖关系,以及与 JMS 集成的 Spring 基础结构。将org.apache.activemq:artemis-jms-server
添加到您的应用程序可让您使用嵌入式模式。
Artemis 配置由spring.artemis.*
中的外部配置属性控制。例如,您可以在application.properties
中声明以下部分:
1 | native = |
嵌入代理时,可以选择是否要启用持久性并列出应使其可用的目的地。可以将它们指定为以逗号分隔的列表,以使用默认选项创建它们,也可以为高级队列和主题配置分别定义类型org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration
或org.apache.activemq.artemis.jms.server.config.TopicConfiguration
的 bean。
默认情况下,CachingConnectionFactory
使用可以由spring.jms.*
中的外部配置属性控制的明智设置来包装本机ConnectionFactory
:
1 | 5 = |
如果您想使用本机池,则可以通过向org.messaginghub:pooled-jms
添加依赖项并相应地配置JmsPoolConnectionFactory
来实现,如下例所示:
1 | true = |
有关更多受支持的选项,请参见ArtemisProperties。
不涉及 JNDI 查找,并且使用 Artemis 配置中的name
属性或通过配置提供的名称来根据目的地名称解析目的地。
使用JNDI连接工厂
如果您正在应用程序服务器中运行应用程序,则 Spring Boot 会尝试使用 JNDI 查找 JMS ConnectionFactory
。默认情况下,选中java:/JmsXA
和java:/XAConnectionFactory
位置。如果需要指定替代位置,则可以使用spring.jms.jndi-name
属性,如以下示例所示:
1 | java:/MyConnectionFactory = |
发送消息
Spring 的JmsTemplate
是自动配置的,您可以将其直接自动连接到自己的 bean 中,如以下示例所示:
1 | import org.springframework.beans.factory.annotation.Autowired; |
Note
JmsMessagingTemplate可以类似的方式注入。如果定义了
DestinationResolver
或MessageConverter
bean,则将其自动关联到自动配置的JmsTemplate
。
接收消息
存在 JMS 基础结构时,可以使用@JmsListener
Comments 任何 bean 以创建侦听器端点。如果未定义JmsListenerContainerFactory
,则会自动配置一个默认值。如果定义了DestinationResolver
或MessageConverter
bean,它将自动关联到默认工厂。
默认情况下,默认工厂是事务性的。如果您在存在JtaTransactionManager
的基础结构中运行,则默认情况下会将其与侦听器容器关联。如果不是,则启用sessionTransacted
标志。在后一种情况下,可以通过在侦听器方法(或其委托)上添加@Transactional
来将本地数据存储事务与传入消息的处理相关联。这样可以确保本地事务完成后,传入消息得到确认。这还包括发送已在同一 JMS 会话上执行的响应消息。
以下组件在someQueue
目标上创建侦听器端点:
1 |
|
Tip
有关更多详细信息,请参见@EnableJms 的 Javadoc。
如果您需要创建更多的JmsListenerContainerFactory
实例,或者想覆盖默认实例,Spring Boot 提供了一个DefaultJmsListenerContainerFactoryConfigurer
,您可以使用与自动配置的设置相同的设置来初始化DefaultJmsListenerContainerFactory
。
例如,以下示例公开了另一个使用特定MessageConverter
的工厂:
1 |
|
然后,您可以在任何带有@JmsListener
Comments 的方法中使用工厂,如下所示:
1 |
|
AMQP
高级消息队列协议(AMQP)是面向消息中间件的与平台无关的有线级别协议。 Spring AMQP 项目将 Spring 的核心概念应用于基于 AMQP 的消息传递解决方案的开发。 Spring Boot 为通过 RabbitMQ 使用 AMQP 提供了许多便利,包括spring-boot-starter-amqp
“ Starter”。
RabbitMQ 支持
RabbitMQ是基于 AMQP 协议的轻型,可靠,可伸缩和便携式消息代理。 Spring 使用RabbitMQ
通过 AMQP 协议进行通信。
RabbitMQ 配置由spring.rabbitmq.*
中的外部配置属性控制。例如,您可以在application.properties
中声明以下部分:
1 | localhost = |
如果上下文中存在ConnectionNameStrategy
bean,它将自动用于命名由自动配置的ConnectionFactory
创建的连接。有关更多受支持的选项,请参见RabbitProperties。
Tip
有关更多详细信息,请参见了解 AMQP,RabbitMQ 使用的协议。
发送信息
Spring 的AmqpTemplate
和AmqpAdmin
是自动配置的,您可以将它们直接自动连接到自己的 bean 中,如以下示例所示:
1 | import org.springframework.amqp.core.AmqpAdmin; |
Note
RabbitMessagingTemplate可以类似的方式注入。如果定义了
MessageConverter
bean,它将自动关联到自动配置的AmqpTemplate
。
如有必要,任何定义为 bean 的org.springframework.amqp.core.Queue
都会自动用于在 RabbitMQ 实例上声明相应的队列。
要重试操作,可以在AmqpTemplate
上启用重试(例如,在代理连接丢失的情况下):
1 | true = |
默认情况下,重试是禁用的。您还可以pass 语句RabbitRetryTemplateCustomizer
bean 来以编程方式自定义RetryTemplate
。
接收消息
存在 Rabbit 基础结构时,可以使用@RabbitListener
Comments 任何 bean 以创建侦听器端点。如果未定义RabbitListenerContainerFactory
,则会自动配置默认的SimpleRabbitListenerContainerFactory
,并且可以使用spring.rabbitmq.listener.type
属性切换到直接容器。如果定义了MessageConverter
或MessageRecoverer
bean,它将自动与默认工厂关联。
以下示例组件在someQueue
队列上创建一个侦听器端点:
1 |
|
Tip
有关更多详细信息,请参见@EnableRabbit 的 Javadoc。
如果您需要创建更多的RabbitListenerContainerFactory
实例,或者想覆盖默认实例,Spring Boot 提供了SimpleRabbitListenerContainerFactoryConfigurer
和DirectRabbitListenerContainerFactoryConfigurer
,您可以使用它们设置与自动配置使用的工厂相同的设置来初始化SimpleRabbitListenerContainerFactory
和DirectRabbitListenerContainerFactory
。
Tip
选择哪种容器都没有关系。这两个 bean 通过自动配置公开。
例如,以下配置类公开了另一个使用特定MessageConverter
的工厂:
1 |
|
然后,您可以使用任何带有@RabbitListener
Comments 的方法来使用工厂,如下所示:
1 |
|
您可以启用重试来处理侦听器引发异常的情况。默认情况下,使用RejectAndDontRequeueRecoverer
,但是您可以定义自己的MessageRecoverer
。重试用尽后,如果将代理配置为这样做,则消息将被拒绝并被丢弃或路由到死信交换。默认情况下,重试是禁用的。您也可以pass 语句RabbitRetryTemplateCustomizer
bean 来以编程方式自定义RetryTemplate
。
Tip
默认情况下,如果禁用了重试,并且侦听器引发了异常,则会无限期地重试传递。您可以通过两种方式修改此行为:将
defaultRequeueRejected
属性设置为false
,以便尝试进行零次重新传递或抛出AmqpRejectAndDontRequeueException
来指示应拒绝该消息。后者是启用重试并达到最大传递尝试次数时使用的机制。
ApacheKafka支持
通过提供spring-kafka
项目的自动配置来支持Apache Kafka。
Kafka 配置由spring.kafka.*
中的外部配置属性控制。例如,您可以在application.properties
中声明以下部分:
1 | localhost:9092 = |
Tip
要在启动时创建主题,请添加
NewTopic
类型的 Bean。如果该主题已经存在,则将忽略 Bean。
有关更多受支持的选项,请参见KafkaProperties。
发送消息
Spring 的KafkaTemplate
是自动配置的,您可以直接在自己的 bean 中自动对其进行布线,如以下示例所示:
1 |
|
Note
如果定义了属性
spring.kafka.producer.transaction-id-prefix
,则会自动配置KafkaTransactionManager
。同样,如果定义了RecordMessageConverter
bean,它将自动与自动配置的KafkaTemplate
关联。
接收消息
存在 Apache Kafka 基础结构时,可以使用@KafkaListener
Comments 任何 bean 以创建侦听器端点。如果未定义KafkaListenerContainerFactory
,则会使用spring.kafka.listener.*
中定义的键自动配置一个默认值。
以下组件在someTopic
主题上创建侦听器终结点:
1 |
|
如果定义了KafkaTransactionManager
bean,它将自动与容器工厂关联。同样,如果定义了RecordMessageConverter
,ErrorHandler
或AfterRollbackProcessor
bean,它将自动与默认工厂关联。
Tip
自定义
ChainedKafkaTransactionManager
必须标记为@Primary
,因为它通常引用自动配置的KafkaTransactionManager
bean。
Kafka流
用于 Apache Kafka 的 Spring 提供了一个工厂 bean 来创建StreamsBuilder
对象并 Management 其流的生命周期。只要kafka-streams
在 Classpath 上并且通过@EnableKafkaStreams
Comments 启用 Kafka Streams,Spring Boot 就会自动配置所需的KafkaStreamsConfiguration
bean。
启用 Kafka Streams 意味着必须设置应用程序 ID 和引导服务器。可以使用spring.kafka.streams.application-id
配置前者,如果未设置,则默认为spring.application.name
。后者可以全局设置,也可以仅针对流进行覆盖。
使用专用属性可以使用几个附加属性。可以使用spring.kafka.streams.properties
名称空间设置其他任意 Kafka 属性。另请参见“其他 Kafka 属性”。
要使用工厂 bean,只需将StreamsBuilder
连接到您的@Bean
中,如以下示例所示:
1 |
|
默认情况下,由它创建的StreamBuilder
对象 Management 的流将自动启动。您可以使用spring.kafka.streams.auto-startup
属性来自定义此行为。
Kafka的其他属性
自动配置支持的属性显示在附录 A,通用应用程序属性中。请注意,在大多数情况下,这些属性(连字符或 camelCase)直接 Map 到 Apache Kafka 点缀属性。有关详细信息,请参阅 Apache Kafka 文档。
这些属性的前几个属性适用于所有组件(生产者,使用者,Management 员和流),但如果您希望使用不同的值,则可以在组件级别上指定。 Apache Kafka 会指定重要性为 HIGH,MEDIUM 或 LOW 的属性。 Spring Boot 自动配置支持所有 HIGH 重要性属性,一些选定的 MEDIUM 和 LOW 属性以及任何没有默认值的属性。
Kafka 支持的属性的子集仅可通过KafkaProperties
类直接使用。如果希望使用不直接支持的其他属性来配置生产者或使用者,请使用以下属性:
1 | first = |
这将公共prop.one
Kafka 属性设置为first
(适用于生产者,Consumer 和 Management 员),将prop.two
admin 属性设置为second
,将prop.three
Consumer 属性设置为third
,将prop.four
生产者属性设置为fourth
,并将prop.five
streams 属性设置为fifth
。
您还可以如下配置 Spring Kafka JsonDeserializer
:
1 | org.springframework.kafka.support.serializer.JsonDeserializer = |
同样,您可以禁用在 Headers 中发送类型信息的JsonSerializer
默认行为:
1 | org.springframework.kafka.support.serializer.JsonSerializer = |
Tip
以这种方式设置的属性将覆盖 Spring Boot 显式支持的任何配置项。
使用RestTemplate调用REST服务
如果您需要从应用程序中调用远程 REST 服务,则可以使用 Spring Framework 的RestTemplate类。由于RestTemplate
实例在使用前通常需要自定义,因此 Spring Boot 不提供任何单个自动配置的RestTemplate
bean。但是,它会自动配置RestTemplateBuilder
,可以在需要时创建RestTemplate
实例。自动配置的RestTemplateBuilder
确保将明智的HttpMessageConverters
应用于RestTemplate
实例。
以下代码显示了一个典型示例:
1 |
|
Tip
RestTemplateBuilder
包含许多可用于快速配置RestTemplate
的有用方法。例如,要添加 BASIC 身份验证支持,可以使用builder.basicAuthentication("user", "password").build()
。
RestTemplate自定义
RestTemplate
自定义有三种 Main 方法,具体取决于您希望自定义应用的范围。
要使所有自定义项的范围尽可能缩小,请注入自动配置的RestTemplateBuilder
,然后根据需要调用其方法。每个方法调用都返回一个新的RestTemplateBuilder
实例,因此自定义仅影响构建器的使用。
要进行应用程序范围的附加自定义,请使用RestTemplateCustomizer
bean。所有此类 bean 都会自动注册到自动配置的RestTemplateBuilder
中,并应用于使用它构建的任何模板。
以下示例显示了一个定制程序,该定制程序为除192.168.0.5
之外的所有主机配置代理的使用:
1 | static class ProxyCustomizer implements RestTemplateCustomizer { |
最后,最极端(也是很少使用)的选项是创建自己的RestTemplateBuilder
bean。这样做会关闭RestTemplateBuilder
的自动配置,并防止使用任何RestTemplateCustomizer
bean。
使用WebClient调用REST服务
如果您的 Classpath 中包含 Spring WebFlux,则还可以选择使用WebClient
来调用远程 REST 服务。与RestTemplate
相比,此 Client 端具有更多的功能感,并且具有完全的 Reactive。您可以在专用的Spring Framework 文档中的部分中了解有关WebClient
的更多信息。
Spring Boot 为您创建并预配置了WebClient.Builder
;强烈建议将其注入您的组件中并使用它来创建WebClient
实例。 Spring Boot 正在配置该构建器以共享 HTTP 资源,以与服务器相同的方式反映编解码器的设置(请参阅WebFlux HTTP 编解码器自动配置,以及更多。
以下代码显示了一个典型示例:
1 |
|
WebClient运行时
Spring Boot 将根据应用程序 Classpath 上可用的库自动检测要使用哪个ClientHttpConnector
来驱动WebClient
。目前,还支持 Reactor Netty 和 Jetty RS Client 端。
默认情况下,spring-boot-starter-webflux
启动程序取决于io.projectreactor.netty:reactor-netty
,这同时带来了服务器和 Client 端实现。如果选择使用 Jetty 作为反应式服务器,则应在 Jetty 反应式 HTTP Client 端库org.eclipse.jetty:jetty-reactive-httpclient
上添加依赖项。对服务器和 Client 端使用相同的技术具有其优势,因为它将自动在 Client 端和服务器之间共享 HTTP 资源。
通过提供自定义的ReactorResourceFactory
或JettyResourceFactory
bean,开发人员可以覆盖 Jetty 和 Reactor Netty 的资源配置-这将同时应用于 Client 端和服务器。
如果您希望为 Client 端覆盖该选择,则可以定义自己的ClientHttpConnector
bean 并完全控制 Client 端配置。
您可以了解有关Spring Framework 参考文档中的 WebClient 配置选项的更多信息。
WebClient自定义
WebClient
自定义有三种 Main 方法,具体取决于您希望自定义应用的范围。
要使所有自定义项的范围尽可能缩小,请注入自动配置的WebClient.Builder
,然后根据需要调用其方法。 WebClient.Builder
实例是有状态的:构建器上的任何更改都会反映在随后使用它创建的所有 Client 端中。如果要使用同一构建器创建多个 Client 端,则也可以考虑使用WebClient.Builder other = builder.clone();
克隆该构建器。
要对所有WebClient.Builder
实例进行应用程序级的附加自定义,您可以声明WebClientCustomizer
bean 并在注入点更改WebClient.Builder
。
最后,您可以使用原始 API 并使用WebClient.create()
。在这种情况下,不会应用任何自动配置或WebClientCustomizer
。
Validation
只要 JSR-303 实现(例如 Hibernate 验证器)位于 Classpath 上,就会自动启用 Bean 验证 1.1 支持的方法验证功能。这样就可以在 Bean 方法的参数和/或返回值上使用javax.validation
约束 Comments。具有此类 Comments 方法的目标类需要在类型级别使用@Validated
Comments 进行 Comments,以便在其方法中搜索内联约束 Comments。
例如,以下服务触发第一个参数的验证,确保其大小在 8 到 10 之间:
1 |
|
发送电子邮件
Spring 框架提供了一种使用JavaMailSender
接口发送电子邮件的简单抽象方法,而 Spring Boot 为它提供了自动配置以及启动程序模块。
Tip
有关如何使用
JavaMailSender
的详细说明,请参见reference documentation。
如果spring.mail.host
和相关库(由spring-boot-starter-mail
定义)可用,则如果不存在默认库JavaMailSender
,则将创建该库。可以通过spring.mail
名称空间中的配置项进一步自定义发送方。有关更多详细信息,请参见MailProperties。
特别是,某些默认超时值是无限的,您可能需要更改该值,以避免线程被无响应的邮件服务器阻塞,如以下示例所示:
1 | 5000 = |
也可以使用 JNDI 中的现有Session
配置JavaMailSender
:
1 | mail/Session = |
设置jndi-name
时,它优先于所有其他与会话相关的其他设置。
JTA 的分布式事务
Spring Boot 通过使用Atomikos或Bitronix嵌入式事务 Management 器,支持跨多个 XA 资源的分布式 JTA 事务。部署到合适的 Java EE 应用程序服务器时,还支持 JTA 事务。
当检测到 JTA 环境时,使用 Spring 的JtaTransactionManager
来 Management 事务。自动配置的 JMS,DataSource 和 JPA Bean 已升级为支持 XA 事务。您可以使用标准的 Spring 习惯用法(例如@Transactional
)来参与分布式事务。如果您在 JTA 环境中,并且仍要使用本地事务,则可以将spring.jta.enabled
属性设置为false
以禁用 JTA 自动配置。
使用Atomikos事物管理器
Atomikos是流行的开源事务 Management 器,可以嵌入到您的 Spring Boot 应用程序中。您可以使用spring-boot-starter-jta-atomikos
Starter 引入适当的 Atomikos 库。 Spring Boot 自动配置 Atomikos 并确保将适当的depends-on
设置应用于您的 Spring Bean,以正确启动和关闭 Sequences。
默认情况下,Atomikos 事务日志将写入应用程序主目录(应用程序 jar 文件所在的目录)中的transaction-logs
目录。您可以通过在application.properties
文件中设置spring.jta.log-dir
属性来自定义此目录的位置。以spring.jta.atomikos.properties
开头的属性也可以用于自定义 Atomikos UserTransactionServiceImp
。有关完整的详细信息,请参见AtomikosProperties Javadoc。
Note
为了确保多个事务 Management 器可以安全地协调同一资源 Management 器,必须为每个 Atomikos 实例配置一个唯一的 ID。默认情况下,此 ID 是运行 Atomikos 的计算机的 IP 地址。为了确保 Producing 的唯一性,应为应用程序的每个实例将
spring.jta.transaction-manager-id
属性配置为不同的值。
使用Bitronix事物管理器
Bitronix是流行的开源 JTA 事务 Management 器实现。您可以使用spring-boot-starter-jta-bitronix
Starter 程序将适当的 Bitronix 依赖项添加到您的项目中。与 Atomikos 一样,Spring Boot 自动配置 Bitronix 并对您的 bean 进行后处理,以确保启动和关闭 Sequences 正确。
默认情况下,Bitronix 事务日志文件(part1.btm
和part2.btm
)被写入应用程序主目录中的transaction-logs
目录。您可以通过设置spring.jta.log-dir
属性来自定义此目录的位置。以spring.jta.bitronix.properties
开头的属性也绑定到bitronix.tm.Configuration
bean,从而可以进行完全自定义。有关详情,请参见Bitronix documentation。
Note
为了确保多个事务 Management 器可以安全地协调同一资源 Management 器,必须为每个 Bitronix 实例配置唯一的 ID。默认情况下,此 ID 是运行 Bitronix 的计算机的 IP 地址。为了确保 Producing 的唯一性,应为应用程序的每个实例将
spring.jta.transaction-manager-id
属性配置为不同的值。
使用JavaEE托管事务管理器
如果将 Spring Boot 应用程序打包为war
或ear
文件并将其部署到 Java EE 应用程序服务器,则可以使用应用程序服务器的内置事务 Management 器。 Spring Boot 尝试通过查看常见的 JNDI 位置(java:comp/UserTransaction
,java:comp/TransactionManager
等)来自动配置事务 Management 器。如果使用应用程序服务器提供的事务服务,通常还需要确保所有资源都由服务器 Management 并通过 JNDI 公开。 Spring Boot 通过在 JNDI 路径(java:/JmsXA
或java:/XAConnectionFactory
)中查找ConnectionFactory
来尝试自动配置 JMS,您可以使用spring.datasource.jndi-name property来配置DataSource
。
混合XA和非XAJMS连接
使用 JTA 时,主要的 JMS ConnectionFactory
bean 支持 XA,并参与分布式事务。在某些情况下,您可能希望通过使用非 XA ConnectionFactory
处理某些 JMS 消息。例如,您的 JMS 处理逻辑可能需要比 XA 超时更长的时间。
如果要使用非 XA ConnectionFactory
,则可以注入nonXaJmsConnectionFactory
bean 而不是@Primary
jmsConnectionFactory
bean。为了保持一致性,还使用 Bean 别名xaJmsConnectionFactory
提供了jmsConnectionFactory
bean。
以下示例显示了如何注入ConnectionFactory
个实例:
1 | // Inject the primary (XA aware) ConnectionFactory |
支持备用嵌入式事务Management器
XAConnectionFactoryWrapper和XADataSourceWrapper接口可用于支持其他嵌入式事务 Management 器。这些接口负责包装XAConnectionFactory
和XADataSource
bean 并将它们作为常规ConnectionFactory
和DataSource
bean 公开,它们透明地注册了分布式事务。数据源和 JMS 自动配置使用 JTA 变体,前提是您拥有JtaTransactionManager
bean 和在ApplicationContext
中注册了适当的 XA 包装 bean。
BitronixXAConnectionFactoryWrapper和BitronixXADataSourceWrapper提供了有关如何编写 XA 包装程序的良好示例。
Hazelcast
如果Hazelcast位于 Classpath 上,并且找到了合适的配置,则 Spring Boot 会自动配置一个HazelcastInstance
,您可以将其插入到应用程序中。
如果定义一个com.hazelcast.config.Config
bean,Spring Boot 将使用它。如果您的配置定义了一个实例名称,Spring Boot 会尝试查找一个现有实例,而不是创建一个新实例。
您还可以指定hazelcast.xml
配置文件以通过配置使用,如以下示例所示:
1 | classpath:config/my-hazelcast.xml = |
否则,Spring Boot 会尝试从默认位置:工作目录中或 Classpath 根目录中的hazelcast.xml
查找 Hazelcast 配置。我们还检查hazelcast.config
系统属性是否设置。有关更多详细信息,请参见Hazelcast documentation。
如果hazelcast-client
存在于 Classpath 中,则 Spring Boot 首先尝试通过检查以下配置选项来创建 Client 端:
com.hazelcast.client.config.ClientConfig
bean 的存在。spring.hazelcast.config
属性定义的配置文件。hazelcast.client.config
系统属性的存在。- 工作目录中或 Classpath 根目录中的
hazelcast-client.xml
。
Note
Spring Boot 也具有对 Hazelcast 的显式缓存支持。如果启用了缓存,则
HazelcastInstance
将自动包装在CacheManager
实现中。
QuartzScheduler
Spring Boot 为使用Quartz scheduler提供了许多便利,其中包括spring-boot-starter-quartz
“ Starter”。如果 Quartz 可用,则会自动配置Scheduler
(通过SchedulerFactoryBean
抽象)。
以下类型的 Bean 被自动拾取并与Scheduler
关联:
JobDetail
:定义特定的作业。可以使用JobBuilder
API 构建JobDetail
实例。Calendar
.Trigger
:定义何时触发特定作业。
默认情况下,使用内存中的JobStore
。但是,如果您的应用程序中有DataSource
bean 可用,并且相应地配置了spring.quartz.job-store-type
属性,则可以配置基于 JDBC 的存储,如以下示例所示:
1 | jdbc = |
使用 JDBC 存储时,可以在启动时初始化模式,如以下示例所示:
1 | always = |
Warning
默认情况下,使用 Quartz 库随附的标准脚本检测并初始化数据库。这些脚本删除现有表,并在每次重新启动时删除所有触发器。也可以通过设置
spring.quartz.jdbc.schema
属性来提供自定义脚本。
要让 Quartz 使用除应用程序主DataSource
之外的DataSource
,请声明DataSource
bean,并用@QuartzDataSource
Comments 其@Bean
方法。这样做可确保SchedulerFactoryBean
使用 Quartz 专用的DataSource
并用于模式初始化。
默认情况下,通过配置创建的作业将不会覆盖从持久性作业存储中读取的已注册作业。要启用覆盖现有作业定义的功能,请设置spring.quartz.overwrite-existing-jobs
属性。
可以使用spring.quartz
属性和SchedulerFactoryBeanCustomizer
bean 自定义 Quartz Scheduler 配置,从而可以通过编程方式自定义SchedulerFactoryBean
。可以使用spring.quartz.properties.*
定制高级 Quartz 配置属性。
Note
特别是,
Executor
bean 没有与调度程序相关联,因为 Quartz 提供了一种通过spring.quartz.properties
配置调度程序的方法。如果您需要自定义任务 Actuator,请考虑实现SchedulerFactoryBeanCustomizer
。
作业可以定义设置器以注入数据 Map 属性。常规 bean 也可以类似的方式注入,如以下示例所示:
1 | public class SampleJob extends QuartzJobBean { |
任务执行和计划
在上下文中没有TaskExecutor
bean 的情况下,Spring Boot 会使用合理的默认值自动配置ThreadPoolTaskExecutor
,这些默认值可以自动与异步任务执行(@EnableAsync
)和 Spring MVC 异步请求处理相关联。
线程池使用 8 个核心线程,这些线程可以根据负载增长和收缩。可以使用spring.task.execution
名称空间对这些默认设置进行微调,如以下示例所示:
1 | 16 = |
这会将线程池更改为使用有界队列,以便当队列已满(100 个任务)时,线程池最多增加到 16 个线程。当线程空闲 10 秒(而不是默认情况下的 60 秒)时,回收线程会使池的收缩更加激进。
如果需要将ThreadPoolTaskScheduler
与计划的任务执行(@EnableScheduling
)关联,也可以对其进行自动配置。默认情况下,线程池使用一个线程,可以使用spring.task.scheduling
名称空间对这些设置进行微调。
如果需要创建自定义执行程序或调度程序,则TaskExecutorBuilder
bean 和TaskSchedulerBuilder
bean 在上下文中都可用。
Spring整合
Spring Boot 为使用Spring Integration提供了许多便利,其中包括spring-boot-starter-integration
“ Starter”。 Spring Integration 在消息传递以及其他传输(例如 HTTP,TCP 等)上提供了抽象。如果您的 Classpath 上有 Spring Integration,则可以通过@EnableIntegration
Comments 对其进行初始化。
Spring Boot 还配置了一些功能,这些功能由其他 Spring Integration 模块的存在触发。如果spring-integration-jmx
也在 Classpath 上,则消息处理统计信息将通过 JMX 发布。如果spring-integration-jdbc
可用,则可以在启动时创建默认数据库架构,如以下行所示:
1 | always = |
有关更多详细信息,请参见IntegrationAutoConfiguration和IntegrationProperties类。
默认情况下,如果存在 Micrometer meterRegistry
bean,那么 Spring Integration Metrics 将由 Micrometer Management。如果您希望使用旧版 Spring Integration Metrics,请将DefaultMetricsFactory
bean 添加到应用程序上下文中。
SpringSession
Spring Boot 为广泛的数据存储提供Spring Session自动配置。构建 Servlet Web 应用程序时,可以自动配置以下存储:
- JDBC
- Redis
- Hazelcast
- MongoDB
构建反应式 Web 应用程序时,可以自动配置以下存储:
- Redis
- MongoDB
如果 Classpath 上只有一个 Spring Session 模块,Spring Boot 会自动使用该存储实现。如果您有多个实现,则必须选择要用于存储会话的StoreType。例如,要将 JDBC 用作后端存储,可以按以下方式配置应用程序:
1 | jdbc = |
Tip
您可以通过将
store-type
设置为none
来禁用 Spring Session。
每个 Store 都有特定的其他设置。例如,可以为 JDBC 存储定制表的名称,如以下示例所示:
1 | SESSIONS = |
要设置会话超时,您可以使用spring.session.timeout
属性。如果未设置该属性,则自动配置将回退到server.servlet.session.timeout
的值。
通过JMX进行监视和管理
Java Management 扩展(JMX)提供了监视和 Management 应用程序的标准机制。默认情况下,Spring Boot 创建一个 ID 为mbeanServer
的MBeanServer
bean,并公开任何带有 Spring JMX Comments(@ManagedResource
,@ManagedAttribute
或@ManagedOperation
)的 bean。
有关更多详细信息,请参见JmxAutoConfiguration类。
Testing
Spring Boot 提供了许多Util和注解,可以在测试应用程序时提供帮助。测试支持由两个模块提供:spring-boot-test
包含核心项目,而spring-boot-test-autoconfigure
支持自动配置测试。
大多数开发人员使用spring-boot-starter-test
“Starter 程序”,该程序同时导入 Spring Boot 测试模块以及 JUnit,AssertJ,Hamcrest 和许多其他有用的库。
启动程序还带来了老式引擎,因此您可以运行JUnit 4和JUnit 5测试。 如果已将测试迁移到JUnit 5,则应排除对JUnit 4的支持,如以下示例所示:
1
2
3
4
5
6
7
8
9
10
11 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
测试范围依赖性
spring-boot-starter-test
“Starter”(位于test
scope
中)包含以下提供的库:
- JUnit:用于对 Java 应用程序进行单元测试的实际标准。
- Spring Test和 Spring Boot 测试:对 Spring Boot 应用程序的 Util 和集成测试支持。
- AssertJ:流畅的 assert 库。
- Hamcrest:匹配器对象库(也称为约束或谓词)。
- Mockito:Java 模拟框架。
- JSONassert:JSON 的 assert 库。
- JsonPath:JSON 的 XPath。
通常,我们发现这些通用库在编写测试时很有用。如果这些库不满足您的需求,则可以添加自己的其他测试依赖项。
测试Spring应用程序
依赖注入的主要优点之一是,它应该使您的代码更易于进行单元测试。您可以使用new
运算符实例化对象,而无需使用 Spring。您也可以使用 mock objects 代替真实的依赖。
通常,您需要超越单元测试并开始集成测试(使用 Spring ApplicationContext
)。能够进行集成测试而无需部署应用程序或连接到其他基础结构,这很有用。
Spring 框架包括用于此类集成测试的专用测试模块。您可以直接向org.springframework:spring-test
声明依赖项,也可以使用spring-boot-starter-test
“启动器”将其引入。
如果以前没有使用过spring-test
模块,则应先阅读 Spring Framework 参考文档的relevant section。
测试SpringBoot应用程序
Spring Boot 应用程序是 Spring ApplicationContext
,因此除了用普通的 Spring 上下文进行测试之外,无需执行任何其他特殊操作即可对其进行测试。
Note
仅当您使用
SpringApplication
创建它时,Spring Boot 的外部属性,日志记录和其他功能才默认安装在上下文中。
Spring Boot 提供了@SpringBootTest
注解,可以在需要 Spring Boot 功能时用作标准spring-test
@ContextConfiguration
注解的替代方法。Comments 由通过 SpringApplication 创建在测试中使用的 ApplicationContext起作用。除了@SpringBootTest
之外,还为应用程序测试更具体的切片提供了许多其他 Comments。
Tip
如果您使用的是 JUnit 4,请不要忘记也将
@RunWith(SpringRunner.class)
添加到测试中,否则注解将被忽略。如果您使用的是 JUnit 5,则无需添加等效的@ExtendWith(SpringExtension)
作为@SpringBootTest
,并且其他@…Test
注解已经对其进行了注解。
默认情况下,@SpringBootTest
不会启动服务器。您可以使用@SpringBootTest
的webEnvironment
属性来进一步优化测试的运行方式:
MOCK
(默认):加载 WebApplicationContext
并提供模拟 Web 环境。使用此 Comments 时,不会启动嵌入式服务器。如果您的 Classpath 中没有 Web 环境,则此模式将透明地退回到创建常规的非 WebApplicationContext
。它可以与@AutoConfigureMockMvc 或@AutoConfigureWebTestClient结合使用,以对 Web 应用程序进行基于模拟的测试。RANDOM_PORT
:加载WebServerApplicationContext
并提供真实的 Web 环境。嵌入式服务器将启动并在随机端口上侦听。DEFINED_PORT
:加载WebServerApplicationContext
并提供真实的 Web 环境。嵌入式服务器将启动,并在已定义的端口(来自application.properties
)或默认端口8080
上进行侦听。NONE
:使用SpringApplication
加载ApplicationContext
,但不提供任何网络环境(模拟或其他方式)。
Note
如果您的测试是
@Transactional
,则默认情况下它将在每个测试方法的末尾回滚事务。但是,由于将这种安排与RANDOM_PORT
或DEFINED_PORT
一起使用隐式提供了 true 的 servlet 环境,因此 HTTP Client 端和服务器在单独的线程中运行,因此在单独的事务中运行。在这种情况下,服务器上启动的任何事务都不会回滚。Note
如果您的应用程序对 Management 服务器使用其他端口,则
@SpringBootTest
和webEnvironment = WebEnvironment.RANDOM_PORT
还将在单独的随机端口上启动 Management 服务器。
检测Web应用程序类型
如果 Spring MVC 可用,则配置基于常规 MVC 的应用程序上下文。如果您只有 Spring WebFlux,我们将检测到该情况并配置基于 WebFlux 的应用程序上下文。
如果两者都存在,则 Spring MVC 优先。如果要在这种情况下测试反应式 Web 应用程序,则必须设置spring.main.web-application-type
属性:
1 |
|
检测测试配置
如果您熟悉 Spring Test Framework,则可能会习惯使用@ContextConfiguration(classes=…)
来指定要加载哪个 Spring @Configuration
。另外,您可能经常在测试中使用嵌套的@Configuration
类。
在测试 Spring Boot 应用程序时,通常不需要这样做。只要您没有明确定义 Spring Boot 的@*Test
注解,它就会自动搜索您的主要配置。
搜索算法从包含测试的程序包开始工作,直到找到带有@SpringBootApplication
或@SpringBootConfiguration
Comments 的类。只要您以一种明智的方式结构化代码,通常就可以找到您的主要配置。
Note
如果您使用测试注解以测试应用程序的更具体部分,则应避免在Main 方法的应用程序类别上添加特定于特定区域的配置设置。
@SpringBootApplication
的基础组件扫描配置定义了用于确保切片按预期工作的排除筛选器。如果在@SpringBootApplication
注解的类上使用显式的@ComponentScan
指令,请注意这些过滤器将被禁用。如果使用切片,则应重新定义它们。
如果要自定义主要配置,则可以使用嵌套的@TestConfiguration
类。与将使用嵌套的@Configuration
类代替应用程序的主要配置不同的是,除了使用应用程序的主要配置之外,还使用嵌套的@TestConfiguration
类。
Note
Spring 的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论如何发现),加载上下文的潜在耗时过程就只会发生一次。
排除测试配置
如果您的应用程序使用组件扫描(例如,如果使用@SpringBootApplication
或@ComponentScan
),则可能会偶然发现到处都是为特定测试创建的顶级配置类。
正如我们早看过,@TestConfiguration
可以在测试的内部类上使用以自定义主要配置。当放在顶级类上时,@TestConfiguration
指示src/test/java
中的类不应通过扫描来拾取。然后,可以在需要的位置显式导入该类,如以下示例所示:
1 |
|
Note
如果您直接使用
@ComponentScan
(即不是通过@SpringBootApplication
),则需要向其注册TypeExcludeFilter
。有关详情,请参见the Javadoc。
在模拟环境中进行测试
默认情况下,@SpringBootTest
不会启动服务器。如果您有要在此模拟环境下进行测试的 Web 终结点,则可以另外配置MockMvc,如以下示例所示:
1 | import org.junit.Test; |
Tip
如果您只想关注 Web 层而不想开始完整的
ApplicationContext
,请考虑使用@WebMvcTest 代替。
或者,您可以配置WebTestClient,如以下示例所示:
1 | import org.junit.Test; |
使用正在运行的服务器进行测试
如果需要启动完全运行的服务器,建议您使用随机端口。如果您使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
,则每次运行测试时都会随机选择一个可用端口。
@LocalServerPort
注解可用于注入实际使用的端口进入您的测试。为了方便起见,需要对启动的服务器进行 REST 调用的测试可以另外@Autowire
a WebTestClient,该解析可以解析到正在运行的服务器的相对链接,并带有用于验证响应的专用 API,如以下示例所示:
1 | import org.junit.Test; |
此设置在 Classpath 上需要spring-webflux
。如果您不能或不会添加 webflux,Spring Boot 还将提供TestRestTemplate
功能:
1 | import org.junit.Test; |
使用JMX
由于测试上下文框架缓存上下文,因此默认情况下禁用 JMX 以防止相同组件在同一域上注册。如果此类测试需要访问MBeanServer
,也请考虑将其标记为脏:
1 |
|
模拟bean和Spybean
运行测试时,有时有必要在应用程序上下文中模拟某些组件。例如,您可能在开发期间无法使用某些远程服务的外观。当您要模拟在实际环境中可能难以触发的故障时,模拟功能也很有用。
Spring Boot 包含@MockBean
注解,可用于为ApplicationContext
中的 bean 定义 Mockito 模拟。您可以使用 Comments 添加新的 bean 或替换单个现有的 bean 定义。注解可以直接用于测试类,测试中的字段或@Configuration
类和字段。在字段上使用时,还将注入创建的模拟的实例。每种测试方法后,模拟 bean 都会自动重置。
Note
如果您的测试使用 Spring Boot 的测试 Comments 之一(例如
@SpringBootTest
),那么此功能将自动启用。要以其他方式使用此功能,必须显式添加侦听器,如以下示例所示:
1 |
下面的示例使用模拟实现替换现有的RemoteService
bean:
1 | import org.junit.*; |
另外,您可以使用@SpyBean
将任何现有的 bean 与 Mockito spy
包装在一起。有关详细信息,请参见Javadoc。
Note
Spring 的测试框架在测试之间缓存应用程序上下文,并为共享相同配置的测试重用上下文,而
@MockBean
或@SpyBean
的使用会影响缓存键,这很可能会增加上下文的数量。Tip
如果您使用
@SpyBean
监视具有通过名称引用参数的@Cacheable
方法的 bean,则您的应用程序必须使用-parameters
进行编译。这样可以确保一旦侦察到 bean,就可以将参数名称用于缓存基础结构。
自动配置的测试
Spring Boot 的自动配置系统适用于应用程序,但有时对于测试来说可能有点过多。它通常仅有助于加载测试应用程序“切片”所需的配置部分。例如,您可能想要测试 Spring MVC 控制器是否正确 Map 了 URL,并且您不想在这些测试中涉及数据库调用,或者您想要测试 JPA 实体,并且对那些 JPA 实体不感兴趣。测试运行。
spring-boot-test-autoconfigure
模块包含许多 Comments,可用于自动配置此类“切片”。它们中的每一个都以类似的方式工作,提供了一个@…Test
注解,该注解加载了ApplicationContext
和一个或多个@AutoConfigure…
注解,这些注解可用于自定义自动配置设置。
Note
每个切片将组件扫描限制为适当的组件,并加载一组非常受限制的自动配置类。如果您需要排除其中之一,则大多数
@…Test
Comments 都提供excludeAutoConfiguration
属性。或者,您可以使用@ImportAutoConfiguration#exclude
。Note
不支持在一个测试中使用多个
@…Test
Comments 来包含多个“切片”。如果您需要多个“切片”,请选择@…Test
Comments 之一,并手动添加其他“切片”的@AutoConfigure…
Comments。Tip
也可以将
@AutoConfigure…
Comments 与标准@SpringBootTest
Comments 一起使用。如果您对“切片”应用程序不感兴趣,但需要一些自动配置的测试 bean,则可以使用此组合。
自动配置的JSON测试
要测试对象 JSON 序列化和反序列化是否按预期工作,可以使用@JsonTest
注解。 @JsonTest
自动配置可用的受支持的 JSON Map 器,该 Map 器可以是以下库之一:
- Jackson
ObjectMapper
,任何@JsonComponent
beans 和任何 JacksonModule
s Gson
Jsonb
Tip
@JsonTest
启用的自动配置的列表可以为见附录。
如果需要配置自动配置的元素,则可以使用@AutoConfigureJsonTesters
Comments。
Spring Boot 包括基于 AssertJ 的助手,这些助手与 JSONAssert 和 JsonPath 库一起使用,以检查 JSON 是否按预期方式显示。 JacksonTester
,GsonTester
,JsonbTester
和BasicJsonTester
类可以分别用于 Jackson,Gson,Jsonb 和 Strings。使用@JsonTest
时,测试类上的任何帮助程序字段都可以为@Autowired
。以下示例显示了 Jackson 的测试类:
1 | import org.junit.*; |
Note
JSON 帮助程序类也可以直接在标准单元测试中使用。这样做,如果不使用
@JsonTest
,请在您的@Before
方法中调用帮助程序的initFields
方法。
自动配置的SpringMVC测试
要测试 Spring MVC 控制器是否按预期工作,请使用@WebMvcTest
注解。 @WebMvcTest
自动配置 Spring MVC 基础结构,并将扫描的 Bean 限制为@Controller
,@ControllerAdvice
,@JsonComponent
,Converter
,GenericConverter
,Filter
,WebMvcConfigurer
和HandlerMethodArgumentResolver
。使用此 Comments 时,不扫描常规的@Component
bean。
Tip
@WebMvcTest
启用的自动配置设置的列表可以为见附录。Tip
如果您需要注册其他组件,例如 Jackson
Module
,则可以在测试中使用@Import
导入其他配置类。
通常,@WebMvcTest
限于单个控制器,并与@MockBean
结合使用以为所需的协作者提供模拟实现。
@WebMvcTest
也会自动配置MockMvc
。 Mock MVC 提供了一种强大的方法来快速测试 MVC 控制器,而无需启动完整的 HTTP 服务器。
Tip
您还可以通过用
@AutoConfigureMockMvc
Comments 非@WebMvcTest
(例如@SpringBootTest
)来自动配置MockMvc
。以下示例使用MockMvc
:
1 | import org.junit.*; |
Tip
如果您需要配置自动配置的元素(例如,当应用 servlet 过滤器时),则可以使用
@AutoConfigureMockMvc
注解中的属性。
如果使用 HtmlUnit 或 Selenium,则自动配置还会提供 HTMLUnit WebClient
bean 和/或WebDriver
bean。以下示例使用 HtmlUnit:
1 | import com.gargoylesoftware.htmlunit.*; |
Note
默认情况下,Spring Boot 将
WebDriver
bean 放在特殊的“作用域”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不希望出现这种情况,可以将@Scope("singleton")
添加到WebDriver
@Bean
定义中。Warning
Spring Boot 创建的
webDriver
作用域将替换任何用户定义的同名作用域。如果定义自己的webDriver
范围,则使用@WebMvcTest
时可能会停止工作。
如果您在 Classpath 上具有 Spring Security,则@WebMvcTest
还将扫描WebSecurityConfigurer
bean。您可以使用 Spring Security 的测试支持,而不是完全禁用此类测试的安全性。有关如何使用 Spring Security 的MockMvc
支持的更多详细信息,可以在此 第 80 章,使用 Spring Security 进行测试 操作方法部分中找到。
Tip
有时编写 Spring MVC 测试是不够的。 Spring Boot 可以帮助您运行使用实际服务器进行完整的端到端测试。
自动配置的SpringWebFlux测试
要测试Spring WebFlux控制器是否按预期工作,可以使用@WebFluxTest
注解。 @WebFluxTest
自动配置 Spring WebFlux 基础结构,并将扫描的 bean 限制为@Controller
,@ControllerAdvice
,@JsonComponent
,Converter
,GenericConverter
和WebFluxConfigurer
。使用@WebFluxTest
注解时,不扫描常规@Component
bean。
Tip
@WebFluxTest
启用的自动配置的列表可以为见附录。Tip
如果您需要注册其他组件,例如 Jackson
Module
,则可以在测试中使用@Import
导入其他配置类。
@WebFluxTest
通常仅限于单个控制器,并与@MockBean
注解结合使用以为所需的协作者提供模拟实现。
@WebFluxTest
还自动配置WebTestClient,它提供了一种强大的方法来快速测试 WebFlux 控制器而无需启动完整的 HTTP 服务器。
Tip
您还可以通过用
@AutoConfigureWebTestClient
Comments 非@WebFluxTest
(例如@SpringBootTest
)来自动配置WebTestClient
。以下示例显示了同时使用@WebFluxTest
和WebTestClient
的类:
1 | import org.junit.Test; |
Tip
WebFlux 应用程序仅支持此设置,因为在模拟的 Web 应用程序中使用
WebTestClient
目前仅适用于 WebFlux。Note
@WebFluxTest
无法检测通过功能 Web 框架注册的路由。要在上下文中测试RouterFunction
bean,请考虑自己通过@Import
或使用@SpringBootTest
导入RouterFunction
。Tip
有时编写 Spring WebFlux 测试是不够的。 Spring Boot 可以帮助您运行使用实际服务器进行完整的端到端测试。
自动配置的数据JPA测试
您可以使用@DataJpaTest
注解来测试 JPA 应用程序。默认情况下,它配置一个内存嵌入式数据库,扫描@Entity
类,并配置 Spring Data JPA 存储库。常规@Component
bean 未加载到ApplicationContext
中。
Tip
@DataJpaTest
启用的自动配置设置的列表可以为见附录。
默认情况下,数据 JPA 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参见《 Spring Framework 参考文档》中的relevant section。如果这不是您想要的,则可以按以下方式禁用测试或整个类的事务 Management:
1 | import org.junit.Test; |
数据 JPA 测试还可以注入TestEntityManager bean,它提供了专门为测试设计的标准 JPA EntityManager
的替代方案。如果要在@DataJpaTest
实例之外使用TestEntityManager
,则也可以使用@AutoConfigureTestEntityManager
Comments。如果需要,也可以提供JdbcTemplate
。以下示例显示了正在使用的@DataJpaTest
注解:
1 | import org.junit.*; |
内存嵌入式数据库通常运行良好,不需要任何安装,因此通常可以很好地进行测试。但是,如果您希望对真实数据库运行测试,则可以使用@AutoConfigureTestDatabase
注解,如以下示例所示:
1 |
|
自动配置的JDBC测试
@JdbcTest
与@DataJpaTest
类似,但适用于只需要DataSource
并且不使用 Spring Data JDBC 的测试。默认情况下,它配置内存嵌入式数据库和JdbcTemplate
。常规@Component
bean 没有加载到ApplicationContext
中。
Tip
@JdbcTest
启用的自动配置的列表可以为[见附录](https://route-nice.github.io/2020/08/31/SpringBoot官方文档翻译-附录/#测试自动配置注解。
缺省情况下,JDBC 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参见《 Spring Framework 参考文档》中的relevant section。如果这不是您想要的,则可以为测试或整个类禁用事务 Management,如下所示:
1 | import org.junit.Test; |
如果您希望测试针对真实数据库运行,则可以使用 Comments,方式与DataJpaTest
相同。 (请参阅“ 第 45.3.12 节,“自动配置的数据 JPA 测试””。)
自动配置的数据JDBC测试
@DataJdbcTest
与@JdbcTest
类似,但适用于使用 Spring Data JDBC 存储库的测试。默认情况下,它配置一个内存嵌入式数据库JdbcTemplate
和 Spring Data JDBC 存储库。常规@Component
bean 没有加载到ApplicationContext
中。
Tip
@DataJdbcTest
启用的自动配置的列表可以为见附录。
默认情况下,Data JDBC 测试是事务性的,并在每个测试结束时回滚。有关更多详细信息,请参见《 Spring Framework 参考文档》中的relevant section。如果这不是您想要的,则可以禁用测试或整个测试类的事务 Management,即在 JDBC 示例中显示。
如果您希望测试针对真实数据库运行,则可以使用 Comments,方式与DataJpaTest
相同。 (请参阅“ 第 45.3.12 节,“自动配置的数据 JPA 测试””。)
自动配置的jOOQ测试
您可以以与@JdbcTest
类似的方式使用@JooqTest
,但可以用于与 jOOQ 相关的测试。由于 jOOQ 严重依赖与数据库模式相对应的基于 Java 的模式,因此使用现有的DataSource
。如果要将其替换为内存数据库,则可以使用@AutoConfigureTestDatabase
覆盖这些设置。 (有关将 jOOQ 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ 第 30.6 节“使用 jOOQ””。)常规@Component
bean 没有加载到ApplicationContext
中。
Tip
@JooqTest
启用的自动配置的列表可以为见附录。
@JooqTest
配置DSLContext
。常规@Component
bean 未加载到ApplicationContext
中。以下示例显示了正在使用的@JooqTest
Comments:
1 | import org.jooq.DSLContext; |
JOOQ 测试是事务性的,默认情况下会在每个测试结束时回滚。如果这不是您想要的,则可以禁用测试或整个测试类的事务 Management,例如在 JDBC 示例中显示。
自动配置的DataMongoDB测试
您可以使用@DataMongoTest
测试 MongoDB 应用程序。默认情况下,它配置内存嵌入式 MongoDB(如果可用),配置MongoTemplate
,扫描@Document
类,并配置 Spring Data MongoDB 存储库。常规@Component
bean 没有加载到ApplicationContext
中。 (有关将 MongoDB 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ 第 31.2 节“ MongoDB””。)
Tip
@DataMongoTest
启用的自动配置设置的列表可以为见附录。
此类显示正在使用的@DataMongoTest
注解:
1 | import org.junit.runner.RunWith; |
内存嵌入式 MongoDB 通常运行良好,不需要任何开发人员安装,因此通常可以很好地用于测试。但是,如果您希望对真实的 MongoDB 服务器运行测试,则应排除嵌入式 MongoDB 自动配置,如以下示例所示:
1 | import org.junit.runner.RunWith; |
自动配置的数据Neo4j测试
您可以使用@DataNeo4jTest
测试 Neo4j 应用程序。默认情况下,它使用内存中嵌入式 Neo4j(如果有嵌入式驱动程序可用),扫描@NodeEntity
类,并配置 Spring Data Neo4j 存储库。常规@Component
bean 没有加载到ApplicationContext
中。 (有关将 Neo4J 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ 第 31.3 节“ Neo4j””。)
Tip
@DataNeo4jTest
启用的自动配置设置的列表可以为见附录。
以下示例显示了在 Spring Boot 中使用 Neo4J 测试的典型设置:
1 | import org.junit.runner.RunWith; |
默认情况下,Data Neo4j 测试是事务性的,并在每个测试结束时回滚。有关更多详细信息,请参见《 Spring Framework 参考文档》中的relevant section。如果这不是您想要的,则可以为测试或整个类禁用事务 Management,如下所示:
1 | import org.junit.Test; |
自动配置的数据Redis测试
您可以使用@DataRedisTest
测试 Redis 应用程序。默认情况下,它将扫描@RedisHash
类并配置 Spring Data Redis 存储库。常规@Component
bean 没有加载到ApplicationContext
中。 (有关在 Spring Boot 中使用 Redis 的更多信息,请参阅本章前面的“ 第 31.1 节“ Redis””。)
Tip
@DataRedisTest
启用的自动配置设置的列表可以为见附录。
以下示例显示了正在使用的@DataRedisTest
注解:
1 | import org.junit.runner.RunWith; |
自动配置的数据LDAP测试
您可以使用@DataLdapTest
测试 LDAP 应用程序。默认情况下,它配置内存嵌入式 LDAP(如果可用),配置LdapTemplate
,扫描@Entry
类,并配置 Spring Data LDAP 存储库。常规@Component
bean 没有加载到ApplicationContext
中。 (有关将 LDAP 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ 第 31.9 节“ LDAP””。)
Tip
@DataLdapTest
启用的自动配置设置的列表可以为见附录。
以下示例显示了正在使用的@DataLdapTest
注解:
1 | import org.junit.runner.RunWith; |
内存嵌入式 LDAP 通常非常适合测试,因为它速度快并且不需要安装任何开发人员。但是,如果您希望针对真实的 LDAP 服务器运行测试,则应排除嵌入式 LDAP 自动配置,如以下示例所示:
1 | import org.junit.runner.RunWith; |
自动配置的RESTClient端
您可以使用@RestClientTest
注解来测试 REST Client 端。默认情况下,它会自动配置 Jackson,GSON 和 Jsonb 支持,配置RestTemplateBuilder
,并添加对MockRestServiceServer
的支持。常规@Component
bean 没有加载到ApplicationContext
中。
Tip
@RestClientTest
启用的自动配置设置的列表可以为见附录。
应该使用@RestClientTest
的value
或components
属性指定要测试的特定 bean,如以下示例所示:
1 |
|
自动配置的SpringREST文档测试
您可以在 Mock MVC,REST 保证或 WebTestClient 的测试中使用@AutoConfigureRestDocs
注解来使用Spring REST 文件。它消除了 Spring REST Docs 中对 JUnit 规则的需求。
@AutoConfigureRestDocs
可用于覆盖默认输出目录(如果使用 Maven,则使用target/generated-snippets
;如果使用 Gradle,则使用build/generated-snippets
)。它也可以用于配置出现在任何记录的 URI 中的主机,方案和端口。
使用MockMVC自动配置的SpringRESTDocs测试
@AutoConfigureRestDocs
自定义MockMvc
bean 以使用 Spring REST Docs。您可以使用@Autowired
注入它,并像通常使用 Mock MVC 和 Spring REST Docs 一样在测试中使用它,如以下示例所示:
1 | import org.junit.Test; |
如果您需要对 Spring REST Docs 配置进行更多控制,而不是@AutoConfigureRestDocs
属性所提供的控制,则可以使用RestDocsMockMvcConfigurationCustomizer
bean,如以下示例所示:
1 |
|
如果要使用 Spring REST Docs 对参数化输出目录的支持,则可以创建RestDocumentationResultHandler
bean。自动配置使用此结果处理程序调用alwaysDo
,从而使每个MockMvc
调用自动生成默认片段。以下示例显示正在定义的RestDocumentationResultHandler
:
1 |
|
具有 REST 保证的自动配置的 Spring REST 文档测试
@AutoConfigureRestDocs
使预配置为使用 Spring REST 文档的RequestSpecification
bean 可用于您的测试。您可以使用@Autowired
注入它,并像在使用 REST Assured 和 Spring REST Docs 时一样,在测试中使用它,如以下示例所示:
1 | import io.restassured.specification.RequestSpecification; |
如果您需要对 Spring REST Docs 配置进行更多控制而不是@AutoConfigureRestDocs
属性提供的控制,则可以使用RestDocsRestAssuredConfigurationCustomizer
bean,如以下示例所示:
1 |
|
其他自动配置和切片
每个切片提供一个或多个@AutoConfigure…
注解,即定义应包含在切片中的自动配置。可以通过创建自定义@AutoConfigure…
Comments 或仅通过向测试中添加@ImportAutoConfiguration
来添加其他自动配置,如以下示例所示:
1 |
|
Note
确保不要使用常规的
@Import
注解 来导入自动配置,因为它们是由 Spring Boot 以特定方式处理的。
用户配置和切片
如果您以明智的方式结构化代码,则您的@SpringBootApplication
类为默认使用作为测试的配置。
因此,重要的是不要用特定于其功能特定区域的配置设置来乱扔应用程序的主类。
假设您正在使用 Spring Batch,并且依赖于它的自动配置。您可以按以下方式定义@SpringBootApplication
:
1 |
|
因为此类是测试的源配置,所以任何切片测试实际上都尝试启动 Spring Batch,这绝对不是您想要执行的操作。建议的方法是将特定于区域的配置移到与您的应用程序相同级别的单独的@Configuration
类,如以下示例所示:
1 |
|
Note
根据您应用程序的复杂性,您可以为自己的自定义设置一个
@Configuration
类,或者每个域区域一个类。后一种方法可让您在必要的测试中使用@Import
注解启用它。
混乱的另一个来源是 Classpath 扫描。假设在以合理的方式组织代码的同时,您需要扫描其他程序包。您的应用程序可能类似于以下代码:
1 |
|
这样做有效地覆盖了默认的组件扫描指令,并且具有扫描这两个软件包的副作用,而与您选择的切片无关。例如,@DataJpaTest
似乎突然扫描了应用程序的组件和用户配置。同样,将自定义指令移至单独的类是解决此问题的好方法。
Tip
如果这不是您的选择,则可以在测试层次结构中的某个位置创建
@SpringBootConfiguration
,以便代替它使用。另外,您可以为测试指定一个源,从而禁用查找默认源的行为。
使用Spock测试SpringBoot应用程序
如果希望使用 Spock 测试 Spring Boot 应用程序,则应在应用程序的构建中添加对 Spock 的spock-spring
模块的依赖。 spock-spring
将 Spring 的测试框架集成到 Spock 中。建议您使用 Spock 1.2 或更高版本,以受益于 Spock 的 Spring Framework 和 Spring Boot 集成的许多改进。有关更多详细信息,请参见Spock 的 Spring 模块的文档。
测试Util
一些测试 Util 类通常在测试您的应用程序时有用,它们被打包为spring-boot
的一部分。
ConfigFileApplicationContextInitializer
ConfigFileApplicationContextInitializer
是ApplicationContextInitializer
,您可以将其应用于测试以加载 Spring Boot application.properties
文件。如不需要以下示例所示,可以在不需要@SpringBootTest
提供的全部功能时使用它:
1 |
Note
单独使用
ConfigFileApplicationContextInitializer
不支持@Value("${…}")
注入。它唯一的工作就是确保将application.properties
文件加载到 Spring 的Environment
中。为了获得@Value
支持,您需要另外配置PropertySourcesPlaceholderConfigurer
或使用@SpringBootTest
,后者会为您自动配置一个。
TestPropertyValues
TestPropertyValues
可让您快速将属性添加到ConfigurableEnvironment
或ConfigurableApplicationContext
。您可以使用key=value
字符串来调用它,如下所示:
1 | TestPropertyValues.of("org=Spring", "name=Boot").applyTo(env); |
OutputCapture
OutputCapture
是一个 JUnit Rule
,可用于捕获System.out
和System.err
输出。您可以将捕获声明为@Rule
,然后将toString()
用于 assert,如下所示:
1 | import org.junit.Rule; |
TestRestTemplate
Tip
Spring Framework 5.0 提供了一个新的
WebTestClient
,它适用于WebFlux 集成测试和WebFlux 和 MVC 端到端测试。与TestRestTemplate
不同,它为声明提供了流畅的 API。
TestRestTemplate
是 Spring RestTemplate
的便捷替代方法,在集成测试中非常有用。您可以使用普通模板或发送基本 HTTP 身份验证(带有用户名和密码)的模板。在这两种情况下,模板都不会通过在服务器端错误上引发异常来以易于测试的方式运行。建议(但不是强制性的)使用 Apache HTTP Client(版本 4.3.2 或更高版本)。如果您在 Classpath 中具有该名称,则TestRestTemplate
会通过适当配置 Client 端进行响应。如果确实使用 Apache 的 HTTP Client 端,则会启用一些其他易于测试的功能:
- 不遵循重定向(因此您可以声明响应位置)。
- Cookies 被忽略(因此模板是 Stateless 的)。
TestRestTemplate
可以在集成测试中直接实例化,如以下示例所示:
1 | public class MyTest { |
另外,如果您将@SpringBootTest
Comments 与WebEnvironment.RANDOM_PORT
或WebEnvironment.DEFINED_PORT
一起使用,则可以注入已完全配置的TestRestTemplate
并开始使用它。如有必要,可以通过RestTemplateBuilder
bean 应用其他定制。未指定主机和端口的所有 URL 都会自动连接到嵌入式服务器,如以下示例所示:
1 |
|
WebSockets
Spring Boot 为嵌入式 Tomcat,Jetty 和 Undertow 提供了 WebSockets 自动配置。如果将 war 文件部署到独立容器,Spring Boot 会假定该容器负责其 WebSocket 支持的配置。
Spring Framework 为 MVC Web 应用程序提供了丰富的 WebSocket 支持,可以通过spring-boot-starter-websocket
模块轻松访问。
WebSocket 支持也可用于响应式 Web 应用程序,并且需要在spring-boot-starter-webflux
旁边包括 WebSocket API:
1 | <dependency> |
WebService
Spring Boot 提供了 Web 服务自动配置,因此您所要做的就是定义Endpoints
。
Spring Web Services 功能可以通过spring-boot-starter-webservices
模块轻松访问。
可以分别为您的 WSDL 和 XSD 自动创建SimpleWsdl11Definition
和SimpleXsdSchema
bean。为此,请配置其位置,如以下示例所示:
1 | classpath:/wsdl = |
使用WebServiceTemplate调用Web服务
如果需要从应用程序调用远程 Web 服务,则可以使用WebServiceTemplate类。由于WebServiceTemplate
实例在使用前通常需要自定义,因此 Spring Boot 不提供任何单个自动配置的WebServiceTemplate
bean。但是,它会自动配置WebServiceTemplateBuilder
,可以在需要时创建WebServiceTemplate
实例。
以下代码显示了一个典型示例:
1 |
|
默认情况下,WebServiceTemplateBuilder
使用 Classpath 上可用的 HTTP Client 端库检测合适的基于 HTTP 的WebServiceMessageSender
。您还可以如下自定义读取和连接超时:
1 |
|
创建自己的自动配置
如果您在开发共享库的公司中工作,或者在开源或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以 Binding 在外部 jar 中,并且仍由 Spring Boot 拾取。
自动配置可以与“启动器”相关联,该“启动器”提供自动配置代码以及您将使用的典型库。我们首先介绍构建自己的自动配置所需的知识,然后 continue 进行创建自定义启动器所需的典型步骤。
Tip
demo project可用来展示如何逐步创建 Starter 者。
了解自动配置的Bean
在后台,自动配置是通过标准的@Configuration
类实现的。其他@Conditional
Comments 用于约束何时应应用自动配置。通常,自动配置类使用@ConditionalOnClass
和@ConditionalOnMissingBean
Comments。这样可以确保仅当找到相关的类并且没有声明自己的@Configuration
时,自动配置才适用。
您可以浏览spring-boot-autoconfigure的源代码以查看 Spring 提供的@Configuration
类(请参见META-INF/spring.factories文件)。
查找自动配置的候选人
Spring Boot 检查发布的 jar 中是否存在META-INF/spring.factories
文件。该文件应在EnableAutoConfiguration
键下列出您的配置类,如以下示例所示:
1 | \ = |
如果需要按特定 Sequences 应用配置,则可以使用@AutoConfigureAfter或@AutoConfigureBefore注解。例如,如果您提供特定于 Web 的配置,则可能需要在WebMvcAutoConfiguration
之后应用您的类。
如果要 Order 某些彼此之间没有直接知识的自动配置,则也可以使用@AutoConfigureOrder
。该 Comments 与常规@Order
Comments 具有相同的语义,但为自动配置类提供了专用 Sequences。
Note
自动配置必须以 only 的方式加载。确保在特定的软件包空间中定义了它们,尤其是它们绝不是组件扫描的目标。
Condition注解
您几乎总是希望在自动配置类中包含一个或多个@Conditional
注解。 @ConditionalOnMissingBean
注解 是一个常见示例,用于使开发人员在对默认设置不满意的情况下覆盖自动配置。
Spring Boot 包含许多@Conditional
注解,您可以通过 Comments@Configuration
类或单个@Bean
方法在自己的代码中重用。这些 注解包括:
- 类条件
- Bean 条件
- 属性条件](#Property条件)
- 资源条件
- Web 应用程序条件
- SpEL 表达条件
Class条件
@ConditionalOnClass
和@ConditionalOnMissingClass
注解允许根据是否存在特定类来包含配置。由于 Comments 元数据是通过使用ASM进行解析的,因此即使该类实际上可能未出现在正在运行的应用程序 Classpath 上,您也可以使用value
属性来引用真实的类。如果您希望通过使用String
值来指定类名,则也可以使用name
属性。
Tip
如果您使用
@ConditionalOnClass
或@ConditionalOnMissingClass
作为元 Comments 的一部分来组成自己的组合 Comments,则必须使用name
,因为在这种情况下无法引用该类。
Bean条件
@ConditionalOnBean
和@ConditionalOnMissingBean
Comments 根据是否存在特定的 bean 来包含 bean。您可以使用value
属性按类型指定 bean,或使用name
按名称指定 bean。 search
属性使您可以限制搜索 Bean 时应考虑的ApplicationContext
层次结构。
当放置在@Bean
方法上时,目标类型默认为该方法的返回类型,如以下示例所示:
1 |
|
在前面的示例中,如果ApplicationContext
中没有包含MyService
类型的 bean,则将创建myService
bean。
Tip
您需要非常注意添加 bean 定义的 Sequences,因为这些条件是根据到目前为止已处理的内容来评估的。因此,我们建议在自动配置类上仅使用
@ConditionalOnBean
和@ConditionalOnMissingBean
Comments(因为保证在添加任何用户定义的 Bean 定义后即可加载这些 Comments)。Note
@ConditionalOnBean
和@ConditionalOnMissingBean
不会阻止@Configuration
类的创建。在类级别使用这些条件与使用 Comments 标记每个包含的@Bean
方法之间的唯一区别是,如果条件不匹配,则前者会阻止@Configuration
类注册为 bean。
Property条件
@ConditionalOnProperty
注解允许基于 Spring Environment 属性包含配置。使用prefix
和name
属性来指定应检查的属性。默认情况下,匹配存在且不等于false
的任何属性。您还可以使用havingValue
和matchIfMissing
属性创建更高级的检查。
Resource条件
@ConditionalOnResource
注解仅在存在特定资源时才包括配置。可以使用通常的 Spring 约定来指定资源,如以下示例所示:file:/home/user/test.dat
。
WebApplication条件
根据应用程序是否为“ Web 应用程序”,可以使用@ConditionalOnWebApplication
和@ConditionalOnNotWebApplication
注解包含配置。 Web 应用程序是使用 Spring WebApplicationContext
,定义session
范围或具有StandardServletEnvironment
的任何应用程序。
SpEL表达条件
@ConditionalOnExpression
注解允许基于SpEL expression的结果包括配置。
测试您的自动配置
自动配置可能受许多因素影响:用户配置(@Bean
定义和Environment
定制),条件评估(特定库的存在)和其他因素。具体而言,每个测试都应创建定义良好的ApplicationContext
,以表示这些自定义项的组合。 ApplicationContextRunner
提供了一种实现此目标的好方法。
ApplicationContextRunner
通常定义为测试类的一个字段,用于收集基本的通用配置。下面的示例确保始终调用UserServiceAutoConfiguration
:
1 | private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() |
Tip
如果必须定义多个自动配置,则无需按与运行应用程序时完全相同的 Sequences 调用它们的声明。
每个测试都可以使用运行器来表示特定的用例。例如,下面的示例调用一个用户配置(UserConfiguration
),并检查自动配置是否正确退出。调用run
提供了可与Assert4J
一起使用的回调上下文。
1 |
|
还可以轻松自定义Environment
,如以下示例所示:
1 |
|
Running 者也可以用来显示ConditionEvaluationReport
。该报告可以INFO
或DEBUG
级别打印。以下示例显示如何在自动配置测试中使用ConditionEvaluationReportLoggingListener
打印报告。
1 |
|
模拟网络环境
如果您需要测试仅在 Servlet 或 Reactive Web 应用程序上下文中运行的自动配置,请分别使用WebApplicationContextRunner
或ReactiveWebApplicationContextRunner
。
覆盖Classpath
还可以测试在运行时不存在特定的类和/或程序包时发生的情况。 Spring Boot 附带FilteredClassLoader
,Running 者可以轻松使用。在以下示例中,我们 assert 如果不存在UserService
,则会自动禁用自动配置:
1 |
|
创建自己的启动器
库的完整 Spring BootStarter 程序可能包含以下组件:
- 包含自动配置代码的
autoconfigure
模块。 starter
模块提供对autoconfigure
模块以及库的依赖关系,以及通常有用的任何其他依赖关系。简而言之,添加启动程序应提供开始使用该库所需的一切。
Tip
如果不需要将这两个问题分开,则可以将自动配置代码和依赖性 Management 结合在一起。
Naming
您应该确保为启动器提供适当的名称空间。即使您使用其他 Maven groupId
,也不要以spring-boot
开头模块名称。将来,我们可能会为您自动配置的内容提供官方支持。
根据经验,您应该在启动器后命名一个组合模块。例如,假设您要为“ acme”创建启动程序,并且将自动配置模块命名为acme-spring-boot-autoconfigure
,而启动程序则命名为acme-spring-boot-starter
。如果只有一个将两者结合的模块,请将其命名为acme-spring-boot-starter
。
另外,如果您的 Starter 者提供了配置密钥,请为其使用唯一的名称空间。特别是,不要在 Spring Boot 使用的名称空间中包含您的密钥(例如server
,management
,spring
等)。如果使用相同的名称空间,将来我们可能会以破坏模块的方式修改这些名称空间。
确保触发元数据生成,以便您的按键也可以使用 IDE 协助。您可能需要查看生成的元数据(META-INF/spring-configuration-metadata.json
),以确保正确记录了您的密钥。
自动配置模块
autoconfigure
模块包含开始使用该库所需的所有内容。它还可能包含配置键定义(例如@ConfigurationProperties
)和可用于进一步自定义组件初始化方式的任何回调接口。
Tip
您应该将对库的依赖关系标记为可选,以便可以更轻松地在项目中包含
autoconfigure
模块。如果这样做,则不提供该库,并且默认情况下,Spring Boot 会后退。
Spring Boot 使用 Comments 处理器来收集元数据文件(META-INF/spring-autoconfigure-metadata.properties
)中自动配置的条件。如果存在该文件,它将用于急切过滤不匹配的自动配置,这将缩短启动时间。建议在包含自动配置的模块中添加以下依赖项:
1 | <dependency> |
对于 Gradle 4.5 及更早版本,依赖关系应在compileOnly
配置中声明,如以下示例所示:
1 | dependencies { |
在 Gradle 4.6 及更高版本中,依赖性应在annotationProcessor
配置中声明,如以下示例所示:
1 | dependencies { |
Starter模块
起动器确实是一个空Jar子。其唯一目的是提供必要的依赖关系以使用库。您可以将其视为对 Starter 所需的看法。
不要对添加了启动器的项目做任何假设。如果您要自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很高,则提供一组适当的 default 依赖项可能会很困难,因为您应避免包括对于库的典型用法而言不必要的依赖项。换句话说,您不应包括可选的依赖项。
Note
无论哪种方式,您的启动程序都必须直接或间接引用核心 Spring Boot 启动程序(
spring-boot-starter
)(即,如果您的启动程序依赖于另一个启动程序,则无需添加它)。如果仅使用您的自定义启动器创建项目,则通过使用该核心启动器来兑现 Spring Boot 的核心功能。
Kotlin支持
Kotlin是针对 JVM(和其他平台)的静态类型的语言,它允许编写简洁明了的代码,同时为interoperability提供以 Java 编写的现有库。
Spring Boot 通过利用其他 Spring 项目(例如 Spring Framework,Spring Data 和 Reactor)中的支持来提供 Kotlin 支持。有关更多信息,请参见Spring Framework Kotlin 支持文档。
从 Spring Boot 和 Kotlin 开始的最简单方法是遵循本综合教程。您可以通过start.spring.io创建新的 Kotlin 项目。如果需要支持,可以随时加入Kotlin Slack的#spring Channels,或在Stack Overflow上使用spring
和kotlin
标签询问问题。
Requirements
Spring Boot 支持 Kotlin1.2.x。要使用 Kotlin,Classpath 上必须存在org.jetbrains.kotlin:kotlin-stdlib
和org.jetbrains.kotlin:kotlin-reflect
。也可以使用kotlin-stdlib
变体kotlin-stdlib-jdk7
和kotlin-stdlib-jdk8
。
从Kotlin 类默认为 final开始,您可能需要配置kotlin-spring插件,以便自动打开带有 Spring Comments 的类,以便对其进行代理。
在 Kotlin 中序列化/反序列化 JSON 数据需要Jackson 的 Kotlin 模块。在 Classpath 上找到它会自动注册。如果存在 Jackson 和 Kotlin 但不存在 Jackson Kotlin 模块,则会记录一条警告消息。
Tip
如果一个人在start.spring.io上引导 Kotlin 项目,则默认情况下会提供这些依赖项和插件。
Null-safety
Kotlin 的主要功能之一是null-safety。它在编译时处理null
值,而不是将问题推迟到运行时并遇到NullPointerException
。这有助于消除常见的错误源,而无需支付Optional
之类的包装器的费用。 Kotlin 还允许使用具有可空值的函数构造,如Kotlin 空安全综合指南中所述。
尽管 Java 不允许人在其类型系统中表示空安全性,但 Spring Framework,Spring Data 和 Reactor 现在通过易于使用工具的注解为 API 提供了空安全性。默认情况下,Kotlin 中使用的 Java API 中的类型被识别为platform types,对此类型的空检查得到了放宽。 Kotlin 对 JSR 305 注解的支持与可空性 Comments 结合使用,为 Kotlin 中的相关 Spring API 提供了空安全性。
可以通过添加带有以下选项的-Xjsr305
编译器标志来配置 JSR 305 检查:-Xjsr305={strict|warn|ignore}
。默认行为与-Xjsr305=warn
相同。必须使用strict
值来考虑从 Spring API 推断出的 Kotlin 类型的空安全性,但应使用该知识,即使 Spring API 的空性声明即使在次要发行版之间也可能会演变,并且将来可能会添加更多检查,这一点应得到使用。
Warning
尚不支持泛型类型参数,varargs 和数组元素的可空性。有关最新信息,请参见SPR-15942。另外请注意,Spring Boot 自己的 API 是尚未 注解。
KotlinAPI
runApplication
Spring Boot 提供了一种惯用的方式来使用runApplication<MyApplication>(*args)
运行应用程序,如以下示例所示:
1 | import org.springframework.boot.autoconfigure.SpringBootApplication |
这是SpringApplication.run(MyApplication::class.java, *args)
的直接替代。它还允许自定义应用程序,如以下示例所示:
1 | runApplication<MyApplication>(*args) { |
Extensions
Kotlin extensions提供了使用其他功能扩展现有类的功能。 Spring Boot Kotlin API 利用这些扩展为现有 API 添加了新的 Kotlin 专用便利。
提供了TestRestTemplate
extensions,类似于 Spring Framework 为RestOperations
在 Spring Framework 中提供的 extensions。除其他事项外,这些扩展使利用 Kotlin 修饰类型参数成为可能。
依赖性管理
为了避免在 Classpath 上混合使用不同版本的 Kotlin 依赖项,提供了以下 Kotlin 依赖项的依赖项 Management:
kotlin-reflect
kotlin-runtime
kotlin-stdlib
kotlin-stdlib-jdk7
kotlin-stdlib-jdk8
kotlin-stdlib-jre7
kotlin-stdlib-jre8
使用 Maven,可以通过kotlin.version
属性自定义 Kotlin 版本,并为kotlin-maven-plugin
提供插件 Management。使用 Gradle,Spring Boot 插件会自动将kotlin.version
与 Kotlin 插件的版本对齐。
@ConfigurationProperties
与@ConstructorBinding结合使用时,@ConfigurationProperties
支持具有不变val
属性的类,如以下示例所示:
1 |
|
Tip
要使用注解处理器生成您自己的元数据,具有
spring-boot-configuration-processor
依赖性的kapt 应该配置。
Testing
虽然可以使用 JUnit 4(由spring-boot-starter-test
提供的默认值)来测试 Kotlin 代码,但建议使用 JUnit 5. JUnit 5 使一个测试类可以实例化一次,并可以重新用于该类的所有测试。这样就可以在非静态方法上使用@BeforeAll
和@AfterAll
注解,这非常适合 Kotlin。
要使用 JUnit 5,请从spring-boot-starter-test
中排除junit:junit
依赖性,添加 JUnit 5 依赖性,并相应地配置 Maven 或 Gradle 插件。有关更多详细信息,请参见JUnit 5 文档。您还需要将测试实例生命周期切换为“每个类”。
Resources
进一步阅读
- Kotlin 语言参考
- Kotlin Slack(带有专用的#spring Channels)
- 具有 Spring 和 Kotlin 标签的 Stackoverflow
- 在浏览器中尝试 Kotlin
- Kotlin blog
- Awesome Kotlin
- 教程:使用 Spring Boot 和 Kotlin 构建 Web 应用程序
- 使用 Kotlin 开发 Spring Boot 应用程序
- 带有 Kotlin,Spring Boot 和 PostgreSQL 的地理空间 Messenger
- 在 Spring Framework 5.0 中引入 Kotlin 支持
- Spring Framework 5 Kotlin API 的功能方式
Examples
- spring-boot-kotlin-demo:常规 Spring Boot Spring Data JPA 项目
- mixit:Spring Boot 2 WebFlux Reactive Spring Data MongoDB
- spring-kotlin-fullstack:WebFlux Kotlin 全栈示例,其中 Kotlin2js 用于前端,而不是 JavaScript 或 TypeScript
- spring-petclinic-kotlin:Spring PetClinic 示例应用程序的 Kotlin 版本
- spring-kotlin-deepdive:从 Boot 1.0 Java 到 Boot 2.0 Kotlin 的逐步迁移
接下来要读什么
如果您想了解有关本节讨论的任何类的更多信息,可以签出Spring Boot API 文档或浏览直接源代码。如果您有特定问题,请查看how-to部分。
如果您熟悉 Spring Boot 的核心功能,则可以 continue 阅读production-ready features。