springboot-核心功能(机翻版)
核心功能
本节深入探讨 Spring Boot 的细节。在这里您可以了解您可能想要使用和自定义的主要功能。如果您还没有这样做,您可能需要阅读“入门”和“使用 Spring Boot 进行开发”部分,以便您打下良好的基础知识。
1. Spring应用
该类SpringApplication
提供了一种方便的方法来引导从方法启动的 Spring 应用程序main()
。在许多情况下,您可以委托给静态SpringApplication.run
方法,如以下示例所示:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
当您的应用程序启动时,您应该会看到类似于以下输出的内容:
. ____ _ _ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | // / /
=========|_|==============|___/=/_/_/_/
:: 春季启动 :: (v2.7.10)
2023-03-23 08:14:17.996 INFO 17618 --- [main] osbdfsMyApplication:在 PID 为 17618 的 myhost 上使用 Java 1.8.0_362 启动 MyApplication(/opt/apps/myapp.jar 由 myuser 在 /opt/apps/ 中启动)
2023-03-23 08:14:18.001 INFO 17618 --- [main] osbdfsMyApplication:未设置活动配置文件,回落到 1 个默认配置文件:“默认”
2023-03-23 08:14:19.597 INFO 17618 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 初始化端口:8080 (http)
2023-03-23 08:14:19.623 INFO 17618 --- [main] o.apache.catalina.core.StandardService:启动服务 [Tomcat]
2023-03-23 08:14:19.623 INFO 17618 --- [main] org.apache.catalina.core.StandardEngine:启动 Servlet 引擎:[Apache Tomcat/9.0.73]
2023-03-23 08:14:20.092 INFO 17618 --- [main] oaccC[Tomcat].[localhost].[/]:初始化 Spring 嵌入式 WebApplicationContext
2023-03-23 08:14:20.092 INFO 17618 --- [main] wscServletWebServerApplicationContext:Root WebApplicationContext:初始化在 2042 毫秒内完成
2023-03-23 08:14:21.281 INFO 17618 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 在端口上启动:8080 (http),上下文路径为“”
2023-03-23 08:14:21.295 INFO 17618 --- [main] osbdfsMyApplication:在 4.208 秒内启动 MyApplication(JVM 运行 4.643)
2023-03-23 08:14:21.309 INFO 17618 --- [ionShutdownHook] o.apache.catalina.core.StandardService:停止服务 [Tomcat]
默认情况下,INFO
会显示日志消息,包括一些相关的启动详细信息,例如启动应用程序的用户。如果您需要 以外的日志级别INFO
,您可以设置它,如日志级别中所述。应用程序版本是使用主应用程序类包中的实现版本来确定的。spring.main.log-startup-info
可以通过设置为关闭启动信息记录false
。这也将关闭应用程序活动配置文件的记录。
要在启动期间添加额外的日志记录,您可以
logStartupInfo(boolean)
在SpringApplication
.
1.1. 启动失败
如果您的应用程序无法启动,注册者FailureAnalyzers
有机会提供专门的错误消息和解决问题的具体操作。例如,如果您在端口上启动 Web 应用程序8080
并且该端口已被使用,您应该会看到类似于以下消息的内容:
******************************
应用程序启动失败
******************************
描述:
嵌入式 servlet 容器无法启动。端口 8080 已被使用。
行动:
识别并停止侦听端口 8080 的进程,或将此应用程序配置为侦听另一个端口。
Spring Boot 提供了多种
FailureAnalyzer
实现,您可以添加自己的.
如果没有故障分析器能够处理异常,您仍然可以显示完整的条件报告以更好地了解出了什么问题。为此,您需要为启用该debug
属性或启用DEBUG
日志记录org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
。
例如,如果您使用 运行您的应用程序java -jar
,则可以按debug
如下方式启用该属性:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
1.2. 惰性初始化
SpringApplication
允许延迟初始化应用程序。当启用惰性初始化时,bean 是在需要时创建的,而不是在应用程序启动期间创建的。因此,启用惰性初始化可以减少应用程序启动所需的时间。在 web 应用程序中,启用惰性初始化将导致许多与 web 相关的 bean 在收到 HTTP 请求之前不会被初始化。
惰性初始化的一个缺点是它可以延迟发现应用程序的问题。如果配置错误的 bean 被懒惰地初始化,则在启动期间将不再发生故障,并且只有在 bean 被初始化时问题才会变得明显。还必须注意确保 JVM 有足够的内存来容纳所有应用程序的 bean,而不仅仅是那些在启动期间初始化的 bean。由于这些原因,默认情况下不启用惰性初始化,建议在启用惰性初始化之前微调 JVM 的堆大小。
可以使用lazyInitialization
on 方法SpringApplicationBuilder
或setLazyInitialization
on 方法以编程方式启用延迟初始化SpringApplication
。spring.main.lazy-initialization
或者,可以使用以下示例中所示的属性启用它:
特性
山药
spring.main.lazy-initialization=true
如果您想对某些 bean 禁用延迟初始化,同时对应用程序的其余部分使用延迟初始化,则可以使用注释将它们的延迟属性显式设置为 false
@Lazy(false)
。
1.3. 自定义横幅
banner.txt
可以通过将文件添加到类路径或将spring.banner.location
属性设置为此类文件的位置来更改启动时打印的横幅。如果文件的编码不是 UTF-8,您可以设置spring.banner.charset
. 除了文本文件之外,您还可以将banner.gif
、banner.jpg
或banner.png
图像文件添加到类路径或设置spring.banner.image.location
属性。图像被转换为 ASCII 艺术表现形式并打印在任何文本横幅上方。
在您的banner.txt
文件中,您可以使用 中可用的任何键Environment
以及以下任何占位符:
多变的 | 描述 |
---|---|
${application.version} |
您的应用程序的版本号,如在中声明的那样MANIFEST.MF 。例如,Implementation-Version: 1.0 打印为1.0 . |
${application.formatted-version} |
您的应用程序的版本号,在中声明MANIFEST.MF 并格式化显示(用括号括起来并以 为前缀v )。例如(v1.0) 。 |
${spring-boot.version} |
您正在使用的 Spring Boot 版本。例如2.7.10 。 |
${spring-boot.formatted-version} |
您正在使用的 Spring Boot 版本,经过格式化以供显示(用方括号括起来并以 为前缀v )。例如(v2.7.10) 。 |
${Ansi.NAME} (或${AnsiColor.NAME} ,,${AnsiBackground.NAME} )${AnsiStyle.NAME} |
NAME ANSI 转义代码的名称在哪里。AnsiPropertySource 详情请见。 |
${application.title} |
您的应用程序的标题,如中声明的那样MANIFEST.MF 。例如Implementation-Title: MyApp 打印为MyApp . |
SpringApplication.setBanner(…)
如果您想以编程方式生成横幅,则可以使用 该方法。使用org.springframework.boot.Banner
接口并实现您自己的printBanner()
方法。
您还可以使用该spring.main.banner-mode
属性来确定是否必须在System.out
( console
) 上打印横幅、将其发送到配置的记录器 ( log
) 或根本不生成 ( off
)。
打印的横幅在以下名称下注册为单例 bean springBootBanner
:。
和
${application.version}
属性${application.formatted-version}
仅在您使用 Spring Boot 启动器时可用。如果您正在运行解压的 jar 并以java -cp <classpath> <mainclass>
.这就是为什么我们建议您始终使用java org.springframework.boot.loader.JarLauncher
.application.*
这将在构建类路径和启动您的应用程序之前初始化横幅变量。
1.4. 自定义 SpringApplication
如果SpringApplication
默认值不合您的口味,您可以创建一个本地实例并对其进行自定义。例如,要关闭横幅,您可以这样写:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
传递给的构造函数参数
SpringApplication
是 Spring bean 的配置源。在大多数情况下,这些是对@Configuration
类的引用,但它们也可以是直接引用@Component
类。
也可以SpringApplication
使用application.properties
文件进行配置。有关详细信息,请参阅*外部化配置*。
有关配置选项的完整列表,请参阅SpringApplication
Javadoc。
1.5. 流利的生成器 API
如果您需要构建ApplicationContext
层次结构(具有父/子关系的多个上下文)或者如果您更喜欢使用“流畅的”构建器 API,则可以使用SpringApplicationBuilder
.
允许您将多个方法调用和包含以及允许您创建层次结构的方法SpringApplicationBuilder
链接在一起,如以下示例所示:parent``child
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
创建层次结构时有一些限制
ApplicationContext
。例如,Web 组件必须包含在子上下文中,并且同样Environment
用于父上下文和子上下文。有关详细信息, 请参阅SpringApplicationBuilder
Javadoc 。
1.6. 应用可用性
当部署在平台上时,应用程序可以使用Kubernetes Probes等基础设施向平台提供有关其可用性的信息。Spring Boot 包括对常用的“活动”和“就绪”可用性状态的开箱即用支持。如果您使用 Spring Boot 的“执行器”支持,那么这些状态将作为健康端点组公开。
此外,您还可以通过将ApplicationAvailability
接口注入到您自己的 bean 中来获取可用性状态。
1.6.1. 活性状态
应用程序的“活动”状态表明它的内部状态是否允许它正常工作,或者如果它当前失败则自行恢复。损坏的“活动”状态意味着应用程序处于无法恢复的状态,基础架构应重新启动应用程序。
一般来说,“Liveness”状态不应该基于外部检查,比如Health checks。如果是这样,一个失败的外部系统(数据库、Web API、外部缓存)将触发大规模重启和整个平台的级联故障
Spring Boot 应用程序的内部状态主要由 Spring 表示ApplicationContext
。如果应用程序上下文已成功启动,Spring Boot 会假定应用程序处于有效状态。一旦上下文被刷新,应用程序就被认为是活跃的,请参阅Spring Boot 应用程序生命周期和相关的应用程序事件。
1.6.2. 准备状态
应用程序的“就绪”状态表明应用程序是否已准备好处理流量。失败的“就绪”状态告诉平台它现在不应该将流量路由到应用程序。这通常发生在启动期间,同时正在处理CommandLineRunner
和ApplicationRunner
组件,或者在应用程序决定它太忙而无法处理额外流量时发生。
一旦应用程序和命令行运行程序被调用,应用程序就被认为准备就绪,请参阅Spring Boot 应用程序生命周期和相关的应用程序事件。
预期在启动期间运行的任务应该由组件执行,
CommandLineRunner
而ApplicationRunner
不是使用 Spring 组件生命周期回调,例如@PostConstruct
.
1.6.3. 管理应用程序可用性状态
应用程序组件可以随时通过注入ApplicationAvailability
接口和调用方法来检索当前的可用性状态。更多时候,应用程序会想要监听状态更新或更新应用程序的状态。
例如,我们可以将应用程序的“Readiness”状态导出到一个文件中,以便 Kubernetes 的“exec Probe”可以查看这个文件:
@Component
public class MyReadinessStateExporter {
@EventListener
public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
switch (event.getState()) {
case ACCEPTING_TRAFFIC:
// create file /tmp/healthy
break;
case REFUSING_TRAFFIC:
// remove file /tmp/healthy
break;
}
}
}
当应用程序中断且无法恢复时,我们还可以更新应用程序的状态:
@Component
public class MyLocalCacheVerifier {
private final ApplicationEventPublisher eventPublisher;
public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void checkLocalCache() {
try {
// ...
}
catch (CacheCompletelyBrokenException ex) {
AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
}
}
}
Spring Boot通过 Actuator Health Endpoints 为“Liveness”和“Readiness”提供 Kubernetes HTTP 探测。您可以在专用部分中获得有关在 Kubernetes 上部署 Spring Boot 应用程序的更多指导。
1.7. 应用程序事件和监听器
除了通常的 Spring Framework 事件(例如 )之外ContextRefreshedEvent
,aSpringApplication
还会发送一些额外的应用程序事件。
有些事件实际上是在
ApplicationContext
创建之前触发的,因此您不能将这些事件的侦听器注册为@Bean
.SpringApplication.addListeners(…)
您可以使用方法或方法注册它们SpringApplicationBuilder.listeners(…)
。如果您希望自动注册这些侦听器,而不管应用程序的创建方式如何,您可以将文件添加META-INF/spring.factories
到您的项目并使用密钥引用您的侦听器org.springframework.context.ApplicationListener
,如以下示例所示:org.springframework.context.ApplicationListener=com.example.project.MyListener
当您的应用程序运行时,应用程序事件按以下顺序发送:
- An
ApplicationStartingEvent
在运行开始时发送,但在任何处理之前发送,除了侦听器和初始化程序的注册。 - 当要在上下文中使用的 已知但在创建上下文之前
ApplicationEnvironmentPreparedEvent
发送An 。Environment
- 准备好并调用 ApplicationContextInitializers 但在加载任何 bean 定义之前
ApplicationContextInitializedEvent
发送An 。ApplicationContext
- 就
ApplicationPreparedEvent
在刷新开始之前但在加载 bean 定义之后发送。 ApplicationStartedEvent
在刷新上下文之后但在调用任何应用程序和命令行运行程序之前发送An 。AvailabilityChangeEvent
在 with 之后立即发送AnLivenessState.CORRECT
以指示该应用程序被认为是实时的。- 在调用
ApplicationReadyEvent
任何应用程序和命令行运行程序后发送。 AvailabilityChangeEvent
在 with 之后立即发送AnReadinessState.ACCEPTING_TRAFFIC
以指示应用程序已准备好服务请求。ApplicationFailedEvent
如果启动时出现异常,则发送An 。
上面的列表只包括SpringApplicationEvent
绑定到 a 的 s SpringApplication
。除了这些之外,以下事件也在之后ApplicationPreparedEvent
和之前发布ApplicationStartedEvent
:
- A在准备就绪
WebServerInitializedEvent
后发送WebServer
。ServletWebServerInitializedEvent
和ReactiveWebServerInitializedEvent
分别是 servlet 和反应式变体。 - 刷新
ContextRefreshedEvent
时发送A。ApplicationContext
您通常不需要使用应用程序事件,但知道它们存在会很方便。在内部,Spring Boot 使用事件来处理各种任务。
事件侦听器不应运行可能冗长的任务,因为它们默认在同一线程中执行。考虑改用应用程序和命令行运行器。
应用事件通过Spring Framework的事件发布机制发送。该机制的一部分确保发布到子上下文中的侦听器的事件也被发布到任何祖先上下文中的侦听器。因此,如果您的应用程序使用SpringApplication
实例层次结构,则侦听器可能会收到同一类型应用程序事件的多个实例。
为了让您的侦听器区分其上下文的事件和后代上下文的事件,它应该请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现注入上下文ApplicationContextAware
,或者,如果侦听器是一个 bean,则使用@Autowired
.
1.8. 网络环境
A尝试代表您SpringApplication
创建正确的类型。ApplicationContext
用于确定 a 的算法WebApplicationType
如下:
- 如果存在 Spring MVC,则
AnnotationConfigServletWebServerApplicationContext
使用 - 如果 Spring MVC 不存在而 Spring WebFlux 存在,则
AnnotationConfigReactiveWebServerApplicationContext
使用 - 否则,
AnnotationConfigApplicationContext
使用
这意味着如果您WebClient
在同一应用程序中使用 Spring MVC 和 Spring WebFlux 的新功能,则默认情况下将使用 Spring MVC。您可以通过调用轻松覆盖它setWebApplicationType(WebApplicationType)
。
也可以完全控制ApplicationContext
调用所使用的类型setApplicationContextFactory(…)
。
在 JUnit 测试中 setWebApplicationType(WebApplicationType.NONE) 使用时 通常需要调用。SpringApplication |
|
---|---|
1.9. 访问应用程序参数
如果您需要访问传递给 的应用程序参数SpringApplication.run(…)
,您可以注入一个org.springframework.boot.ApplicationArguments
bean。该ApplicationArguments
接口提供对原始String[]
参数以及已解析参数option
和non-option
参数的访问,如以下示例所示:
@Component
public class MyBean {
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
if (debug) {
System.out.println(files);
}
// if run with "--debug logfile.txt" prints ["logfile.txt"]
}
}
Spring Boot 还CommandLinePropertySource 向 Spring注册了一个Environment 。这使您还可以使用@Value 注释注入单个应用程序参数。 |
|
---|---|
1.10. 使用 ApplicationRunner 或 CommandLineRunner
如果您需要在启动后运行一些特定的代码SpringApplication
,您可以实现ApplicationRunner
或CommandLineRunner
接口。这两个接口以相同的方式工作,并提供一个run
方法,该方法在完成之前被调用SpringApplication.run(…)
。
此合同非常适合应在应用程序启动后但在开始接受流量之前运行的任务。 | |
---|---|
这些CommandLineRunner
接口提供对应用程序参数作为字符串数组的访问,而ApplicationRunner
使用ApplicationArguments
前面讨论的接口。以下示例显示了一个CommandLineRunner
方法run
:
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// Do something...
}
}
如果定义了几个CommandLineRunner
必须ApplicationRunner
按特定顺序调用的 bean,您可以另外实现org.springframework.core.Ordered
接口或使用org.springframework.core.annotation.Order
注释。
1.11. 申请出口
每个都SpringApplication
向 JVM 注册一个关闭挂钩,以确保ApplicationContext
在退出时正常关闭。可以使用所有标准的 Spring 生命周期回调(例如DisposableBean
接口或注释)。@PreDestroy
此外,org.springframework.boot.ExitCodeGenerator
如果 bean 希望在SpringApplication.exit()
被调用时返回特定的退出代码,则它们可以实现该接口。然后可以将此退出代码传递给以System.exit()
将其作为状态代码返回,如以下示例所示:
@SpringBootApplication
public class MyApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
}
}
此外,ExitCodeGenerator
接口可以通过异常来实现。遇到此类异常时,Spring Boot 会返回已实现getExitCode()
方法提供的退出代码。
如果有多个ExitCodeGenerator
,则使用生成的第一个非零退出代码。要控制调用生成器的顺序,另外实现接口org.springframework.core.Ordered
或使用org.springframework.core.annotation.Order
注释。
1.12. 管理员功能
可以通过指定属性为应用程序启用与管理相关的功能spring.application.admin.enabled
。这暴露了SpringApplicationAdminMXBean
平台上的MBeanServer
。您可以使用此功能远程管理您的 Spring Boot 应用程序。此功能也可用于任何服务包装器实现。
如果您想知道应用程序在哪个 HTTP 端口上运行,请获取键为 的属性local.server.port 。 |
|
---|---|
1.13. 应用程序启动跟踪
在应用程序启动期间,SpringApplication
执行ApplicationContext
许多与应用程序生命周期、bean 生命周期甚至处理应用程序事件相关的任务。有了ApplicationStartup
Spring Framework, 您就可以使用对象跟踪应用程序启动顺序StartupStep
。可以收集这些数据用于分析目的,或者只是为了更好地了解应用程序启动过程。
您可以ApplicationStartup
在设置SpringApplication
实例时选择一个实现。例如,要使用BufferingApplicationStartup
,您可以这样写:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
}
}
第一个可用的实现FlightRecorderApplicationStartup
由 Spring Framework 提供。它将特定于 Spring 的启动事件添加到 Java Flight Recorder 会话中,旨在分析应用程序并将其 Spring 上下文生命周期与 JVM 事件(例如分配、GC、类加载……)相关联。配置完成后,您可以在启用飞行记录器的情况下运行应用程序来记录数据:
$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar
Spring Boot 附带BufferingApplicationStartup
变体;此实现旨在缓冲启动步骤并将它们排入外部指标系统。应用程序可以在任何组件中请求类型的 bean BufferingApplicationStartup
。
Spring Boot 还可以配置为公开一个以 JSON 文档形式提供此信息的startup
端点。
2. 外化配置
Spring Boot 允许您外部化您的配置,以便您可以在不同的环境中使用相同的应用程序代码。您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以通过注解直接注入 bean @Value
,通过 Spring 的抽象访问,Environment
或者通过.@ConfigurationProperties
Spring Boot 使用一种非常特殊的PropertySource
顺序,旨在允许合理地覆盖值。后面的属性源可以覆盖前面定义的值。来源按以下顺序考虑:
- 默认属性(由设置指定
SpringApplication.setDefaultProperties
)。 @PropertySource
类上的注释@Configuration
。Environment
请注意,在刷新应用程序上下文之前,不会将此类属性源添加到。现在配置某些属性(例如logging.*
和spring.main.*
在刷新开始前读取)为时已晚。- 配置数据(例如
application.properties
文件)。 RandomValuePropertySource
仅在 中具有属性的random.*
。- 操作系统环境变量。
- Java 系统属性 (
System.getProperties()
)。 - JNDI 属性来自
java:comp/env
. ServletContext
初始化参数。ServletConfig
初始化参数。- 属性来自
SPRING_APPLICATION_JSON
(嵌入在环境变量或系统属性中的内联 JSON)。 - 命令行参数。
properties
测试的属性。@SpringBootTest
在和测试注释上可用,用于测试应用程序的特定部分。@TestPropertySource
测试注释。$HOME/.config/spring-boot
当 devtools 处于活动状态时,目录中的Devtools全局设置属性。
配置数据文件按以下顺序考虑:
- 打包在 jar 中的应用程序属性
application.properties
(和 YAML 变体)。 - 打包在您的 jar(和 YAML 变体)中的特定于配置文件的应用程序属性
application-{profile}.properties
。 - 打包的 jar(和 YAML 变体)之外的应用程序属性
application.properties
。 - 打包的 jar(和 YAML 变体)之外的特定于配置文件的应用程序属性
application-{profile}.properties
。
建议为您的整个应用程序坚持使用一种格式。如果您的配置文件同时具有.properties 和格式,则优先。 .yml``.properties |
|
---|---|
为了提供一个具体示例,假设您开发了一个@Component
使用name
属性的应用程序,如以下示例所示:
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
在您的应用程序类路径中(例如,在您的 jar 中),您可以有一个application.properties
文件为name
. 在新环境中运行时,application.properties
可以在 jar 之外提供一个文件来覆盖name
. 对于一次性测试,您可以使用特定的命令行开关(例如,java -jar app.jar --name="Spring"
)启动。
和端点可用于确定属性具有特定值的原因env 。configprops 您可以使用这两个端点来诊断意外的属性值。有关详细信息,请参阅“生产就绪功能”部分。 |
|
---|---|
2.1. 访问命令行属性
默认情况下,SpringApplication
将任何命令行选项参数(即以 开头的参数--
,例如--server.port=9000
)转换为 aproperty
并将它们添加到 Spring 中Environment
。如前所述,命令行属性始终优先于基于文件的属性源。
如果您不想将命令行属性添加到 中Environment
,您可以使用 禁用它们SpringApplication.setAddCommandLineProperties(false)
。
2.2. JSON 应用程序属性
环境变量和系统属性通常有限制,这意味着某些属性名称不能使用。为了解决这个问题,Spring Boot 允许您将属性块编码为单个 JSON 结构。
当您的应用程序启动时,任何spring.application.json
或SPRING_APPLICATION_JSON
属性将被解析并添加到Environment
.
例如,SPRING_APPLICATION_JSON
可以在 UN*X shell 的命令行中将属性作为环境变量提供:
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,您最终my.name=test
在 Spring 中Environment
。
同样的 JSON 也可以作为系统属性提供:
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
或者您可以使用命令行参数提供 JSON:
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
如果要部署到经典应用程序服务器,您还可以使用名为 的 JNDI 变量java:comp/env/spring.application.json
。
虽然null JSON 中的值将添加到生成的属性源中,但PropertySourcesPropertyResolver 会将null 属性视为缺失值。这意味着 JSON 无法使用值覆盖来自低阶属性源的属性null 。 |
|
---|---|
2.3. 外部应用程序属性
当您的应用程序启动时,Spring Boot 将自动从以下位置查找并加载application.properties
文件:application.yaml
- 从类路径
- 类路径根
- 类路径
/config
包
- 从当前目录
- 当前目录
config/
当前目录下的子目录config/
子目录的直接子目录
该列表按优先级排序(较低项的值覆盖较早的项)。加载文件中的文档被添加PropertySources
到 Spring 中Environment
。
如果您不喜欢application
作为配置文件名,您可以通过指定一个spring.config.name
环境属性来切换到另一个文件名。例如,要查找myproject.properties
和myproject.yaml
文件,您可以按如下方式运行您的应用程序:
$ java -jar myproject.jar --spring.config.name=myproject
您还可以使用环境属性来引用显式位置spring.config.location
。此属性接受一个或多个要检查的位置的逗号分隔列表。
以下示例显示如何指定两个不同的文件:
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
optional: 如果位置是可选的并且您不介意它们不存在, 请使用前缀。 |
|
---|---|
spring.config.name , spring.config.location , 和spring.config.additional-location 很早就用于确定必须加载哪些文件。它们必须定义为环境属性(通常是操作系统环境变量、系统属性或命令行参数)。 |
|
---|---|
如果spring.config.location
包含目录(而不是文件),它们应该以/
. 在运行时,它们将附加在spring.config.name
加载之前生成的名称。中指定的文件spring.config.location
直接导入。
目录和文件位置值也被扩展以检查特定于配置文件的文件。例如,如果您有一个spring.config.location of classpath:myconfig.properties ,您还会发现classpath:myconfig-<profile>.properties 加载了适当的文件。 |
|
---|---|
在大多数情况下,spring.config.location
您添加的每个项目都将引用一个文件或目录。位置按照它们被定义的顺序处理,后面的可以覆盖前面的值。
如果你有一个复杂的位置设置,并且你使用特定于配置文件的配置文件,你可能需要提供进一步的提示,以便 Spring Boot 知道它们应该如何分组。位置组是所有位置都被视为同一级别的位置的集合。例如,您可能希望对所有类路径位置进行分组,然后对所有外部位置进行分组。位置组中的项目应该用 分隔;
。有关详细信息,请参阅“配置文件特定文件”部分中的示例。
使用配置的位置spring.config.location
替换默认位置。例如,如果spring.config.location
配置了值optional:classpath:/custom-config/,optional:file:./custom-config/
,则考虑的完整位置集是:
optional:classpath:custom-config/
optional:file:./custom-config/
如果您更喜欢添加其他位置,而不是替换它们,您可以使用spring.config.additional-location
. 从其他位置加载的属性可以覆盖默认位置中的属性。例如,如果spring.config.additional-location
配置了值optional:classpath:/custom-config/,optional:file:./custom-config/
,则考虑的完整位置集是:
optional:classpath:/;optional:classpath:/config/
optional:file:./;optional:file:./config/;optional:file:./config/*/
optional:classpath:custom-config/
optional:file:./custom-config/
此搜索顺序使您可以在一个配置文件中指定默认值,然后在另一个配置文件中有选择地覆盖这些值。您可以在默认位置之一的application.properties
(或您选择的任何其他基本名称)中为您的应用程序提供默认值。spring.config.name
然后可以在运行时使用位于自定义位置之一的不同文件覆盖这些默认值。
如果您使用环境变量而不是系统属性,大多数操作系统不允许使用句点分隔的键名,但您可以使用下划线代替(例如,SPRING_CONFIG_NAME 代替spring.config.name )。有关详细信息, 请参阅从环境变量绑定。 |
|
---|---|
如果您的应用程序在 servlet 容器或应用程序服务器中运行,则java:comp/env 可以使用 JNDI 属性(在 中)或 servlet 上下文初始化参数来代替或同时使用环境变量或系统属性。 |
|
---|---|
2.3.1. 可选地点
默认情况下,当指定的配置数据位置不存在时,Spring Boot 将抛出一个ConfigDataLocationNotFoundException
并且您的应用程序将不会启动。
如果你想指定一个位置,但你不介意它并不总是存在,你可以使用前缀optional:
。您可以将此前缀与spring.config.location
和spring.config.additional-location
属性以及spring.config.import
声明一起使用。
例如,spring.config.import
值optional:file:./myconfig.properties
允许您的应用程序启动,即使myconfig.properties
文件丢失。
如果您想忽略所有ConfigDataLocationNotFoundExceptions
并始终继续启动您的应用程序,您可以使用该spring.config.on-not-found
属性。将值设置为ignore
使用SpringApplication.setDefaultProperties(…)
或与系统/环境变量一起使用。
2.3.2. 通配符位置
如果配置文件位置包含*
最后一个路径段的字符,则它被视为通配符位置。加载配置时会扩展通配符,以便也检查直接子目录。当存在多个配置属性源时,通配符位置在 Kubernetes 等环境中特别有用。
例如,如果您有一些 Redis 配置和一些 MySQL 配置,您可能希望将这两部分配置分开,同时要求它们都存在于一个文件中application.properties
。这可能会导致两个单独的application.properties
文件安装在不同的位置,例如/config/redis/application.properties
和/config/mysql/application.properties
。在这种情况下,具有通配符位置config/*/
, 将导致同时处理两个文件。
默认情况下,Spring Boot 包含config/*/
在默认搜索位置中。这意味着/config
将搜索 jar 之外目录的所有子目录。
您可以自己将通配符位置与spring.config.location
和spring.config.additional-location
属性一起使用。
对于作为目录的搜索位置或作为文件的搜索位置, 通配符位置必须仅包含一个* 并以结尾。带通配符的位置根据文件名的绝对路径按字母顺序排序。 */``*/<filename> |
|
---|---|
通配符位置仅适用于外部目录。您不能在位置中使用通配符classpath: 。 |
|
---|---|
2.3.3. 配置文件特定文件
除了application
属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}
。例如,如果您的应用程序激活一个名为 profileprod
并使用 YAML 文件,那么application.yml
和application-prod.yml
都会被考虑。
特定于配置文件的属性从与标准相同的位置加载application.properties
,特定于配置文件的文件始终覆盖非特定文件。如果指定了多个配置文件,则应用最后获胜的策略。例如,如果配置文件prod,live
由属性指定spring.profiles.active
,则 中的值application-prod.properties
可以被 中的值覆盖application-live.properties
。
最后获胜的策略适用于营业地点组级别。A spring.config.location ofclasspath:/cfg/,classpath:/ext/ 将不会具有与 相同的覆盖规则classpath:/cfg/;classpath:/ext/ 。例如,继续prod,live 上面的示例,我们可能有以下文件:/配置文件 application-live.properties /分机 application-live.properties 应用产品.properties 当我们有一个spring.config.location 时classpath:/cfg/,classpath:/ext/ ,我们在处理所有/cfg 文件之前处理所有/ext 文件:/cfg/application-live.properties``/ext/application-prod.properties``/ext/application-live.properties 相反,当我们有classpath:/cfg/;classpath:/ext/ (带有; 分隔符)时,我们在同一级别处理/cfg 和:/ext``/ext/application-prod.properties``/cfg/application-live.properties``/ext/application-live.properties |
|
---|---|
有Environment
一组默认配置文件(默认情况下为[default]
),如果未设置活动配置文件,则使用这些配置文件。换句话说,如果没有显式激活配置文件,则application-default
考虑来自的属性。
属性文件只加载一次。如果您已经直接导入了配置文件特定的属性文件,则不会再次导入它。 | |
---|---|
2.3.4. 导入附加数据
应用程序属性可以使用该属性从其他位置导入更多配置数据spring.config.import
。进口在发现时进行处理,并被视为紧接在声明进口的文件下方插入的附加文件。
例如,您的类路径application.properties
文件中可能包含以下内容:
特性
山药
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
这将触发当前目录中文件的导入dev.properties
(如果存在这样的文件)。来自导入的值dev.properties
将优先于触发导入的文件。在上面的示例中,dev.properties
可以重新定义spring.application.name
为不同的值。
一个导入无论声明多少次都只会被导入一次。在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。例如,下面的两个示例产生相同的结果:
特性
山药
spring.config.import=my.properties
my.property=value
特性
山药
my.property=value
spring.config.import=my.properties
在上述两个示例中,文件中的值my.properties
将优先于触发其导入的文件。
可以在一个键下指定多个位置spring.config.import
。位置将按照定义的顺序进行处理,以后的导入优先。
在适当的时候,特定于配置文件的变体也被考虑导入。上面的示例将导入两者my.properties 以及任何my-<profile>.properties 变体。 |
|
---|---|
Spring Boot 包含可插入的 API,允许支持各种不同的位置地址。默认情况下,您可以导入 Java 属性、YAML 和“配置树”。第三方 jar 可以提供对其他技术的支持(不要求文件是本地的)。例如,您可以想象配置数据来自 Consul、Apache ZooKeeper 或 Netflix Archaius 等外部存储。如果您想支持自己的位置,请参阅包中的ConfigDataLocationResolver 和类。ConfigDataLoader``org.springframework.boot.context.config |
|
---|---|
2.3.5. 导入无扩展名文件
某些云平台无法为卷挂载文件添加文件扩展名。要导入这些没有扩展名的文件,你需要给 Spring Boot 一个提示,让它知道如何加载它们。您可以通过在方括号中放置一个扩展提示来做到这一点。
例如,假设您有一个/etc/config/myconfig
要导入为 yaml 的文件。您可以application.properties
使用以下方法将其导入:
特性
山药
spring.config.import=file:/etc/config/myconfig[.yaml]
2.3.6. 使用配置树
在云平台(例如 Kubernetes)上运行应用程序时,您经常需要读取平台提供的配置值。出于此类目的使用环境变量并不少见,但这可能有缺点,尤其是在值应该保密的情况下。
作为环境变量的替代方案,许多云平台现在允许您将配置映射到已安装的数据卷中。例如,Kubernetes 可以卷挂载ConfigMaps
和Secrets
.
可以使用两种常见的卷安装模式:
- 单个文件包含一组完整的属性(通常写为 YAML)。
- 多个文件被写入目录树,文件名成为“键”,内容成为“值”。
对于第一种情况,您可以直接使用上述spring.config.import
方法导入 YAML 或 Properties 文件。对于第二种情况,您需要使用前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。configtree:
例如,假设 Kubernetes 已经安装了以下卷:
ETC/
配置/
我的应用程序/
用户名
密码
该username
文件的内容将是一个配置值,而其内容password
将是一个秘密。
要导入这些属性,您可以将以下内容添加到您的application.properties
orapplication.yaml
文件中:
特性
山药
spring.config.import=optional:configtree:/etc/config/
然后,您可以以通常的方式访问或注入myapp.username
属性。myapp.password``Environment
配置树下的文件夹构成属性名称。在上面的示例中,要访问属性为username 和password ,您可以设置spring.config.import 为optional:configtree:/etc/config/myapp 。 |
|
---|---|
带点符号的文件名也被正确映射。例如,在上面的示例中,名为myapp.username in的文件/etc/config 将导致. myapp.username``Environment |
|
---|---|
根据预期的内容, 配置树值可以绑定到字符串String 和类型。byte[] |
|
---|---|
如果您有多个配置树要从同一个父文件夹导入,您可以使用通配符快捷方式。configtree:
以结尾的任何位置都/*/
将导入所有直接子项作为配置树。
例如,给定以下体积:
ETC/
配置/
数据库配置/
D b/
用户名
密码
mq配置/
平方米/
用户名
密码
您可以用作configtree:/etc/config/*/
导入位置:
特性
山药
spring.config.import=optional:configtree:/etc/config/*/
这将添加db.username
、db.password
和mq.username
属性mq.password
。
使用通配符加载的目录按字母顺序排序。如果您需要不同的订单,那么您应该将每个位置列为单独的导入 | |
---|---|
配置树也可用于 Docker 机密。当 Docker swarm 服务被授予访问秘密的权限时,秘密就会被装载到容器中。例如,如果一个名为 secretdb.password
挂载在 location /run/secrets/
,您可以db.password
使用以下命令使 Spring 环境可用:
特性
山药
spring.config.import=optional:configtree:/run/secrets/
2.3.7. 财产占位符
application.properties
和中的值在使用时application.yml
会通过现有值进行过滤Environment
,因此您可以参考以前定义的值(例如,来自系统属性或环境变量)。标准${name}
属性占位符语法可用于值内的任何位置。属性占位符还可以指定一个默认值,使用 a:
将默认值与属性名称分隔开,例如${name:default}
。
以下示例显示了带默认值和不带默认值的占位符的使用:
特性
山药
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
假设该username
属性未在别处设置,app.description
则值为MyApp is a Spring Boot application written by Unknown
。
您应该始终使用规范形式(仅使用小写字母的 kebab-case)来引用占位符中的属性名称。这将允许 Spring Boot 使用与放松绑定 @ConfigurationProperties 时相同的逻辑。例如,将从文件以及系统环境中${demo.item-price} 获取demo.item-price 和形成demo.itemPrice 表格。如果你改用了,就不会考虑了。application.properties``DEMO_ITEMPRICE``${demo.itemPrice}``demo.item-price``DEMO_ITEMPRICE |
|
---|---|
您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。有关详细信息,请参阅*howto.html*操作指南。 | |
---|---|
2.3.8. 使用多文档文件
Spring Boot 允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档都是独立添加的。文档按顺序从上到下处理。以后的文档可以覆盖早期文档中定义的属性。
对于application.yml
文件,使用标准的 YAML 多文档语法。三个连续的连字符代表一个文档的结尾和下一个文档的开始。
例如,以下文件有两个逻辑文档:
spring:
application:
name: "MyApp"
---
spring:
application:
name: "MyCloudApp"
config:
activate:
on-cloud-platform: "kubernetes"
对于application.properties
文件,特殊#---
或!---
注释用于标记文档拆分:
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
属性文件分隔符不能有任何前导空格,并且必须正好有三个连字符。分隔符前后的行不能是相同的注释前缀。 | |
---|---|
多文档属性文件通常与激活属性结合使用,例如spring.config.activate.on-profile . 有关详细信息,请参阅下一节。 |
|
---|---|
不能使用@PropertySource 或@TestPropertySource 注释加载多文档属性文件。 |
|
---|---|
2.3.9. 激活属性
有时仅在满足某些条件时才激活一组给定的属性很有用。例如,您可能拥有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用 有条件地激活属性文档spring.config.activate.*
。
以下激活属性可用:
财产 | 笔记 |
---|---|
on-profile |
必须匹配文档才能激活的配置文件表达式。 |
on-cloud-platform |
必须CloudPlatform 检测到文档才能激活的 。 |
例如,以下指定第二个文档仅在 Kubernetes 上运行时才处于活动状态,并且仅当“prod”或“staging”配置文件处于活动状态时:
特性
山药
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
2.4. 加密属性
Spring Boot 不提供任何对加密属性值的内置支持,但是,它确实提供了修改 Spring 中包含的值所必需的挂钩点Environment
。该界面允许您在应用程序启动之前EnvironmentPostProcessor
操作。Environment
有关详细信息,请参阅howto.html。
如果您需要一种安全的方式来存储凭据和密码,Spring Cloud Vault项目提供了对在HashiCorp Vault中存储外部化配置的支持。
2.5. 使用 YAML
YAML是 JSON 的超集,因此是一种用于指定分层配置数据的便捷格式。只要您的类路径上有SnakeYAML库,该类SpringApplication
就会自动支持 YAML 作为属性的替代方法。
如果您使用“Starters”,SnakeYAML 由spring-boot-starter . |
|
---|---|
2.5.1. 将 YAML 映射到属性
YAML 文档需要从其分层格式转换为可与 Spring 一起使用的平面结构Environment
。例如,考虑以下 YAML 文档:
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
为了从 访问这些属性Environment
,它们将被展平如下:
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App
同样,YAML 列表也需要扁平化。它们表示为带有[index]
解引用器的属性键。例如,考虑以下 YAML:
my:
servers:
- "dev.example.com"
- "another.example.com"
前面的示例将转换为这些属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
使用该[index] 表示法的属性可以绑定到 JavaList 或Set 使用 Spring BootBinder 类的对象。有关详细信息,请参阅下面的“类型安全配置属性”部分。 |
|
---|---|
YAML 文件不能使用@PropertySource 或@TestPropertySource 注释加载。因此,如果您需要以这种方式加载值,则需要使用属性文件。 |
|
---|---|
2.5.2. 直接加载 YAML
Spring 框架提供了两个方便的类,可用于加载 YAML 文档。将YamlPropertiesFactoryBean
YAML 加载为Properties
并将YamlMapFactoryBean
YAML 加载为Map
.
YamlPropertySourceLoader
如果要将 YAML 作为 Spring 加载,也可以使用该类PropertySource
。
2.6. 配置随机值
这RandomValuePropertySource
对于注入随机值很有用(例如,注入秘密或测试用例)。它可以生成整数、长整数、uuid 或字符串,如以下示例所示:
特性
山药
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
语法random.int*
是任何OPEN value (,max) CLOSE
字符OPEN,CLOSE
和value,max
整数。如果max
提供,则为value
最小值,max
为最大值(不包括)。
2.7. 配置系统环境属性
Spring Boot 支持为环境属性设置前缀。如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将非常有用。系统环境属性的前缀可以直接在SpringApplication
.
例如,如果将前缀设置为,则也将像在系统环境中一样解析input
诸如 之类的属性。remote.timeout``input.remote.timeout
2.8. 类型安全配置属性
使用@Value("${property}")
注解注入配置属性有时会很麻烦,尤其是当您使用多个属性或您的数据本质上是分层的时。Spring Boot 提供了一种使用属性的替代方法,可以让强类型 bean 管理和验证应用程序的配置。
另请参阅类型安全配置属性和类型安全配置属性之间的差异@Value 。 |
|
---|---|
2.8.1. JavaBean 属性绑定
可以绑定声明标准 JavaBean 属性的 bean,如以下示例所示:
@ConfigurationProperties("my.service")
public class MyProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
// getters / setters...
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
// getters / setters...
}
}
前面的 POJO 定义了以下属性:
my.service.enabled
,默认值为false
。my.service.remote-address
, 具有可以从String
.my.service.security.username
,具有嵌套的“安全”对象,其名称由属性的名称确定。特别是,该类型根本没有在那里使用,可能是SecurityProperties
.my.service.security.password
.my.service.security.roles
,其中的集合String
默认为USER
.
通过属性文件、YAML 文件、环境变量和其他机制配置的映射到 Spring Boot 中可用类的属性@ConfigurationProperties 是公共 API,但类本身的访问器(getters/setters)并不意味着直接使用. |
|
---|---|
这种安排依赖于默认的空构造函数,getter 和 setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。在以下情况下可以省略 setter:地图,只要它们被初始化,就需要一个 getter 但不一定是 setter,因为它们可以被活页夹改变。可以通过索引(通常使用 YAML)或使用单个逗号分隔值(属性)来访问集合和数组。在后一种情况下,setter 是强制性的。我们建议始终为此类类型添加一个 setter。如果您初始化一个集合,请确保它不是不可变的(如前例所示)。如果嵌套的 POJO 属性被初始化(如Security 前面示例中的字段),则不需要 setter。如果您希望活页夹使用其默认构造函数动态创建实例,则需要一个设置器。有些人使用 Project Lombok 来自动添加 getter 和 setter。确保 Lombok 不会为此类类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。最后,只考虑标准 Java Bean 属性,不支持绑定静态属性。 |
|
---|---|
2.8.2. 构造函数绑定
上一节中的示例可以以不可变的方式重写,如以下示例所示:
@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {
// fields...
public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
// getters...
public static class Security {
// fields...
public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
this.username = username;
this.password = password;
this.roles = roles;
}
// getters...
}
}
在此设置中,@ConstructorBinding
注释用于指示应使用构造函数绑定。这意味着绑定器将期望找到一个带有您希望绑定的参数的构造函数。如果您使用的是 Java 16 或更高版本,构造函数绑定可以与记录一起使用。在这种情况下,除非您的记录有多个构造函数,否则没有必要使用@ConstructorBinding
.
类的嵌套成员@ConstructorBinding
(如上Security
例)也将通过其构造函数进行绑定。
可以使用@DefaultValue
构造函数参数指定默认值,或者在使用 Java 16 或更高版本时使用记录组件指定默认值。转换服务将用于将String
值强制转换为缺失属性的目标类型。
参考前面的示例,如果没有属性绑定到Security
,则该MyProperties
实例将包含null
的值security
。要使它包含一个非空的实例,Security
即使没有属性绑定到它(使用 Kotlin 时,这将需要将 的username
和password
参数声明Security
为可空的,因为它们没有默认值),使用空@DefaultValue
注释:
public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
要使用构造函数绑定,必须使用@EnableConfigurationProperties 或配置属性扫描来启用类。您不能对由常规 Spring 机制创建的 bean 使用构造函数绑定(例如@Component bean、使用@Bean 方法创建的 bean 或使用加载的 bean @Import ) |
|
---|---|
如果您的类有多个构造函数,您也可以@ConstructorBinding 直接在应该绑定的构造函数上使用。 |
|
---|---|
不建议使用java.util.Optional with @ConfigurationProperties ,因为它主要用作返回类型。因此,它不太适合配置属性注入。为了与其他类型的属性保持一致,如果您确实声明了一个Optional 属性并且它没有值,null 那么Optional 将绑定一个空值。 |
|
---|---|
2.8.3. 启用@ConfigurationProperties 注释类型
Spring Boot 提供基础设施来绑定@ConfigurationProperties
类型并将它们注册为 beans。您可以逐个类地启用配置属性,也可以启用以类似于组件扫描的方式工作的配置属性扫描。
有时,带有注释的类@ConfigurationProperties
可能不适合扫描,例如,如果您正在开发自己的自动配置或者您希望有条件地启用它们。在这些情况下,使用注释指定要处理的类型列表@EnableConfigurationProperties
。这可以在任何类上完成@Configuration
,如以下示例所示:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {
}
@ConfigurationProperties("some.properties")
public class SomeProperties {
}
要使用配置属性扫描,请将@ConfigurationPropertiesScan
注释添加到您的应用程序。通常,它被添加到带有注释的主应用程序类中,@SpringBootApplication
但它可以添加到任何@Configuration
类中。默认情况下,将从声明注释的类的包中进行扫描。如果要定义要扫描的特定包,可以按照以下示例所示进行操作:
@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {
}
当@ConfigurationProperties 使用配置属性扫描或通过 注册 bean时@EnableConfigurationProperties ,bean 有一个约定名称:<prefix>-<fqn> ,其中是注释<prefix> 中指定的环境键前缀,是 bean 的完全限定名称。如果注释不提供任何前缀,则仅使用 bean 的完全限定名称。@ConfigurationProperties``<fqn> 假设在包中,上面例子com.example.app 的bean名字是.SomeProperties``some.properties-com.example.app.SomeProperties |
|
---|---|
我们建议@ConfigurationProperties
只处理环境,特别是不要从上下文中注入其他 beans。*Aware
对于极端情况,可以使用 setter 注入或框架提供的任何接口(例如EnvironmentAware
,如果您需要访问Environment
)。如果您仍想使用构造函数注入其他 bean,则配置属性 bean 必须注释@Component
并使用基于 JavaBean 的属性绑定。
2.8.4. 使用@ConfigurationProperties 注释的类型
这种配置方式特别适用于SpringApplication
外部 YAML 配置,如以下示例所示:
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
要使用@ConfigurationProperties
bean,您可以使用与任何其他 bean 相同的方式注入它们,如以下示例所示:
@Service
public class MyService {
private final MyProperties properties;
public MyService(MyProperties properties) {
this.properties = properties;
}
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
server.start();
// ...
}
// ...
}
使用@ConfigurationProperties 还可以让您生成元数据文件,IDE 可以使用这些文件为您自己的密钥提供自动完成功能。详见 附件。 |
|
---|---|
2.8.5. 第三方配置
除了用于@ConfigurationProperties
注释类之外,您还可以在公共@Bean
方法上使用它。当您想要将属性绑定到您无法控制的第三方组件时,这样做会特别有用。
要从Environment
属性配置 bean,请添加@ConfigurationProperties
到它的 bean 注册中,如以下示例所示:
@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {
@Bean
@ConfigurationProperties(prefix = "another")
public AnotherComponent anotherComponent() {
return new AnotherComponent();
}
}
使用前缀定义的任何 JavaBean 属性都以类似于前面示例的方式another
映射到该bean 。AnotherComponent``SomeProperties
2.8.6. 宽松的装订
Spring Boot 使用一些宽松的规则将Environment
属性绑定到bean,因此属性名称和 bean 属性名称@ConfigurationProperties
之间不需要完全匹配。Environment
这有用的常见示例包括破折号分隔的环境属性(例如,context-path
绑定到contextPath
)和大写的环境属性(例如,PORT
绑定到port
)。
例如,考虑以下@ConfigurationProperties
类:
@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
通过前面的代码,可以使用以下属性名称:
财产 | 笔记 |
---|---|
my.main-project.person.first-name |
烤肉盒,推荐用于.properties 和.yml 文件。 |
my.main-project.person.firstName |
标准的驼峰式大小写语法。 |
my.main-project.person.first_name |
下划线符号,这是用于.properties 和.yml 文件的替代格式。 |
MY_MAINPROJECT_PERSON_FIRSTNAME |
大写格式,在使用系统环境变量时推荐使用。 |
prefix 注释的值 必须采用kebab 大小写(小写并以 分隔- ,例如my.main-project.person )。 |
|
---|---|
财产来源 | 简单的 | 列表 |
---|---|---|
属性文件 | 骆驼大小写、烤肉串大小写或下划线符号 | [ ] 使用或逗号分隔值的标准列表语法 |
YAML 文件 | 骆驼大小写、烤肉串大小写或下划线符号 | 标准 YAML 列表语法或逗号分隔值 |
环境变量 | 下划线作为分隔符的大写格式(请参阅从环境变量绑定)。 | 下划线包围的数值(请参阅从环境变量绑定) |
系统属性 | 骆驼大小写、烤肉串大小写或下划线符号 | [ ] 使用或逗号分隔值的标准列表语法 |
我们建议尽可能以小写的 kebab 格式存储属性,例如my.person.first-name=Rod . |
|
---|---|
绑定地图
绑定到Map
属性时,您可能需要使用特殊的括号表示法,以便key
保留原始值。如果键未被 包围[]
,则任何非字母数字字符-
或.
将被删除。
例如,考虑将以下属性绑定到 a Map<String,String>
:
特性
山药
my.map.[/key1]=value1
my.map.[/key2]=value2
my.map./key3=value3
对于 YAML 文件,括号需要用引号引起来才能正确解析键。 | |
---|---|
上面的属性将绑定到一个Map
with /key1
, /key2
andkey3
作为地图中的键。斜线已被删除,key3
因为它没有被方括号包围。
绑定到标量值时,.
其中带有的键不需要用[]
. 标量值包括枚举和java.lang
包中除Object
. 绑定a.b=c
到Map<String, String>
将保留.
键中的并返回一个包含条目的映射{"a.b"="c"}
。对于任何其他类型,如果您包含key
一个.
. 例如,绑定a.b=c
到Map<String, Object>
将返回一个带有条目的映射{"a"={"b"="c"}}
,而[a.b]=c
将返回一个带有条目的映射{"a.b"="c"}
。
从环境变量绑定
大多数操作系统对可用于环境变量的名称施加了严格的规则。例如,Linux shell 变量只能包含字母(a
toz
或A
to Z
)、数字(0
to 9
)或下划线字符(_
)。按照惯例,Unix shell 变量的名称也将以大写形式显示。
Spring Boot 宽松的绑定规则,就是为了尽可能兼容这些命名限制而设计的。
要将规范形式的属性名称转换为环境变量名称,您可以遵循以下规则:
- 将点 (
.
) 替换为下划线 (_
)。 - 删除任何破折号 (
-
)。 - 转换为大写。
例如,配置属性spring.main.log-startup-info
将是一个名为 的环境变量SPRING_MAIN_LOGSTARTUPINFO
。
绑定到对象列表时也可以使用环境变量。要绑定到 a List
,元素编号应在变量名称中用下划线括起来。
例如,配置属性my.service[0].other
将使用名为 的环境变量MY_SERVICE_0_OTHER
。
2.8.7. 合并复杂类型
当列表在多个地方配置时,覆盖通过替换整个列表来工作。
例如,假设一个MyPojo
对象具有name
默认的description
属性null
。MyPojo
以下示例公开了来自 的对象列表MyProperties
:
@ConfigurationProperties("my")
public class MyProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
考虑以下配置:
特性
山药
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
如果dev
配置文件未激活,MyProperties.list
则包含一个MyPojo
条目,如先前定义的那样。但是,如果dev
配置文件已启用,则list
仍然只包含一个条目(名称为my another name
,描述为null
)。此配置不会将第二个MyPojo
实例添加到列表中,也不会合并项目。
当在多个配置文件中指定 a 时List
,将使用优先级最高的(并且只有那个)。考虑以下示例:
特性
山药
my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
在前面的示例中,如果dev
配置文件处于活动状态,MyProperties.list
则包含一个 MyPojo
条目(名称为my another name
,描述为null
)。对于 YAML,逗号分隔列表和 YAML 列表都可用于完全覆盖列表的内容。
对于Map
属性,您可以绑定从多个来源提取的属性值。但是,对于多个来源中的同一属性,将使用优先级最高的那个。以下示例公开了一个Map<String, MyPojo>
from MyProperties
:
@ConfigurationProperties("my")
public class MyProperties {
private final Map<String, MyPojo> map = new LinkedHashMap<>();
public Map<String, MyPojo> getMap() {
return this.map;
}
}
考虑以下配置:
特性
山药
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2
如果dev
配置文件未激活,MyProperties.map
则包含一个带键的条目key1
(名称为my name 1
,描述为my description 1
)。但是,如果dev
配置文件已启用,则map
包含两个条目,其中的键key1
(名称dev name 1
和描述为my description 1
)和key2
(名称dev name 2
和描述为dev description 2
)。
前面的合并规则适用于所有属性源的属性,而不仅仅是文件。 | |
---|---|
2.8.8. 属性转换
Spring Boot 尝试在绑定到 bean 时将外部应用程序属性强制转换为正确的类型@ConfigurationProperties
。如果您需要自定义类型转换,您可以提供一个ConversionService
bean(带有一个名为 的 bean conversionService
)或自定义属性编辑器(通过一个CustomEditorConfigurer
bean)或自定义Converters
(带有注释为 的 bean 定义@ConfigurationPropertiesBinding
)。
由于在应用程序生命周期的早期请求此 bean,请确保限制您ConversionService 正在使用的依赖项。通常,您需要的任何依赖项在创建时可能未完全初始化。如果配置键强制不需要它ConversionService 并且只依赖于符合@ConfigurationPropertiesBinding . |
|
---|---|
转换持续时间
Spring Boot 专门支持表达持续时间。如果公开java.time.Duration
属性,则应用程序属性中的以下格式可用:
- 常规
long
表示(使用毫秒作为默认单位,除非@DurationUnit
已指定 a) - 使用的标准 ISO-8601 格式
java.time.Duration
- 一种更易读的格式,其中值和单位耦合(
10s
表示 10 秒)
考虑以下示例:
@ConfigurationProperties("my")
public class MyProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
// getters / setters...
}
要指定 30 秒的会话超时,30
和PT30S
都是30s
等效的。可以使用以下任何形式指定 500 毫秒的读取超时:500
,PT0.5S
和500ms
。
您还可以使用任何受支持的单位。这些都是:
ns
纳秒us
微秒ms
几毫秒s
几秒钟m
几分钟h
用了几个小时d
好几天
默认单位是毫秒,可以使用@DurationUnit
上面示例中所示的方法覆盖。
如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
// fields...
public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
@DefaultValue("1000ms") Duration readTimeout) {
this.sessionTimeout = sessionTimeout;
this.readTimeout = readTimeout;
}
// getters...
}
如果要升级Long 属性,请确保定义单位(使用@DurationUnit )(如果不是毫秒)。这样做提供了一个透明的升级路径,同时支持更丰富的格式。 |
|
---|---|
转换期间
除了持续时间之外,Spring Boot 还可以使用java.time.Period
类型。应用程序属性中可以使用以下格式:
- 常规
int
表示(使用天作为默认单位,除非@PeriodUnit
已指定 a) - 使用的标准 ISO-8601 格式
java.time.Period
- 一种更简单的格式,其中值和单位对耦合(
1y3d
表示 1 年零 3 天)
简单格式支持以下单位:
y
多年m
几个月w
数周d
好几天
该java.time.Period 类型从不实际存储周数,它是表示“7 天”的快捷方式。 |
|
---|---|
转换数据大小
Spring Framework 有一个以DataSize
字节为单位表示大小的值类型。如果公开DataSize
属性,则应用程序属性中的以下格式可用:
- 常规
long
表示(使用字节作为默认单位,除非@DataSizeUnit
已指定 a) - 一种更易读的格式,其中值和单位耦合(
10MB
表示 10 兆字节)
考虑以下示例:
@ConfigurationProperties("my")
public class MyProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
// getters/setters...
}
指定缓冲区大小为 10 兆字节,10
并且10MB
是等效的。256 字节的大小阈值可以指定为256
或256B
。
您还可以使用任何受支持的单位。这些都是:
B
对于字节KB
千字节MB
兆字节GB
千兆字节TB
太字节
默认单位是字节,可以使用@DataSizeUnit
上面示例中所示的方法覆盖。
如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
// fields...
public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
@DefaultValue("512B") DataSize sizeThreshold) {
this.bufferSize = bufferSize;
this.sizeThreshold = sizeThreshold;
}
// getters...
}
如果要升级Long 属性,请确保定义单位(使用@DataSizeUnit )(如果它不是字节)。这样做提供了一个透明的升级路径,同时支持更丰富的格式。 |
|
---|---|
2.8.9. @ConfigurationProperties 验证
@ConfigurationProperties
每当使用 Spring 的注释对类进行注释时,Spring Boot 都会尝试验证类@Validated
。javax.validation
您可以直接在配置类上使用 JSR-303约束注释。为此,请确保您的类路径上有一个兼容的 JSR-303 实现,然后将约束注释添加到您的字段,如以下示例所示:
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
// getters/setters...
}
@Bean 您还可以通过注释创建配置属性的方法 来触发验证@Validated 。 |
|
---|---|
为确保始终为嵌套属性触发验证,即使未找到任何属性,关联的字段也必须用 注释@Valid
。以下示例建立在前面的MyProperties
示例之上:
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// getters/setters...
public static class Security {
@NotEmpty
private String username;
// getters/setters...
}
}
您还可以Validator
通过创建一个名为configurationPropertiesValidator
. @Bean
应声明该方法static
。配置属性验证器是在应用程序生命周期的早期创建的,将方法声明@Bean
为静态可以创建 bean,而无需实例化@Configuration
类。这样做可以避免早期实例化可能导致的任何问题。
该spring-boot-actuator 模块包含一个公开所有 bean 的端点@ConfigurationProperties 。将 Web 浏览器指向/actuator/configprops 或使用等效的 JMX 端点。有关详细信息,请参阅“生产就绪功能”部分。 |
|
---|---|
2.8.10。@ConfigurationProperties 与@Value
注解@Value
是一个核心容器特性,它不提供与类型安全配置属性相同的特性。@ConfigurationProperties
下表总结了和支持的功能@Value
:
特征 | @ConfigurationProperties |
@Value |
---|---|---|
松绑 | 是的 | 有限(见下面的注释) |
元数据支持 | 是的 | 不 |
SpEL 评估 |
不 | 是的 |
如果您确实想使用@Value ,我们建议您使用规范形式(仅使用小写字母的 kebab-case)来引用属性名称。这将允许 Spring Boot 使用与放松绑定 @ConfigurationProperties 时相同的逻辑。例如,将从文件以及系统环境中@Value("${demo.item-price}") 获取demo.item-price 和形成demo.itemPrice 表格。如果你改用了,就不会考虑了。application.properties``DEMO_ITEMPRICE``@Value("${demo.itemPrice}")``demo.item-price``DEMO_ITEMPRICE |
|
---|---|
如果您为自己的组件定义一组配置键,我们建议您将它们分组在一个 POJO 注释中@ConfigurationProperties
。这样做将为您提供结构化的、类型安全的对象,您可以将其注入到您自己的 bean 中。
SpEL
在解析这些文件和填充环境时,不会处理来自应用程序属性文件的表达式 。但是,可以SpEL
在@Value
. 如果应用程序属性文件中的属性值是一个SpEL
表达式,则在通过@Value
.
3.简介
Spring Profiles 提供了一种方法来隔离应用程序配置的各个部分,并使其仅在特定环境中可用。任何@Component
, @Configuration
or 都@ConfigurationProperties
可以@Profile
在加载时标上限制,如下例所示:
@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {
// ...
}
如果@ConfigurationProperties bean 是通过@EnableConfigurationProperties 而不是自动扫描注册的,则需要在具有注解的类@Profile 上指定注解。在扫描的情况下,可以在类本身上指定。 @Configuration``@EnableConfigurationProperties``@ConfigurationProperties``@Profile``@ConfigurationProperties |
|
---|---|
您可以使用spring.profiles.active
Environment
属性来指定哪些配置文件处于活动状态。您可以使用本章前面描述的任何方式指定属性。例如,您可以将其包含在您的 中application.properties
,如以下示例所示:
特性
山药
spring.profiles.active=dev,hsqldb
您还可以使用以下开关在命令行上指定它:--spring.profiles.active=dev,hsqldb
。
如果没有配置文件处于活动状态,则会启用默认配置文件。默认配置文件的名称是default
,可以使用spring.profiles.default
Environment
属性对其进行调整,如以下示例所示:
特性
山药
spring.profiles.default=none
spring.profiles.active`并且`spring.profiles.default`只能用于非配置文件特定的文档。这意味着它们不能包含在[配置](https://docs.spring.io/spring-boot/docs/2.7.10/reference/html/features.html#features.external-config.files.activation-properties)[文件特定文件](https://docs.spring.io/spring-boot/docs/2.7.10/reference/html/features.html#features.external-config.files.profile-specific)或由.`spring.config.activate.on-profile
例如第二个文件配置无效:
特性
山药
# this document is valid
spring.profiles.active=prod
#---
# this document is invalid
spring.config.activate.on-profile=prod
spring.profiles.active=metrics
3.1. 添加活动配置文件
该spring.profiles.active
属性遵循与其他属性相同的排序规则:最高者PropertySource
获胜。这意味着您可以在其中指定活动配置文件application.properties
,然后使用命令行开关替换它们。
有时,将属性添加到活动配置文件而不是替换它们很有用。该spring.profiles.include
属性可用于在属性激活的配置文件之上添加活动配置文件spring.profiles.active
。入口SpringApplication
点还有一个 Java API 用于设置额外的配置文件。请参阅SpringApplicationsetAdditionalProfiles()
中的方法。
例如,当运行具有以下属性的应用程序时,即使使用 --spring.profiles.active 开关运行,公共配置文件和本地配置文件也会被激活:
特性
山药
spring.profiles.include[0]=common
spring.profiles.include[1]=local
类似于spring.profiles.active ,spring.profiles.include 只能用于非配置文件特定的文档。这意味着它不能包含在由 .激活的配置文件特定文件或文档中。 spring.config.activate.on-profile |
|
---|---|
如果给定的配置文件处于活动状态,则下一部分中描述的配置文件组也可用于添加活动配置文件。
3.2. 配置文件组
有时,您在应用程序中定义和使用的配置文件过于细化,使用起来很麻烦。例如,您可能拥有proddb
用于prodmq
独立启用数据库和消息传递功能的配置文件。
为此,Spring Boot 允许您定义配置文件组。配置文件组允许您为相关的配置文件组定义逻辑名称。
例如,我们可以创建一个由我们的和配置文件production
组成的组。proddb``prodmq
特性
山药
spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq
现在可以开始使用我们的应用程序--spring.profiles.active=production
来激活production
,proddb
和prodmq
配置文件。
3.3. 以编程方式设置配置文件
SpringApplication.setAdditionalProfiles(…)
您可以通过在应用程序运行之前调用以编程方式设置活动配置文件。也可以通过使用 Spring 的ConfigurableEnvironment
接口来激活配置文件。
3.4. 配置文件特定的配置文件
通过引用的application.properties
(或) 和文件的特定配置文件变体被视为文件并加载。有关详细信息,请参阅“配置文件特定文件”。application.yml``@ConfigurationProperties
4.日志记录
Spring Boot 将Commons Logging用于所有内部日志记录,但将底层日志实现保持打开状态。为Java Util Logging、Log4J2和Logback提供了默认配置。在每种情况下,记录器都预先配置为使用控制台输出,同时还提供可选的文件输出。
默认情况下,如果您使用“Starters”,Logback 用于日志记录。还包括适当的 Logback 路由,以确保使用 Java Util Logging、Commons Logging、Log4J 或 SLF4J 的依赖库都能正常工作。
有很多可用于 Java 的日志记录框架。如果上面的列表看起来令人困惑,请不要担心。通常,您不需要更改日志记录依赖项,Spring Boot 默认设置就可以正常工作。 | |
---|---|
将应用程序部署到 servlet 容器或应用程序服务器时,使用 Java Util Logging API 执行的日志记录不会路由到应用程序的日志中。这可以防止由容器或已部署到它的其他应用程序执行的日志记录出现在您的应用程序日志中。 | |
---|---|
4.1. 日志格式
Spring Boot 的默认日志输出类似于以下示例:
2023-03-23 08:14:12.786 INFO 17119 --- [main] osbdfsMyApplication:在 PID 为 17119 的 myhost 上使用 Java 1.8.0_362 启动 MyApplication(/opt/apps/myapp.jar 由 myuser 在 /opt/apps/ 中启动)
2023-03-23 08:14:12.791 INFO 17119 --- [main] osbdfsMyApplication:未设置活动配置文件,回落到 1 个默认配置文件:“默认”
2023-03-23 08:14:14.729 INFO 17119 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 初始化端口:8080 (http)
2023-03-23 08:14:14.740 INFO 17119 --- [main] o.apache.catalina.core.StandardService:启动服务 [Tomcat]
2023-03-23 08:14:14.741 INFO 17119 --- [main] org.apache.catalina.core.StandardEngine:启动 Servlet 引擎:[Apache Tomcat/9.0.73]
2023-03-23 08:14:14.824 INFO 17119 --- [main] oaccC[Tomcat].[localhost].[/]:初始化 Spring 嵌入式 WebApplicationContext
2023-03-23 08:14:14.824 INFO 17119 --- [main] wscServletWebServerApplicationContext:Root WebApplicationContext:初始化在 1939 毫秒内完成
2023-03-23 08:14:15.444 INFO 17119 --- [main] osbwembedded.tomcat.TomcatWebServer:Tomcat 在端口上启动:8080 (http),上下文路径为“”
2023-03-23 08:14:15.456 INFO 17119 --- [main] osbdfsMyApplication:在 4.097 秒内启动 MyApplication(JVM 运行时间为 4.769)
2023-03-23 08:14:15.469 INFO 17119 --- [ionShutdownHook] o.apache.catalina.core.StandardService:停止服务 [Tomcat]
输出以下项目:
- 日期和时间:毫秒精度且易于排序。
- 日志级别:
ERROR
、WARN
、INFO
、DEBUG
或TRACE
。 - 进程标识。
---
用于区分实际日志消息开始的分隔符。- 线程名称:括在方括号中(对于控制台输出可能会被截断)。
- 记录器名称:这通常是源类名称(通常缩写)。
- 日志消息。
Logback 没有FATAL 级别。它映射到ERROR . |
|
---|---|
4.2. 控制台输出
默认日志配置在写入消息时将消息回显到控制台。默认情况下,记录ERROR
-level、WARN
-level 和-level 消息。INFO
您还可以通过使用标志启动应用程序来启用“调试”模式--debug
。
$ java -jar myapp.jar --debug
您也可以debug=true 在您的application.properties . |
|
---|---|
当启用调试模式时,选择的核心记录器(嵌入式容器、Hibernate 和 Spring Boot)被配置为输出更多信息。启用调试模式不会将您的应用程序配置为记录所有DEBUG
级别的消息。
--trace
或者,您可以通过使用标志(或trace=true
在您的)中启动您的应用程序来启用“跟踪”模式application.properties
。这样做可以为选定的核心记录器(嵌入式容器、Hibernate 模式生成和整个 Spring 产品组合)启用跟踪日志记录。
4.2.1. 颜色编码输出
如果您的终端支持 ANSI,则使用颜色输出来提高可读性。您可以设置spring.output.ansi.enabled
为受支持的值以覆盖自动检测。
颜色编码是使用%clr
转换字配置的。在其最简单的形式中,转换器根据日志级别为输出着色,如以下示例所示:
%clr(%5p)
下表描述了日志级别到颜色的映射:
等级 | 颜色 |
---|---|
FATAL |
红色的 |
ERROR |
红色的 |
WARN |
黄色的 |
INFO |
绿色的 |
DEBUG |
绿色的 |
TRACE |
绿色的 |
或者,您可以通过将其作为转换选项提供来指定应使用的颜色或样式。例如,要使文本变为黄色,请使用以下设置:
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
支持以下颜色和样式:
blue
cyan
faint
green
magenta
red
yellow
4.3. 文件输出
默认情况下,Spring Boot 只记录到控制台,不写入日志文件。如果除了控制台输出之外还想写入日志文件,则需要设置一个logging.file.name
或logging.file.path
属性(例如,在您的application.properties
.
下表显示了如何logging.*
一起使用这些属性:
logging.file.name |
logging.file.path |
例子 | 描述 |
---|---|---|---|
(没有任何) | (没有任何) | 仅控制台日志记录。 | |
具体文件 | (没有任何) | my.log |
写入指定的日志文件。名称可以是确切位置或相对于当前目录。 |
(没有任何) | 具体目录 | /var/log |
写入spring.log 指定目录。名称可以是确切位置或相对于当前目录。 |
日志文件在达到 10 MB 时会轮换,并且与控制台输出一样,默认情况下会记录ERROR
-level、WARN
-level 和-level 消息。INFO
日志记录属性独立于实际的日志记录基础设施。因此,特定的配置键(例如logback.configurationFile Logback)不由 spring Boot 管理。 |
|
---|---|
4.4. 文件轮换
如果您使用的是 Logback,则可以使用您的application.properties
或application.yaml
文件微调日志轮换设置。对于所有其他日志系统,您将需要自己直接配置轮换设置(例如,如果您使用 Log4J2,那么您可以添加一个log4j2.xml
或log4j2-spring.xml
文件)。
支持以下旋转策略属性:
姓名 | 描述 |
---|---|
logging.logback.rollingpolicy.file-name-pattern |
用于创建日志存档的文件名模式。 |
logging.logback.rollingpolicy.clean-history-on-start |
应用程序启动时是否应进行日志归档清理。 |
logging.logback.rollingpolicy.max-file-size |
归档前日志文件的最大大小。 |
logging.logback.rollingpolicy.total-size-cap |
日志存档在被删除之前可以占用的最大大小。 |
logging.logback.rollingpolicy.max-history |
要保留的归档日志文件的最大数量(默认为 7)。 |
4.5. 日志级别
所有支持的日志记录系统都可以在 Spring 中设置记录器级别Environment
(例如,在 中),方法是application.properties
使用TRACE、DEBUG、INFO、WARN、ERROR、FATAL 或 OFF 之一。记录器可以通过使用来配置。logging.level.<logger-name>=<level>``level``root``logging.level.root
以下示例显示了潜在的日志记录设置application.properties
:
特性
山药
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
也可以使用环境变量设置日志级别。例如,LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG
将设置org.springframework.web
为DEBUG
。
上述方法仅适用于包级别的日志记录。由于宽松绑定总是将环境变量转换为小写,因此不可能以这种方式为单个类配置日志记录。如果需要为类配置日志记录,可以使用变量SPRING_APPLICATION_JSON 。 |
|
---|---|
4.6. 日志组
将相关的记录器分组在一起通常很有用,这样它们就可以同时配置。例如,您可能经常更改所有与Tomcat 相关的记录器的日志记录级别,但您不能轻易记住顶级包。
为了解决这个问题,Spring Boot 允许您在 Spring 中定义日志记录组Environment
。例如,您可以通过将“tomcat”组添加到您的 来定义它application.properties
:
特性
山药
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
定义后,您可以使用一行更改组中所有记录器的级别:
特性
山药
logging.level.tomcat=trace
Spring Boot 包括以下可以开箱即用的预定义日志记录组:
姓名 | 伐木工 |
---|---|
网络 | org.springframework.core.codec , org.springframework.http , org.springframework.web , org.springframework.boot.actuate.endpoint.web ,org.springframework.boot.web.servlet.ServletContextInitializerBeans |
数据库 | org.springframework.jdbc.core , org.hibernate.SQL ,org.jooq.tools.LoggerListener |
4.7. 使用日志关闭挂钩
为了在您的应用程序终止时释放日志记录资源,提供了一个关闭挂钩,该挂钩将在 JVM 退出时触发日志系统清理。除非您的应用程序部署为 war 文件,否则此关闭挂钩会自动注册。如果您的应用程序具有复杂的上下文层次结构,则关闭挂钩可能无法满足您的需求。如果没有,请禁用关闭挂钩并调查底层日志系统直接提供的选项。例如,Logback 提供上下文选择器,允许每个 Logger 在其自己的上下文中创建。您可以使用该logging.register-shutdown-hook
属性来禁用关闭挂钩。将其设置为false
将禁用注册。application.properties
您可以在您的或文件中设置属性application.yaml
:
特性
山药
logging.register-shutdown-hook=false
4.8. 自定义日志配置
Environment
可以通过在类路径中包含适当的库来激活各种日志记录系统,并且可以通过在类路径的根目录或以下 Spring属性指定的位置提供合适的配置文件来进一步自定义:logging.config
。
您可以通过使用系统属性强制 Spring Boot 使用特定的日志记录系统org.springframework.boot.logging.LoggingSystem
。该值应该是实现的完全限定类名LoggingSystem
。您还可以使用 . 值完全禁用 Spring Boot 的日志记录配置none
。
由于日志记录是在创建之前初始化的,因此ApplicationContext 无法从@PropertySources Spring@Configuration 文件中控制日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。 |
|
---|---|
根据您的日志系统,将加载以下文件:
记录系统 | 客制化 |
---|---|
登录 | logback-spring.xml 、logback-spring.groovy 、logback.xml 或logback.groovy |
Log4j2 | log4j2-spring.xml 或者log4j2.xml |
JDK(Java Util 日志记录) | logging.properties |
如果可能,我们建议您-spring 为日志记录配置使用变体(例如,logback-spring.xml 而不是logback.xml )。如果使用标准配置位置,Spring 无法完全控制日志初始化。 |
|
---|---|
Java Util Logging 存在已知的类加载问题,当从“可执行 jar”运行时会导致问题。我们建议您在从“可执行 jar”运行时尽可能避免使用它。 | |
---|---|
为了帮助定制,一些其他属性从 Spring 转移Environment
到系统属性,如下表所述:
春季环境 | 系统属性 | 评论 |
---|---|---|
logging.exception-conversion-word |
LOG_EXCEPTION_CONVERSION_WORD |
记录异常时使用的转换词。 |
logging.file.name |
LOG_FILE |
如果已定义,它将用于默认日志配置。 |
logging.file.path |
LOG_PATH |
如果已定义,它将用于默认日志配置。 |
logging.pattern.console |
CONSOLE_LOG_PATTERN |
在控制台 (stdout) 上使用的日志模式。 |
logging.pattern.dateformat |
LOG_DATEFORMAT_PATTERN |
日志日期格式的附加程序模式。 |
logging.charset.console |
CONSOLE_LOG_CHARSET |
用于控制台日志记录的字符集。 |
logging.pattern.file |
FILE_LOG_PATTERN |
在文件中使用的日志模式(如果LOG_FILE 启用)。 |
logging.charset.file |
FILE_LOG_CHARSET |
用于文件日志记录的字符集(如果LOG_FILE 启用)。 |
logging.pattern.level |
LOG_LEVEL_PATTERN |
呈现日志级别时使用的格式(默认值%5p )。 |
PID |
PID |
当前进程 ID(如果可能并且在尚未定义为操作系统环境变量时发现)。 |
如果您使用 Logback,还会传输以下属性:
春季环境 | 系统属性 | 评论 |
---|---|---|
logging.logback.rollingpolicy.file-name-pattern |
LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN |
滚动日志文件名的模式(默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz )。 |
logging.logback.rollingpolicy.clean-history-on-start |
LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START |
是否在启动时清理归档日志文件。 |
logging.logback.rollingpolicy.max-file-size |
LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE |
最大日志文件大小。 |
logging.logback.rollingpolicy.total-size-cap |
LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP |
要保留的日志备份的总大小。 |
logging.logback.rollingpolicy.max-history |
LOGBACK_ROLLINGPOLICY_MAX_HISTORY |
要保留的归档日志文件的最大数量。 |
所有受支持的日志系统在解析其配置文件时都可以查询系统属性。spring-boot.jar
有关示例,请参见中的默认配置:
如果你想在日志属性中使用占位符,你应该使用Spring Boot 的语法而不是底层框架的语法。值得注意的是,如果你使用 Logback,你应该使用: 作为属性名称和它的默认值之间的分隔符,而不是使用:- . |
|
---|---|
LOG_LEVEL_PATTERN 您可以通过仅覆盖(或logging.pattern.level 使用 Logback)将 MDC 和其他临时内容添加到日志行。例如,如果您使用logging.pattern.level=user:%X{user} %5p ,则默认日志格式包含“用户”的 MDC 条目(如果存在),如以下示例所示。2019-08-30 12:30:04.031 用户:某人信息 22174 --- [nio-8080-exec-0] demo.Controller 处理经过身份验证的请求 |
|
---|---|
4.9. 登录扩展
Spring Boot 包含许多对 Logback 的扩展,可以帮助进行高级配置。您可以在配置文件中使用这些扩展logback-spring.xml
。
因为标准logback.xml 配置文件加载的太早,你不能在里面使用扩展。您需要使用logback-spring.xml 或定义logging.config 属性。 |
|
---|---|
这些扩展不能与 Logback 的配置扫描 一起使用。如果您尝试这样做,对配置文件进行更改会导致记录类似于以下内容之一的错误: | |
---|---|
ch.qos.logback.core.joran.spi.Interpreter@4中的错误:71 - [springProperty] 没有适用的操作,当前 ElementPath 是 [[configuration][springProperty]]ch.qos.logback.core.joran.spi.Interpreter@4
中的错误:71 - [springProfile] 没有适用的操作,当前 ElementPath 是 [[configuration][springProfile]]
4.9.1. 配置文件特定的配置
该<springProfile>
标记允许您根据活动的 Spring 配置文件选择性地包含或排除配置部分。元素内的任何位置都支持配置文件部分<configuration>
。使用该name
属性指定哪个配置文件接受配置。标记<springProfile>
可以包含配置文件名称(例如staging
)或配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑,例如production & (eu-central | eu-west)
。查看参考指南了解更多详情。以下清单显示了三个示例配置文件:
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
<springProfile name="dev | staging">
<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>
<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
4.9.2. 环境属性
该<springProperty>
标记允许您公开 Spring 的属性Environment
以在 Logback 中使用。application.properties
如果您想在 Logback 配置中访问文件中的值,这样做会很有用。该标签的工作方式与 Logback 的标准标签类似<property>
。但是,您不是直接指定value
,而是指定source
属性的 (来自Environment
)。如果您需要将属性存储在local
作用域之外的其他地方,您可以使用scope
属性。如果您需要一个回退值(以防该属性未在 中设置Environment
),您可以使用该defaultValue
属性。以下示例显示了如何公开在 Logback 中使用的属性:
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
必须source 在 kebab 大小写中指定(例如my.property-name )。Environment 但是,可以使用宽松的规则 将属性添加到。 |
|
---|---|
5、国际化
Spring Boot 支持本地化消息,因此您的应用程序可以迎合不同语言偏好的用户。messages
默认情况下,Spring Boot在类路径的根目录中查找资源包是否存在。
当已配置资源包的默认属性文件可用时(messages.properties 默认情况下),自动配置适用。如果您的资源包仅包含特定于语言的属性文件,则您需要添加默认值。如果找不到与任何配置的基本名称匹配的属性文件,则不会有自动配置的MessageSource . |
|
---|---|
资源包的基本名称以及其他几个属性可以使用spring.messages
命名空间进行配置,如以下示例所示:
特性
山药
spring.messages.basename=messages,config.i18n.messages
spring.messages.fallback-to-system-locale=false
spring.messages.basename 支持以逗号分隔的位置列表,可以是包限定符或从类路径根解析的资源。 |
|
---|---|
MessageSourceProperties
有关更多支持的选项,请参阅。
6. JSON
Spring Boot 提供与三个 JSON 映射库的集成:
- 格森
- 杰克逊
- JSON-B
Jackson 是首选的默认库。
6.1. 杰克逊
提供了 Jackson 的自动配置,Jackson 是spring-boot-starter-json
. 当 Jackson 在类路径上时,ObjectMapper
会自动配置一个 bean。提供了几个配置属性来自定义ObjectMapper
.
6.1.1. 自定义序列化器和反序列化器
如果您使用 Jackson 序列化和反序列化 JSON 数据,您可能想要编写自己的JsonSerializer
和JsonDeserializer
类。自定义序列化器通常通过模块向 Jackson 注册,但 Spring Boot 提供了另一种@JsonComponent
注解,可以更轻松地直接注册 Spring Beans。
您可以@JsonComponent
直接在JsonSerializer
或JsonDeserializer
实现上使用注解KeyDeserializer
。您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonSerializer<MyObject> {
@Override
public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
jgen.writeStartObject();
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
jgen.writeEndObject();
}
}
public static class Deserializer extends JsonDeserializer<MyObject> {
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
return new MyObject(name, age);
}
}
}
@JsonComponent
中的所有beanApplicationContext
都会自动向 Jackson 注册。因为@JsonComponent
是元注释的@Component
,所以适用通常的组件扫描规则。
Spring Boot 还提供JsonObjectSerializer
和JsonObjectDeserializer
基类,这些类在序列化对象时提供标准 Jackson 版本的有用替代方案。有关详细信息,请参阅Javadoc 中的JsonObjectSerializer
和。JsonObjectDeserializer
上面的例子可以重写为使用JsonObjectSerializer
/JsonObjectDeserializer
如下:
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonObjectSerializer<MyObject> {
@Override
protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
public static class Deserializer extends JsonObjectDeserializer<MyObject> {
@Override
protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
JsonNode tree) throws IOException {
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new MyObject(name, age);
}
}
}
6.1.2. 混入
Jackson 支持 mixin,可用于将附加注释混合到已在目标类上声明的注释中。Spring Boot 的 Jackson 自动配置将扫描您的应用程序包以查找带有注释的类,@JsonMixin
并将它们注册到自动配置的ObjectMapper
. 注册由 Spring Boot 执行JsonMixinModule
。
6.2. 格森
提供了 Gson 的自动配置。当 Gson 在类路径上时,Gson
会自动配置一个 bean。提供了几个spring.gson.*
配置属性用于自定义配置。要获得更多控制,GsonBuilderCustomizer
可以使用一个或多个 bean。
6.3. JSON-B
提供了 JSON-B 的自动配置。当 JSON-B API 和实现在类路径上时,Jsonb
将自动配置一个 bean。首选的 JSON-B 实现是 Apache Johnzon,它提供了依赖管理。
七、任务执行与调度
Executor
在上下文中没有 bean的情况下,Spring Boot 会自动配置一个ThreadPoolTaskExecutor
合理的默认值,这些默认值可以自动关联到异步任务执行 ( @EnableAsync
) 和 Spring MVC 异步请求处理。
Executor 如果您在上下文中定义了自定义项,常规任务执行(即@EnableAsync )将透明地使用它,但不会配置 Spring MVC 支持,因为它需要一个AsyncTaskExecutor 实现(名为applicationTaskExecutor )。根据您的目标安排,您可以将您的更改Executor 为 aThreadPoolTaskExecutor 或同时定义 aThreadPoolTaskExecutor 和 anAsyncConfigurer 来包装您的自定义Executor .自动配置TaskExecutorBuilder 允许您轻松创建实例来重现默认情况下自动配置的功能。 |
|
---|---|
线程池使用8个核心线程,可以根据负载增长和收缩。可以使用命名空间对这些默认设置进行微调spring.task.execution
,如以下示例所示:
特性
山药
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
这会将线程池更改为使用有界队列,以便当队列已满(100 个任务)时,线程池增加到最多 16 个线程。当线程空闲 10 秒(而不是默认情况下的 60 秒)时,线程会被回收,因此池的收缩更为激进。
ThreadPoolTaskScheduler
如果需要关联到计划任务执行(@EnableScheduling
例如使用),也可以自动配置。线程池默认使用一个线程,其设置可以使用命名空间进行微调spring.task.scheduling
,如下例所示:
特性
山药
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
TaskExecutorBuilder
如果需要创建自定义执行程序或调度程序,bean 和bean都TaskSchedulerBuilder
可以在上下文中使用。
8. 测试
Spring Boot 提供了许多实用程序和注释来帮助测试您的应用程序。测试支持由两个模块提供:spring-boot-test
包含核心项目,并spring-boot-test-autoconfigure
支持测试的自动配置。
大多数开发人员使用spring-boot-starter-test
“Starter”,它导入 Spring Boot 测试模块以及 JUnit Jupiter、AssertJ、Hamcrest 和许多其他有用的库。
如果您有使用 JUnit 4 的测试,则可以使用 JUnit 5 的老式引擎来运行它们。要使用 vintage 引擎,请添加对 的依赖项junit-vintage-engine ,如以下示例所示:<dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> |
|
---|---|
hamcrest-core
被排除在外org.hamcrest:hamcrest
是 的一部分spring-boot-starter-test
。
8.1. 测试范围依赖
“ Starter spring-boot-starter-test
”(在 中test
scope
)包含以下提供的库:
- JUnit 5:单元测试 Java 应用程序的实际标准。
- Spring Test & Spring Boot Test:对 Spring Boot 应用程序的实用程序和集成测试支持。
- AssertJ:一个流畅的断言库。
- Hamcrest:匹配器对象库(也称为约束或谓词)。
- Mockito:一个 Java 模拟框架。
- JSONassert:JSON 的断言库。
- JsonPath:JSON 的 XPath。
我们通常会发现这些公共库在编写测试时很有用。如果这些库不适合您的需要,您可以添加自己的额外测试依赖项。
8.2. 测试 Spring 应用程序
依赖注入的主要优点之一是它应该使您的代码更容易进行单元测试。您甚至可以在不涉及 Spring 的情况下使用运算符实例化对象new
。您还可以使用模拟对象而不是真正的依赖项。
通常,您需要超越单元测试并开始集成测试(使用 Spring ApplicationContext
)。能够执行集成测试而不需要部署应用程序或连接到其他基础设施是很有用的。
Spring Framework 包含一个专门用于此类集成测试的测试模块。您可以直接声明依赖项org.springframework:spring-test
或使用spring-boot-starter-test
“Starter”以传递方式将其拉入。
如果您以前没有使用过该spring-test
模块,您应该先阅读Spring Framework 参考文档的相关部分。
8.3. 测试 Spring Boot 应用程序
Spring Boot 应用程序是一个 Spring ApplicationContext
,因此除了通常使用 vanilla Spring 上下文所做的之外,无需做任何特别的事情来测试它。
Spring Boot 的外部属性、日志记录和其他功能默认情况下安装在上下文中,只有当您使用SpringApplication 它来创建它时。 |
|
---|---|
Spring Boot 提供了一个@SpringBootTest
注解,当你需要 Spring Boot 的特性时,它可以作为标准spring-test
@ContextConfiguration
注解的替代。注释通过创建ApplicationContext
在您的测试中使用的 来SpringApplication
工作。除了@SpringBootTest
许多其他注释之外,还提供了用于测试应用程序的更具体部分的注释。
如果您使用的是 JUnit 4,请不要忘记也添加@RunWith(SpringRunner.class) 到您的测试中,否则注释将被忽略。如果您使用的是 JUnit 5,则无需添加等效的@ExtendWith(SpringExtension.class) as@SpringBootTest 并且其他@…Test 注释已使用它进行注释。 |
|
---|---|
默认情况下,@SpringBootTest
不会启动服务器。您可以使用的webEnvironment
属性@SpringBootTest
进一步优化测试的运行方式:
MOCK
(默认):加载网络ApplicationContext
并提供模拟网络环境。使用此注释时不会启动嵌入式服务器。如果您的类路径上没有可用的 Web 环境,此模式会透明地回退到创建常规的非 WebApplicationContext
. 它可以与您的 Web 应用程序结合使用@AutoConfigureMockMvc
或@AutoConfigureWebTestClient
用于基于模拟的测试。RANDOM_PORT
: 加载WebServerApplicationContext
并提供真实的网络环境。嵌入式服务器启动并侦听随机端口。DEFINED_PORT
: 加载WebServerApplicationContext
并提供真实的网络环境。嵌入式服务器启动并侦听定义的端口(来自您的application.properties
)或默认端口8080
。NONE``ApplicationContext
:通过使用加载SpringApplication
但不提供任何网络环境(模拟或其他)。
如果您的测试是@Transactional ,默认情况下它会在每个测试方法结束时回滚事务。然而,由于将这种安排与 eitherRANDOM_PORT 或DEFINED_PORT implicitly 一起使用提供了一个真正的 servlet 环境,因此 HTTP 客户端和服务器在单独的线程中运行,因此在单独的事务中运行。在这种情况下,服务器上发起的任何事务都不会回滚。 |
|
---|---|
@SpringBootTest 如果您的应用程序为管理服务器使用不同的端口, withwebEnvironment = WebEnvironment.RANDOM_PORT 还将在单独的随机端口上启动管理服务器。 |
|
---|---|
8.3.1. 检测 Web 应用程序类型
如果 Spring MVC 可用,则会配置常规的基于 MVC 的应用程序上下文。如果您只有 Spring WebFlux,我们将检测到它并配置一个基于 WebFlux 的应用程序上下文。
如果两者都存在,则 Spring MVC 优先。如果要在这种情况下测试响应式 Web 应用程序,则必须设置属性spring.main.web-application-type
:
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {
// ...
}
8.3.2. 检测测试配置
如果您熟悉 Spring 测试框架,您可能习惯于使用@ContextConfiguration(classes=…)
order 来指定@Configuration
加载哪个 Spring。或者,您可能经常@Configuration
在测试中使用嵌套类。
在测试 Spring Boot 应用程序时,通常不需要这样做。@*Test
只要您没有明确定义,Spring Boot 的注解就会自动搜索您的主要配置。
@SpringBootApplication
搜索算法从包含测试的包开始工作,直到找到用或注释的类@SpringBootConfiguration
。只要您以合理的方式构建代码,通常就能找到您的主要配置。
如果您使用测试注释来测试应用程序的更具体的部分,则应避免在main 方法的应用程序类上添加特定于特定区域的配置设置。定义的底层组件扫描配置@SpringBootApplication 排除了用于确保切片按预期工作的过滤器。@ComponentScan 如果您在带 -annotated 的类上使用显式指令@SpringBootApplication ,请注意这些过滤器将被禁用。如果你正在使用切片,你应该重新定义它们。 |
|
---|---|
如果要自定义主要配置,可以使用嵌套@TestConfiguration
类。与嵌套@Configuration
类不同,嵌套类将用于代替应用程序的主要配置,嵌套@TestConfiguration
类是在应用程序的主要配置之外使用的。
Spring 的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论它是如何被发现的),加载上下文的潜在耗时过程只会发生一次。 | |
---|---|
8.3.3. 排除测试配置
如果您的应用程序使用组件扫描(例如,如果您使用@SpringBootApplication
或@ComponentScan
),您可能会发现您仅为特定测试创建的顶级配置类会意外地随处可见。
正如我们之前看到的,@TestConfiguration
可以在测试的内部类上使用来自定义主要配置。当放置在顶级类上时,表示不应通过扫描拾取@TestConfiguration
类中的类。src/test/java
然后,您可以在需要的地方显式导入该类,如以下示例所示:
@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {
@Test
void exampleTest() {
// ...
}
}
如果您直接使用@ComponentScan (即不通过@SpringBootApplication ),则需要向其注册TypeExcludeFilter 。有关详细信息, 请参阅Javadoc 。 |
|
---|---|
8.3.4. 使用应用程序参数
如果您的应用程序需要arguments,您可以@SpringBootTest
使用属性注入它们args
。
@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {
@Test
void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
assertThat(args.getOptionNames()).containsOnly("app.test");
assertThat(args.getOptionValues("app.test")).containsOnly("one");
}
}
8.3.5. 使用模拟环境进行测试
默认情况下,@SpringBootTest
不启动服务器,而是设置用于测试 Web 端点的模拟环境。
MockMvc
使用 Spring MVC,我们可以使用or查询我们的 Web 端点WebTestClient
,如以下示例所示:
@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {
@Test
void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
}
// If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient
@Test
void testWithWebTestClient(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
如果您只想关注 web 层而不是开始一个完整的ApplicationContext ,请考虑使用@WebMvcTest . |
|
---|---|
使用 Spring WebFlux 端点,您可以使用WebTestClient
如下示例所示:
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
在模拟环境中进行测试通常比在完整的 servlet 容器中运行要快。但是,由于模拟发生在 Spring MVC 层,依赖于较低级别 servlet 容器行为的代码无法直接使用 MockMvc 进行测试。例如,Spring Boot 的错误处理是基于 servlet 容器提供的“错误页面”支持。这意味着,虽然您可以测试 MVC 层抛出并按预期处理异常,但您无法直接测试特定的自定义错误页面是否已呈现。如果您需要测试这些较低级别的问题,您可以启动一个完全运行的服务器,如下一节所述。 | |
---|---|
8.3.6. 使用正在运行的服务器进行测试
如果您需要启动一个完整运行的服务器,我们建议您使用随机端口。如果您使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
,每次测试运行时都会随机选择一个可用端口。
注释@LocalServerPort
可用于将实际使用的端口注入到您的测试中。为方便起见,需要对启动的服务器进行 REST 调用的测试可以额外使用@Autowire
,WebTestClient
它解析到正在运行的服务器的相关链接,并带有用于验证响应的专用 API,如以下示例所示:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
WebTestClient 可用于实时服务器和模拟环境。 |
|
---|---|
此设置需要spring-webflux
类路径。如果你不能或不会添加 webflux,Spring Boot 也提供了一个TestRestTemplate
工具:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
String body = restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
8.3.7. 自定义 WebTestClient
要自定义WebTestClient
bean,请配置一个WebTestClientBuilderCustomizer
bean。任何此类 bean 都使用用于WebTestClient.Builder
创建WebTestClient
.
8.3.8. 使用 JMX
由于测试上下文框架缓存上下文,默认情况下禁用 JMX 以防止相同的组件在同一域上注册。如果此类测试需要访问MBeanServer
,请考虑将其标记为脏:
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {
@Autowired
private MBeanServer mBeanServer;
@Test
void exampleTest() {
assertThat(this.mBeanServer.getDomains()).contains("java.lang");
// ...
}
}
8.3.9. 使用指标
无论您的类路径如何,仪表注册表(内存中支持的除外)在使用@SpringBootTest
.
如果您需要将指标导出到不同的后端作为集成测试的一部分,请使用@AutoConfigureMetrics
.
8.3.10。模拟和间谍豆
运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能有一些在开发期间不可用的远程服务的外观。当您想要模拟在真实环境中可能难以触发的故障时,模拟也很有用。
Spring Boot 包含一个@MockBean
注释,可用于为您的ApplicationContext
. 您可以使用注释来添加新的 bean 或替换单个现有的 bean 定义。注释可以直接用于测试类、测试中的字段或@Configuration
类和字段。当在一个字段上使用时,创建的 mock 的实例也会被注入。模拟 bean 在每个测试方法后自动重置。
如果您的测试使用了 Spring Boot 的测试注释之一(例如@SpringBootTest ),则会自动启用此功能。要以不同的安排使用此功能,必须显式添加侦听器,如以下示例所示:爪哇科特林@ContextConfiguration(classes = MyConfig.class) @TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class }) class MyTests { // ... } |
|
---|---|
以下示例将现有的RemoteService
bean 替换为模拟实现:
@SpringBootTest
class MyTests {
@Autowired
private Reverser reverser;
@MockBean
private RemoteService remoteService;
@Test
void exampleTest() {
given(this.remoteService.getValue()).willReturn("spring");
String reverse = this.reverser.getReverseValue(); // Calls injected RemoteService
assertThat(reverse).isEqualTo("gnirps");
}
}
@MockBean 不能用于模拟在应用程序上下文刷新期间执行的 bean 的行为。执行测试时,应用程序上下文刷新已完成,配置模拟行为为时已晚。在这种情况下,我们建议使用一种@Bean 方法来创建和配置模拟。 |
|
---|---|
此外,您可以使用@SpyBean
Mockito 包装任何现有的 bean spy
。有关详细信息,请参阅Javadoc 。
CGLib 代理,例如为作用域 bean 创建的代理,将代理方法声明为final . 这会阻止 Mockito 正常运行,因为它无法模拟或监视final 其默认配置中的方法。如果您想模拟或监视这样的 bean,请将 Mockito 配置为通过添加到org.mockito:mockito-inline 您的应用程序的测试依赖项来使用其内联模拟制造商。这允许 Mockito 模拟和监视final 方法。 |
|
---|---|
虽然 Spring 的测试框架在测试之间缓存应用程序上下文并为共享相同配置的测试重用上下文,但使用@MockBean 或@SpyBean 影响缓存键很可能会增加上下文的数量。 |
|
---|---|
如果您使用通过名称引用参数的方法@SpyBean 来监视 bean @Cacheable ,则您的应用程序必须使用-parameters . 这确保一旦侦测到 bean,参数名称就可用于缓存基础结构。 |
|
---|---|
当您用于@SpyBean 监视由 Spring 代理的 bean 时,您可能需要在某些情况下删除 Spring 的代理,例如在使用given or设置期望时when 。用于AopTestUtils.getTargetObject(yourProxiedSpy) 这样做。 |
|
---|---|
8.3.11。自动配置测试
Spring Boot 的自动配置系统适用于应用程序,但有时对测试来说有点过分。它通常有助于仅加载测试应用程序“切片”所需的配置部分。例如,您可能想测试 Spring MVC 控制器是否正确映射 URL,并且您不想在这些测试中涉及数据库调用,或者您可能想测试 JPA 实体,而当那些时您对 Web 层不感兴趣测试运行。
该spring-boot-test-autoconfigure
模块包含许多可用于自动配置此类“切片”的注释。它们中的每一个都以类似的方式工作,提供一个@…Test
加载的注解ApplicationContext
和一个或多个@AutoConfigure…
可用于自定义自动配置设置的注解。
每个切片将组件扫描限制在适当的组件上,并加载一组非常有限的自动配置类。如果您需要排除其中之一,大多数@…Test 注释都会提供一个excludeAutoConfiguration 属性。或者,您可以使用@ImportAutoConfiguration#exclude . |
|
---|---|
@…Test 不支持 通过在一个测试中使用多个注释来包含多个“切片” 。如果您需要多个“切片”,请选择其中一个@…Test 注释并@AutoConfigure… 手动包含其他“切片”的注释。 |
|
---|---|
也可以使用@AutoConfigure… 带有标准@SpringBootTest 注释的注释。如果您对“切片”您的应用程序不感兴趣,但您想要一些自动配置的测试 bean,则可以使用这种组合。 |
|
---|---|
8.3.12。自动配置的 JSON 测试
要测试对象 JSON 序列化和反序列化是否按预期工作,您可以使用注释@JsonTest
。 @JsonTest
自动配置可用的支持的 JSON 映射器,它可以是以下库之一:
- 杰克逊
ObjectMapper
,任何@JsonComponent
豆子和任何Module
杰克逊 Gson
Jsonb
@JsonTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
如果需要配置自动配置的元素,可以使用注解@AutoConfigureJsonTesters
。
Spring Boot 包含基于 AssertJ 的帮助程序,这些帮助程序与 JSONAssert 和 JsonPath 库一起工作,以检查 JSON 是否按预期显示。、、和类可分别用于 Jackson、Gson、Jsonb 和字符串JacksonTester
。测试类上的任何辅助字段都可以在使用. 以下示例显示了 Jackson 的测试类:GsonTester``JsonbTester``BasicJsonTester``@Autowired``@JsonTest
@JsonTest
class MyJsonTests {
@Autowired
private JacksonTester<VehicleDetails> json;
@Test
void serialize() throws Exception {
VehicleDetails details = new VehicleDetails("Honda", "Civic");
// Assert against a `.json` file in the same package as the test
assertThat(this.json.write(details)).isEqualToJson("expected.json");
// Or use JSON path based assertions
assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda");
}
@Test
void deserialize() throws Exception {
String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford", "Focus"));
assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
}
}
JSON 帮助器类也可以直接用于标准单元测试。为此,如果您不使用,请initFields 在您的方法中调用助手的方法。 @Before``@JsonTest |
|
---|---|
如果您使用 Spring Boot 的基于 AssertJ 的帮助程序对给定 JSON 路径中的数字值进行断言,则可能无法使用,isEqualTo
具体取决于类型。相反,您可以使用 AssertJsatisfies
断言该值与给定条件匹配。例如,以下示例断言实际数字是一个接近于0.15
偏移量内的浮点值0.01
。
@Test
void someTest() throws Exception {
SomeObject value = new SomeObject(0.152f);
assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
.satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));
}
8.3.13。自动配置的 Spring MVC 测试
要测试 Spring MVC 控制器是否按预期工作,请使用@WebMvcTest
注释。 @WebMvcTest
自动配置 Spring MVC 基础设施并将扫描的 bean 限制为@Controller
, @ControllerAdvice
, @JsonComponent
, Converter
, GenericConverter
, Filter
, HandlerInterceptor
, WebMvcConfigurer
,WebMvcRegistrations
和HandlerMethodArgumentResolver
. 使用注解 时不扫描正则@Component
和bean。可用于包含bean。@ConfigurationProperties``@WebMvcTest``@EnableConfigurationProperties``@ConfigurationProperties
@WebMvcTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
如果您需要注册额外的组件,例如 Jackson Module ,您可以通过@Import 在测试中使用导入额外的配置类。 |
|
---|---|
通常,@WebMvcTest
仅限于单个控制器,并与 结合使用,@MockBean
为所需的协作者提供模拟实现。
@WebMvcTest
也自动配置MockMvc
。Mock MVC 提供了一种强大的方法来快速测试 MVC 控制器,而无需启动完整的 HTTP 服务器。
MockMvc 您还可以在非@WebMvcTest (例如)中 自动配置@SpringBootTest ,方法是使用 对其进行注释@AutoConfigureMockMvc 。以下示例使用MockMvc : |
|
---|---|
@WebMvcTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("Honda Civic"));
}
}
如果您需要配置自动配置的元素(例如,何时应用 servlet 过滤器),您可以在注释中使用属性@AutoConfigureMockMvc 。 |
|
---|---|
如果您使用 HtmlUnit 和 Selenium,自动配置还会提供一个 HtmlUnit WebClient
bean 和/或一个 Selenium WebDriver
bean。以下示例使用 HtmlUnit:
@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {
@Autowired
private WebClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));
HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
}
}
默认情况下,Spring Boot 将WebDriver beans 放在一个特殊的“范围”中,以确保驱动程序在每次测试后退出并注入一个新实例。如果您不想要这种行为,您可以添加@Scope("singleton") 到您的WebDriver @Bean 定义中。 |
|
---|---|
Spring Boot 创建的作用域webDriver 将替换任何用户定义的同名作用域。如果您定义自己的webDriver 范围,您可能会发现它在您使用 时停止工作@WebMvcTest 。 |
|
---|---|
如果类路径上有 Spring Security,@WebMvcTest
也会扫描WebSecurityConfigurer
bean。您可以使用 Spring Security 的测试支持,而不是完全禁用此类测试的安全性。有关如何使用 Spring SecurityMockMvc
支持的更多详细信息,请参见*howto.html*操作部分。
有时编写 Spring MVC 测试是不够的;Spring Boot 可以帮助您使用实际服务器运行完整的端到端测试。 | |
---|---|
8.3.14。自动配置的 Spring WebFlux 测试
要测试Spring WebFlux控制器是否按预期工作,您可以使用@WebFluxTest
注释。 @WebFluxTest
自动配置 Spring WebFlux 基础设施并将扫描的 bean 限制为@Controller
, @ControllerAdvice
, @JsonComponent
, Converter
, GenericConverter
,WebFilter
和WebFluxConfigurer
. 使用注解 时不扫描正则@Component
和bean。可用于包含bean。@ConfigurationProperties``@WebFluxTest``@EnableConfigurationProperties``@ConfigurationProperties
@WebFluxTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
如果您需要注册额外的组件,例如 Jackson Module ,您可以@Import 在测试中使用导入额外的配置类。 |
|
---|---|
通常,@WebFluxTest
仅限于单个控制器,并与@MockBean
注释结合使用,为所需的协作者提供模拟实现。
@WebFluxTest
还有 auto-configures WebTestClient
,它提供了一种强大的方法来快速测试 WebFlux 控制器,而无需启动完整的 HTTP 服务器。
WebTestClient 您还可以在非@WebFluxTest (例如)中 自动配置@SpringBootTest ,方法是使用 对其进行注释@AutoConfigureWebTestClient 。以下示例显示了一个同时使用@WebFluxTest 和 a 的类WebTestClient : |
|
---|---|
@WebFluxTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private WebTestClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Honda Civic");
}
}
此设置仅受 WebFlux 应用程序支持,因为WebTestClient 在模拟 Web 应用程序中使用目前仅适用于 WebFlux。 |
|
---|---|
@WebFluxTest 无法检测通过功能性 Web 框架注册的路由。要RouterFunction 在上下文中测试 bean,请考虑RouterFunction 通过使用@Import 或使用@SpringBootTest . |
|
---|---|
@WebFluxTest 无法检测注册为@Bean 类型的自定义安全配置SecurityWebFilterChain 。@Import 要将其包含在您的测试中,您将需要通过使用或使用导入注册 bean 的配置@SpringBootTest 。 |
|
---|---|
有时编写 Spring WebFlux 测试是不够的;Spring Boot 可以帮助您使用实际服务器运行完整的端到端测试。 | |
---|---|
8.3.15。自动配置的 Spring GraphQL 测试
Spring GraphQL 提供了专门的测试支持模块;你需要将它添加到你的项目中:
行家
<dependencies>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Unless already present in the compile scope -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
摇篮
dependencies {
testImplementation("org.springframework.graphql:spring-graphql-test")
// Unless already present in the implementation configuration
testImplementation("org.springframework.boot:spring-boot-starter-webflux")
}
这个测试模块附带了GraphQlTester。测试仪在测试中使用较多,一定要熟悉使用。有GraphQlTester
多种变体,Spring Boot 将根据测试类型自动配置它们:
- 在服务器端执行测试
ExecutionGraphQlServiceTester
,没有客户端也没有传输 HttpGraphQlTester
使用连接到服务器的客户端执行测试,有或没有实时服务器
Spring Boot 可帮助您使用注解测试Spring GraphQL 控制器@GraphQlTest
。 @GraphQlTest
自动配置 Spring GraphQL 基础设施,不涉及任何传输或服务器。这将扫描的bean 限制为@Controller
、RuntimeWiringConfigurer
、JsonComponent
、Converter
、GenericConverter
、DataFetcherExceptionResolver
和Instrumentation
。使用注解 时不扫描GraphQlSourceBuilderCustomizer
正则@Component
和bean。可用于包含bean。@ConfigurationProperties``@GraphQlTest``@EnableConfigurationProperties``@ConfigurationProperties
@GraphQlTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
如果您需要注册额外的组件,例如 Jackson Module ,您可以@Import 在测试中使用导入额外的配置类。 |
|
---|---|
通常,@GraphQlTest
仅限于一组控制器,并与注释结合使用,@MockBean
为所需的协作者提供模拟实现。
@GraphQlTest(GreetingController.class)
class GreetingControllerTests {
@Autowired
private GraphQlTester graphQlTester;
@Test
void shouldGreetWithSpecificName() {
this.graphQlTester.document("{ greeting(name: \"Alice\") } ")
.execute()
.path("greeting")
.entity(String.class)
.isEqualTo("Hello, Alice!");
}
@Test
void shouldGreetWithDefaultName() {
this.graphQlTester.document("{ greeting } ")
.execute()
.path("greeting")
.entity(String.class)
.isEqualTo("Hello, Spring!");
}
}
@SpringBootTest
测试是完整的集成测试,涉及整个应用程序。使用随机或定义的端口时,会配置一个实时服务器并HttpGraphQlTester
自动提供一个 bean,以便您可以使用它来测试您的服务器。配置 MOCK 环境后,您还可以HttpGraphQlTester
通过使用以下注释测试类来请求 bean @AutoConfigureHttpGraphQlTester
:
@AutoConfigureHttpGraphQlTester
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class GraphQlIntegrationTests {
@Test
void shouldGreetWithSpecificName(@Autowired HttpGraphQlTester graphQlTester) {
HttpGraphQlTester authenticatedTester = graphQlTester.mutate()
.webTestClient((client) -> client.defaultHeaders((headers) -> headers.setBasicAuth("admin", "ilovespring")))
.build();
authenticatedTester.document("{ greeting(name: \"Alice\") } ")
.execute()
.path("greeting")
.entity(String.class)
.isEqualTo("Hello, Alice!");
}
}
8.3.16。自动配置的数据 Cassandra 测试
您可以使用它@DataCassandraTest
来测试 Cassandra 应用程序。默认情况下,它会配置一个CassandraTemplate
、扫描类@Table
并配置 Spring Data Cassandra 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 Cassandra 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)@ConfigurationProperties``@DataCassandraTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataCassandraTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了在 Spring Boot 中使用 Cassandra 测试的典型设置:
@DataCassandraTest
class MyDataCassandraTests {
@Autowired
private SomeRepository repository;
}
8.3.17。自动配置的数据 Couchbase 测试
您可以使用它@DataCouchbaseTest
来测试 Couchbase 应用程序。默认情况下,它配置一个CouchbaseTemplate
or ReactiveCouchbaseTemplate
,扫描@Document
类,并配置 Spring Data Couchbase 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 Couchbase 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ data.html ”。)@ConfigurationProperties``@DataCouchbaseTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataCouchbaseTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了在 Spring Boot 中使用 Couchbase 测试的典型设置:
@DataCouchbaseTest
class MyDataCouchbaseTests {
@Autowired
private SomeRepository repository;
// ...
}
8.3.18。自动配置的数据 Elasticsearch 测试
您可以使用它@DataElasticsearchTest
来测试 Elasticsearch 应用程序。默认情况下,它会配置一个ElasticsearchRestTemplate
、扫描@Document
类并配置 Spring Data Elasticsearch 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 Elasticsearch 与 Spring Boot 结合使用的更多信息,请参阅本章前面的“ data.html ”。)@ConfigurationProperties``@DataElasticsearchTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataElasticsearchTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了在 Spring Boot 中使用 Elasticsearch 测试的典型设置:
@DataElasticsearchTest
class MyDataElasticsearchTests {
@Autowired
private SomeRepository repository;
// ...
}
8.3.19。自动配置的数据 JPA 测试
您可以使用@DataJpaTest
注释来测试 JPA 应用程序。默认情况下,它会扫描@Entity
类并配置 Spring Data JPA 存储库。如果嵌入式数据库在类路径上可用,它也会配置一个。spring.jpa.show-sql
默认情况下,通过将属性设置为 来记录 SQL 查询true
。这可以使用showSql()
注释的属性来禁用。
使用注解 时不扫描正则@Component
和bean。可用于包含bean。@ConfigurationProperties``@DataJpaTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataJpaTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
默认情况下,数据 JPA 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个班级禁用事务管理,如下所示:
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {
// ...
}
数据 JPA 测试还可以注入一个TestEntityManager
bean,它提供了一种替代专门为测试设计的标准 JPA 的方法EntityManager
。
TestEntityManager 也可以通过添加@AutoConfigureTestEntityManager . 这样做时,请确保您的测试在事务中运行,例如通过添加 @Transactional 您的测试类或方法。 |
|
---|---|
JdbcTemplate
如果您需要,也可以使用A。以下示例显示了@DataJpaTest
正在使用的注解:
@DataJpaTest
class MyRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
void testExample() {
this.entityManager.persist(new User("sboot", "1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getEmployeeNumber()).isEqualTo("1234");
}
}
内存嵌入式数据库通常适用于测试,因为它们速度快且不需要任何安装。但是,如果您更喜欢针对真实数据库运行测试,则可以使用注释@AutoConfigureTestDatabase
,如以下示例所示:
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {
// ...
}
8.3.20。自动配置的 JDBC 测试
@JdbcTest`类似于`@DataJpaTest`但适用于只需要`DataSource`而不使用 Spring Data JDBC 的测试。默认情况下,它配置一个内存中的嵌入式数据库和一个`JdbcTemplate`. 使用注解 时不扫描正则`@Component`和bean。可用于包含bean。`@ConfigurationProperties``@JdbcTest``@EnableConfigurationProperties``@ConfigurationProperties
@JdbcTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
默认情况下,JDBC 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个班级禁用事务管理,如下所示:
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {
}
如果您希望您的测试针对真实数据库运行,您可以使用@AutoConfigureTestDatabase
与 for 相同的方式使用注释DataJpaTest
。(请参阅“自动配置的数据 JPA 测试”。)
8.3.21。自动配置的数据 JDBC 测试
@DataJdbcTest`类似于`@JdbcTest`但适用于使用 Spring Data JDBC 存储库的测试。默认情况下,它配置一个内存中嵌入式数据库、一个`JdbcTemplate`和 Spring Data JDBC 存储库。使用注解时只`AbstractJdbcConfiguration`扫描子类,不扫描 regular和bean。可用于包含bean。`@DataJdbcTest``@Component``@ConfigurationProperties``@EnableConfigurationProperties``@ConfigurationProperties
@DataJdbcTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
默认情况下,数据 JDBC 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个测试类禁用事务管理,如JDBC 示例所示。
如果您希望您的测试针对真实数据库运行,您可以使用@AutoConfigureTestDatabase
与 for 相同的方式使用注释DataJpaTest
。(请参阅“自动配置的数据 JPA 测试”。)
8.3.22。自动配置的 jOOQ 测试
您可以使用@JooqTest
与 but 类似的方式@JdbcTest
进行 jOOQ 相关测试。由于 jOOQ 严重依赖与数据库模式相对应的基于 Java 的模式,因此DataSource
使用现有模式。如果你想用内存数据库替换它,你可以使用@AutoConfigureTestDatabase
覆盖这些设置。(有关将 jOOQ 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)使用注释 时不会扫描Regular@Component
和beans。可用于包含bean。@ConfigurationProperties``@JooqTest``@EnableConfigurationProperties``@ConfigurationProperties
@JooqTest 可以在附录中找到 由 启用的自动配置列表。 |
|
---|---|
@JooqTest
配置一个DSLContext
. 以下示例显示了@JooqTest
正在使用的注解:
@JooqTest
class MyJooqTests {
@Autowired
private DSLContext dslContext;
// ...
}
JOOQ 测试是事务性的,默认情况下在每个测试结束时回滚。如果这不是您想要的,您可以为测试或整个测试类禁用事务管理,如JDBC 示例所示。
8.3.23。自动配置数据 MongoDB 测试
您可以使用它@DataMongoTest
来测试 MongoDB 应用程序。默认情况下,它会配置内存中的嵌入式 MongoDB(如果可用)、配置MongoTemplate
、扫描@Document
类并配置 Spring Data MongoDB 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 MongoDB 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)@ConfigurationProperties``@DataMongoTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataMongoTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下类显示了@DataMongoTest
正在使用的注解:
@DataMongoTest
class MyDataMongoDbTests {
@Autowired
private MongoTemplate mongoTemplate;
// ...
}
内存中嵌入式 MongoDB 通常适用于测试,因为它速度快且不需要任何开发人员安装。但是,如果您更喜欢针对真实的 MongoDB 服务器运行测试,则应排除嵌入式 MongoDB 自动配置,如以下示例所示:
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
class MyDataMongoDbTests {
// ...
}
8.3.24。自动配置的数据 Neo4j 测试
您可以使用它@DataNeo4jTest
来测试 Neo4j 应用程序。默认情况下,它会扫描@Node
类并配置 Spring Data Neo4j 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 Neo4J 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)@ConfigurationProperties``@DataNeo4jTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataNeo4jTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了在 Spring Boot 中使用 Neo4J 测试的典型设置:
@DataNeo4jTest
class MyDataNeo4jTests {
@Autowired
private SomeRepository repository;
// ...
}
默认情况下,Data Neo4j 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个班级禁用事务管理,如下所示:
@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {
}
反应性访问不支持交易测试。如果您使用此样式,则必须@DataNeo4jTest 如上所述配置测试。 |
|
---|---|
8.3.25。自动配置的数据 Redis 测试
您可以使用它@DataRedisTest
来测试 Redis 应用程序。默认情况下,它会扫描@RedisHash
类并配置 Spring Data Redis 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 Redis 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)@ConfigurationProperties``@DataRedisTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataRedisTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了@DataRedisTest
正在使用的注解:
@DataRedisTest
class MyDataRedisTests {
@Autowired
private SomeRepository repository;
// ...
}
8.3.26。自动配置的数据 LDAP 测试
您可以使用它@DataLdapTest
来测试 LDAP 应用程序。默认情况下,它会配置内存中的嵌入式 LDAP(如果可用)、配置LdapTemplate
、扫描@Entry
类并配置 Spring Data LDAP 存储库。使用注解 时不扫描正则@Component
和bean。可用于包含bean。(有关将 LDAP 与 Spring Boot 结合使用的更多信息,请参阅“ data.html ”。)@ConfigurationProperties``@DataLdapTest``@EnableConfigurationProperties``@ConfigurationProperties
@DataLdapTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了@DataLdapTest
正在使用的注解:
@DataLdapTest
class MyDataLdapTests {
@Autowired
private LdapTemplate ldapTemplate;
// ...
}
内存中嵌入式 LDAP 通常适用于测试,因为它速度快且不需要任何开发人员安装。但是,如果您更喜欢针对真实 LDAP 服务器运行测试,则应排除嵌入式 LDAP 自动配置,如以下示例所示:
@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {
// ...
}
8.3.27。自动配置的 REST 客户端
您可以使用@RestClientTest
注释来测试 REST 客户端。默认情况下,它会自动配置 Jackson、GSON 和 Jsonb 支持,配置一个RestTemplateBuilder
,并添加对MockRestServiceServer
. 使用注解 时不扫描正则@Component
和bean。可用于包含bean。@ConfigurationProperties``@RestClientTest``@EnableConfigurationProperties``@ConfigurationProperties
@RestClientTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
value
应使用 的或components
属性指定要测试的特定 bean @RestClientTest
,如以下示例所示:
@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestClientTests {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
String greeting = this.service.callRestService();
assertThat(greeting).isEqualTo("hello");
}
}
8.3.28。自动配置的 Spring REST 文档测试
您可以使用注释在 Mock MVC、REST Assured 或 WebTestClient 的测试中@AutoConfigureRestDocs
使用Spring REST Docs 。它消除了 Spring REST Docs 中对 JUnit 扩展的需求。
@AutoConfigureRestDocs
可用于覆盖默认输出目录(target/generated-snippets
如果您使用 Maven 或build/generated-snippets
Gradle)。它还可用于配置出现在任何记录的 URI 中的主机、方案和端口。
使用 Mock MVC 自动配置的 Spring REST Docs 测试
@AutoConfigureRestDocs``MockMvc
在测试基于 servlet 的 Web 应用程序时自定义bean 以使用 Spring REST Docs。@Autowired
您可以像使用 Mock MVC 和 Spring REST Docs 时一样,通过在测试中使用和使用它来注入它,如以下示例所示:
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Autowired
private MockMvc mvc;
@Test
void listUsers() throws Exception {
this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andDo(document("list-users"));
}
}
如果您需要对 Spring REST Docs 配置的控制比 的属性提供的更多@AutoConfigureRestDocs
,则可以使用RestDocsMockMvcConfigurationCustomizer
bean,如以下示例所示:
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer {
@Override
public void customize(MockMvcRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
}
如果您想使用 Spring REST Docs 对参数化输出目录的支持,您可以创建一个RestDocumentationResultHandler
bean。自动配置调用alwaysDo
此结果处理程序,从而导致每次MockMvc
调用自动生成默认片段。以下示例显示了一个RestDocumentationResultHandler
被定义的对象:
@TestConfiguration(proxyBeanMethods = false)
public class MyResultHandlerConfiguration {
@Bean
public RestDocumentationResultHandler restDocumentation() {
return MockMvcRestDocumentation.document("{method-name}");
}
}
使用 WebTestClient 自动配置的 Spring REST Docs 测试
@AutoConfigureRestDocs
也可以在测试响应式 Web 应用程序时使用WebTestClient
。@Autowired
您可以像使用 Spring REST Docs时一样,通过在测试中使用和使用它来注入它@WebFluxTest
,如以下示例所示:
@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {
@Autowired
private WebTestClient webTestClient;
@Test
void listUsers() {
this.webTestClient
.get().uri("/")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(document("list-users"));
}
}
如果您需要对 Spring REST Docs 配置的控制比 的属性提供的更多@AutoConfigureRestDocs
,则可以使用RestDocsWebTestClientConfigurationCustomizer
bean,如以下示例所示:
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {
@Override
public void customize(WebTestClientRestDocumentationConfigurer configurer) {
configurer.snippets().withEncoding("UTF-8");
}
}
如果你想利用 Spring REST Docs 对参数化输出目录的支持,你可以使用 aWebTestClientBuilderCustomizer
为每个实体交换结果配置一个消费者。以下示例显示了这样的WebTestClientBuilderCustomizer
定义:
@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {
@Bean
public WebTestClientBuilderCustomizer restDocumentation() {
return (builder) -> builder.entityExchangeResultConsumer(document("{method-name}"));
}
}
使用 REST Assured 自动配置的 Spring REST Docs 测试
@AutoConfigureRestDocs
制作一个RequestSpecification
预配置为使用 Spring REST Docs 的 bean,可用于您的测试。@Autowired
您可以像使用 REST Assured 和 Spring REST Docs 时一样,通过在测试中使用和使用它来注入它,如以下示例所示:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Test
void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) {
given(documentationSpec)
.filter(document("list-users"))
.when()
.port(port)
.get("/")
.then().assertThat()
.statusCode(is(200));
}
}
如果您需要对 Spring REST Docs 配置的控制比 的属性提供的控制更多@AutoConfigureRestDocs
,则RestDocsRestAssuredConfigurationCustomizer
可以使用 bean,如以下示例所示:
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer {
@Override
public void customize(RestAssuredRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
}
8.3.29。自动配置的 Spring Web 服务测试
自动配置的 Spring Web 服务客户端测试
您可以@WebServiceClientTest
使用 Spring Web 服务项目来测试调用 Web 服务的应用程序。默认情况下,它会配置一个模拟WebServiceServer
bean 并自动自定义您的WebServiceTemplateBuilder
. (有关将 Web 服务与 Spring Boot 结合使用的更多信息,请参阅“ io.html ”。)
@WebServiceClientTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了@WebServiceClientTest
正在使用的注解:
@WebServiceClientTest(SomeWebService.class)
class MyWebServiceClientTests {
@Autowired
private MockWebServiceServer server;
@Autowired
private SomeWebService someWebService;
@Test
void mockServerCall() {
this.server
.expect(payload(new StringSource("<request/>")))
.andRespond(withPayload(new StringSource("<response><status>200</status></response>")));
assertThat(this.someWebService.test())
.extracting(Response::getStatus)
.isEqualTo(200);
}
}
自动配置的 Spring Web 服务服务器测试
您可以@WebServiceServerTest
使用 Spring Web Services 项目来测试实现 Web 服务的应用程序。默认情况下,它配置一个MockWebServiceClient
可用于调用 Web 服务端点的 bean。(有关将 Web 服务与 Spring Boot 结合使用的更多信息,请参阅“ io.html ”。)
@WebServiceServerTest 可以在附录中找到 由 启用的自动配置设置列表。 |
|
---|---|
以下示例显示了@WebServiceServerTest
正在使用的注解:
@WebServiceServerTest(ExampleEndpoint.class)
class MyWebServiceServerTests {
@Autowired
private MockWebServiceClient client;
@Test
void mockServerCall() {
this.client
.sendRequest(RequestCreators.withPayload(new StringSource("<ExampleRequest/>")))
.andExpect(ResponseMatchers.payload(new StringSource("<ExampleResponse>42</ExampleResponse>")));
}
}
8.3.30。额外的自动配置和切片
每个切片提供一个或多个@AutoConfigure…
注释,即定义应作为切片的一部分包含的自动配置。@AutoConfigure…
通过创建自定义注释或添加到测试中,可以在逐个测试的基础上添加其他自动配置,@ImportAutoConfiguration
如以下示例所示:
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class MyJdbcTests {
}
确保不使用常规@Import 注释来导入自动配置,因为它们由 Spring Boot 以特定方式处理。 |
|
---|---|
或者,可以为切片注释的任何使用添加额外的自动配置,方法是将它们注册到存储在META-INF/spring
以下示例中的文件中:
META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.JdbcTest.imports
com.example.IntegrationAutoConfiguration
在此示例中,com.example.IntegrationAutoConfiguration
在每个用 注释的测试上启用@JdbcTest
。
# 您可以在此文件中 使用注释。 |
|
---|---|
切片或@AutoConfigure… 注解可以通过这种方式定制,只要它是用 元注解的@ImportAutoConfiguration 。 |
|
---|---|
8.3.31。用户配置和切片
如果您以合理的方式构建代码,默认情况下@SpringBootApplication
您的类将用作测试的配置。
因此,重要的是不要在应用程序的主类中乱放特定于其功能的特定区域的配置设置。
假设您正在使用 Spring Batch 并且您依赖于它的自动配置。你可以定义你@SpringBootApplication
的如下:
@SpringBootApplication
@EnableBatchProcessing
public class MyApplication {
// ...
}
因为这个类是测试的源配置,所以任何切片测试实际上都会尝试启动 Spring Batch,这绝对不是你想要做的。推荐的方法是将特定于区域的配置移动到与@Configuration
您的应用程序处于同一级别的单独类,如以下示例所示:
@Configuration(proxyBeanMethods = false)
@EnableBatchProcessing
public class MyBatchConfiguration {
// ...
}
根据应用程序的复杂性,您可以为自定义设置一个@Configuration 类,也可以为每个域区域设置一个类。后一种方法允许您在其中一个测试中启用它,如有必要,使用注释@Import 。有关何时可能希望为切片测试启用特定类的更多详细信息,请参阅此操作方法部分@Configuration 。 |
|
---|---|
测试切片将@Configuration
类排除在扫描之外。例如,对于 a @WebMvcTest
,以下配置不会WebMvcConfigurer
在测试切片加载的应用程序上下文中包含给定的 bean:
@Configuration(proxyBeanMethods = false)
public class MyWebConfiguration {
@Bean
public WebMvcConfigurer testConfigurer() {
return new WebMvcConfigurer() {
// ...
};
}
}
但是,下面的配置将导致WebMvcConfigurer
测试切片加载自定义。
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
// ...
}
另一个混淆来源是类路径扫描。假设,当您以合理的方式构建代码时,您需要扫描一个额外的包。您的应用程序可能类似于以下代码:
@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {
// ...
}
这样做会有效地覆盖默认组件扫描指令,并产生扫描这两个包的副作用,而不管您选择的切片如何。例如,a@DataJpaTest
似乎突然扫描应用程序的组件和用户配置。同样,将自定义指令移至单独的类是解决此问题的好方法。
如果这不是您的选择,您可以@SpringBootConfiguration 在测试层次结构中的某处创建一个,以便使用它。或者,您可以为您的测试指定一个源,这会禁用查找默认源的行为。 |
|
---|---|
8.3.32。使用 Spock 测试 Spring Boot 应用程序
Spock 2.x 可用于测试 Spring Boot 应用程序。为此,请将对 Spockspock-spring
模块的依赖项添加到应用程序的构建中。 spock-spring
将 Spring 的测试框架集成到 Spock 中。有关详细信息,请参阅Spock 的 Spring 模块的文档。
8.4. 测试实用程序
一些在测试您的应用程序时通常有用的测试实用程序类被打包为spring-boot
.
8.4.1. ConfigDataApplicationContextInitializer
ConfigDataApplicationContextInitializer
是一个ApplicationContextInitializer
您可以应用于您的测试以加载 Spring Bootapplication.properties
文件的工具。当您不需要 提供的全套功能时,您可以使用它@SpringBootTest
,如下例所示:
@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {
// ...
}
单独使用ConfigDataApplicationContextInitializer 不提供对@Value("${…}") 注入的支持。它唯一的工作是确保application.properties 文件加载到 Spring 的Environment . 要获得@Value 支持,您需要另外配置一个PropertySourcesPlaceholderConfigurer 或使用@SpringBootTest ,后者会为您自动配置一个。 |
|
---|---|
8.4.2. 测试属性值
TestPropertyValues
让您快速将属性添加到ConfigurableEnvironment
或ConfigurableApplicationContext
。您可以使用key=value
字符串调用它,如下所示:
class MyEnvironmentTests {
@Test
void testPropertySources() {
MockEnvironment environment = new MockEnvironment();
TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);
assertThat(environment.getProperty("name")).isEqualTo("Boot");
}
}
8.4.3. 输出捕获
OutputCapture
是一个 JUnit Extension
,您可以使用它来捕获System.out
和System.err
输出。使用 add@ExtendWith(OutputCaptureExtension.class)
和 injectCapturedOutput
作为测试类构造函数或测试方法的参数,如下所示:
@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {
@Test
void testName(CapturedOutput output) {
System.out.println("Hello World!");
assertThat(output).contains("World");
}
}
8.4.4. 测试模板
TestRestTemplate
是 Spring 的便捷替代品RestTemplate
,在集成测试中很有用。您可以获得普通模板或发送基本 HTTP 身份验证(使用用户名和密码)的模板。在任何一种情况下,模板都是容错的。这意味着它不会在 4xx 和 5xx 错误上抛出异常,以测试友好的方式运行。相反,可以通过返回ResponseEntity
的及其状态代码来检测此类错误。
Spring Framework 5.0 提供了一个WebTestClient 适用于WebFlux 集成测试以及WebFlux 和 MVC 端到端测试的新功能。与TestRestTemplate . |
|
---|---|
建议但不强制使用 Apache HTTP 客户端(版本 4.3.2 或更高版本)。如果您的类路径中有它,则会TestRestTemplate
通过适当配置客户端进行响应。如果您确实使用 Apache 的 HTTP 客户端,则会启用一些额外的测试友好功能:
- 不遵循重定向(因此您可以断言响应位置)。
- Cookies 被忽略(因此模板是无状态的)。
TestRestTemplate
可以直接在您的集成测试中实例化,如以下示例所示:
class MyTests {
private final TestRestTemplate template = new TestRestTemplate();
@Test
void testRequest() {
ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class);
assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");
}
}
或者,如果您将@SpringBootTest
注解与WebEnvironment.RANDOM_PORT
或 一起使用WebEnvironment.DEFINED_PORT
,则可以注入一个完全配置的TestRestTemplate
并开始使用它。如有必要,可以通过 bean 应用其他定制RestTemplateBuilder
。任何未指定主机和端口的 URL 都会自动连接到嵌入式服务器,如以下示例所示:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {
@Autowired
private TestRestTemplate template;
@Test
void testRequest() {
HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();
assertThat(headers.getLocation()).hasHost("other.example.com");
}
@TestConfiguration(proxyBeanMethods = false)
static class RestTemplateBuilderConfiguration {
@Bean
RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1));
}
}
}
9. 创建你自己的自动配置
如果您在开发共享库的公司工作,或者如果您在开源或商业库上工作,您可能想要开发自己的自动配置。自动配置类可以捆绑在外部 jar 中,并且仍然可以由 Spring Boot 获取。
自动配置可以与提供自动配置代码以及您将使用它的典型库的“启动器”相关联。我们首先介绍构建您自己的自动配置所需了解的内容,然后我们继续介绍创建自定义启动器所需的典型步骤。
9.1. 了解自动配置的 Bean
实现自动配置的类用@AutoConfiguration
. 这个注解本身是用元注解的@Configuration
,使自动配置成为标准@Configuration
类。附加@Conditional
注释用于限制何时应应用自动配置。通常,自动配置类使用@ConditionalOnClass
和@ConditionalOnMissingBean
注解。这确保自动配置仅在找到相关类且您尚未声明自己的@Configuration
.
您可以浏览 的源代码spring-boot-autoconfigure
以查看@AutoConfiguration
Spring 提供的类(请参阅META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件)。
9.2. 定位自动配置候选者
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Spring Boot 检查已发布的 jar 中是否存在文件。该文件应列出您的配置类,每行一个类名,如以下示例所示:
com.mycorp.libx.autoconfigure.LibXAutoConfiguration
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
您可以使用字符向导入文件添加注释# 。 |
|
---|---|
必须仅通过在导入文件中命名 来加载自动配置。确保它们是在特定的包空间中定义的,并且它们永远不是组件扫描的目标。此外,自动配置类不应启用组件扫描来查找其他组件。@Import 应改用 特定的s。 |
|
---|---|
如果您的配置需要按特定顺序应用,您可以在注释或专用和注释上使用before
、beforeName
和属性。例如,如果您提供特定于 Web 的配置,则您的类可能需要在.after``afterName
@AutoConfiguration
@AutoConfigureBefore
@AutoConfigureAfter
WebMvcAutoConfiguration
如果你想订购某些相互之间不应该有任何直接知识的自动配置,你也可以使用@AutoConfigureOrder
. 该注释与常规@Order
注释具有相同的语义,但为自动配置类提供了专用顺序。
与标准@Configuration
类一样,应用自动配置类的顺序只会影响定义它们的 bean 的顺序。随后创建这些 bean 的顺序不受影响,并由每个 bean 的依赖关系和任何关系决定@DependsOn
。
9.3. 条件注解
@Conditional
您几乎总是希望在您的自动配置类中包含一个或多个注释。注释@ConditionalOnMissingBean
是一个常见的示例,用于允许开发人员在对您的默认设置不满意时覆盖自动配置。
Spring Boot 包含许多注释,您可以通过注释类或单个方法@Conditional
在自己的代码中重用这些注释。这些注释包括:@Configuration``@Bean
9.3.1. 上课条件
和注释允许根据特定类的存在或不存在来包含类@ConditionalOnClass
。由于注释元数据是使用ASM解析的,因此您可以使用该属性来引用真实的类,即使该类实际上可能不会出现在正在运行的应用程序类路径中。如果您更喜欢使用值来指定类名,也可以使用该属性。@ConditionalOnMissingClass``@Configuration``value``name``String
这种机制不适用于@Bean
通常返回类型是条件目标的方法:在方法的条件应用之前,JVM 将加载类和可能处理的方法引用,如果类不是展示。
为了处理这种情况,@Configuration
可以使用一个单独的类来隔离这种情况,如以下示例所示:
@AutoConfiguration
// Some conditions ...
public class MyAutoConfiguration {
// Auto-configured beans ...
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService.class)
public static class SomeServiceConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}
}
如果您使用@ConditionalOnClass or@ConditionalOnMissingClass 作为元注释的一部分来编写您自己的组合注释,则必须使用name as 引用类,在这种情况下不会处理。 |
|
---|---|
9.3.2. Bean 条件
和注释允许根据特定 bean 的存在或不存在来包含 bean @ConditionalOnBean
。@ConditionalOnMissingBean
您可以使用该value
属性按类型指定 beans 或name
按名称指定 beans。该search
属性允许您限制ApplicationContext
在搜索 bean 时应考虑的层次结构。
当放置在@Bean
方法上时,目标类型默认为方法的返回类型,如以下示例所示:
@AutoConfiguration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}
在前面的示例中,如果.bean 中尚未包含someService
任何类型的 bean,则将创建该 bean 。SomeService``ApplicationContext
您需要非常注意添加 bean 定义的顺序,因为这些条件是根据目前已处理的内容进行评估的。出于这个原因,我们建议在自动配置类上 只使用@ConditionalOnBean 和注释(因为这些可以保证在添加任何用户定义的 bean 定义后加载)。@ConditionalOnMissingBean |
|
---|---|
@ConditionalOnBean 并且@ConditionalOnMissingBean 不要阻止@Configuration 创建类。在类级别使用这些条件与使用@Bean 注释标记每个包含的方法之间的唯一区别是,@Configuration 如果条件不匹配,前者会阻止将类注册为 bean。 |
|
---|---|
声明@Bean 方法时,在方法的返回类型中提供尽可能多的类型信息。例如,如果你的 bean 的具体类实现了一个接口,bean 方法的返回类型应该是具体类而不是接口。在使用 bean 条件时,在方法中提供尽可能多的类型信息@Bean 尤为重要,因为它们的评估只能依赖于方法签名中可用的类型信息。 |
|
---|---|
9.3.3. 物业条件
注释@ConditionalOnProperty
允许基于 Spring Environment 属性包含配置。使用prefix
和name
属性指定应检查的属性。false
默认情况下,匹配任何存在且不等于的属性。您还可以使用havingValue
和matchIfMissing
属性创建更高级的检查。
9.3.4. 资源条件
@ConditionalOnResource
仅当存在特定资源时,注释才允许包含配置。可以使用常用的 Spring 约定来指定资源,如以下示例所示file:/home/user/test.dat
:
9.3.5. 网络申请条件
和注释允许根据应用程序是否为 Web 应用程序来包含配置@ConditionalOnWebApplication
。@ConditionalOnNotWebApplication
基于 servlet 的 Web 应用程序是任何使用 Spring WebApplicationContext
、定义session
范围或具有ConfigurableWebEnvironment
. 反应式 Web 应用程序是任何ReactiveWebApplicationContext
使用ConfigurableReactiveWebEnvironment
.
和注释允许根据应用程序是否是部署到 servlet 容器的传统 WAR 应用程序来包含配置@ConditionalOnWarDeployment
。@ConditionalOnNotWarDeployment
此条件与使用嵌入式 Web 服务器运行的应用程序不匹配。
9.3.6. SpEL 表达条件
注释@ConditionalOnExpression
允许根据SpEL 表达式的结果包含配置。
在表达式中引用一个 bean 将导致该 bean 在上下文刷新处理中很早就被初始化。因此,bean 将不符合后处理(例如配置属性绑定)的条件,并且其状态可能不完整。 | |
---|---|
9.4. 测试您的自动配置
自动配置会受到许多因素的影响:用户配置(@Bean
定义和Environment
定制)、条件评估(特定库的存在)等。具体来说,每个测试都应该创建一个定义良好的ApplicationContext
代表这些定制的组合。 ApplicationContextRunner
提供了实现这一目标的好方法。
ApplicationContextRunner
通常定义为测试类的一个字段,用于收集基础的、通用的配置。以下示例确保MyServiceAutoConfiguration
始终调用它:
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MyServiceAutoConfiguration.class));
如果必须定义多个自动配置,则无需对它们的声明进行排序,因为它们的调用顺序与运行应用程序时的顺序完全相同。 | |
---|---|
每个测试都可以使用运行器来表示特定的用例。例如,下面的示例调用用户配置 ( UserConfiguration
) 并检查自动配置是否正确退出。Invokingrun
提供了一个可以与 一起使用的回调上下文AssertJ
。
@Test
void defaultServiceBacksOff() {
this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(MyService.class);
assertThat(context).getBean("myCustomService").isSameAs(context.getBean(MyService.class));
});
}
@Configuration(proxyBeanMethods = false)
static class UserConfiguration {
@Bean
MyService myCustomService() {
return new MyService("mine");
}
}
也可以轻松自定义Environment
,如以下示例所示:
@Test
void serviceNameCanBeConfigured() {
this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
assertThat(context).hasSingleBean(MyService.class);
assertThat(context.getBean(MyService.class).getName()).isEqualTo("test123");
});
}
跑步者也可用于显示ConditionEvaluationReport
. 报告可以打印在INFO
或DEBUG
水平。以下示例显示如何使用ConditionEvaluationReportLoggingListener
打印自动配置测试中的报告。
class MyConditionEvaluationReportingTests {
@Test
void autoConfigTest() {
new ApplicationContextRunner()
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
.run((context) -> {
// Test something...
});
}
}
9.4.1. 模拟 Web 上下文
如果您需要测试仅在 servlet 或反应式 Web 应用程序上下文中运行的自动配置,请分别使用WebApplicationContextRunner
或ReactiveWebApplicationContextRunner
。
9.4.2. 覆盖类路径
也可以测试当特定类和/或包在运行时不存在时会发生什么。Spring Boot 附带了一个FilteredClassLoader
可以让跑步者轻松使用的工具。在下面的示例中,我们断言如果MyService
不存在,则自动配置被正确禁用:
@Test
void serviceIsIgnoredIfLibraryIsNotPresent() {
this.contextRunner.withClassLoader(new FilteredClassLoader(MyService.class))
.run((context) -> assertThat(context).doesNotHaveBean("myService"));
}
9.5. 创建你自己的启动器
一个典型的 Spring Boot starter 包含自动配置和定制给定技术基础设施的代码,我们称之为“acme”。为了使其易于扩展,可以将专用命名空间中的许多配置键暴露给环境。最后,提供了一个单一的“启动器”依赖项,以帮助用户尽可能轻松地入门。
具体来说,自定义启动器可以包含以下内容:
autoconfigure
包含“acme”的自动配置代码的模块。starter
提供对模块的依赖关系的模块autoconfigure
以及“acme”和通常有用的任何其他依赖关系。简而言之,添加启动器应该提供开始使用该库所需的一切。
两个模块的这种分离是没有必要的。如果“acme”有多种风格、选项或可选功能,那么最好将自动配置分开,因为您可以清楚地表达某些功能是可选的。此外,您还可以制作一个 starter 来提供关于这些可选依赖项的意见。同时,其他人也只能依托autoconfigure
模块,打造自己的starter,见仁见智。
如果自动配置相对简单并且没有可选功能,那么在启动器中合并两个模块绝对是一个选项。
9.5.1. 命名
你应该确保为你的启动器提供一个合适的命名空间。不要以 开头您的模块名称spring-boot
,即使您使用不同的 Maven groupId
。我们可能会为您将来自动配置的东西提供官方支持。
根据经验,您应该以启动器命名组合模块。acme-spring-boot
例如,假设您正在为“acme”创建启动器,并将自动配置模块和启动器命名为acme-spring-boot-starter
。如果只有一个模块结合了两者,请将其命名为acme-spring-boot-starter
.
9.5.2. 配置键
如果您的启动器提供配置密钥,请为它们使用唯一的命名空间。特别是,不要将您的密钥包含在 Spring Boot 使用的命名空间中(例如server
、management
、spring
等)。如果您使用相同的命名空间,我们将来可能会以破坏您的模块的方式修改这些命名空间。根据经验,在所有键前加上您拥有的名称空间(例如acme
)。
确保通过为每个属性添加字段 javadoc 来记录配置键,如以下示例所示:
@ConfigurationProperties("acme")
public class AcmeProperties {
/**
* Whether to check the location of acme resources.
*/
private boolean checkLocation = true;
/**
* Timeout for establishing a connection to the acme server.
*/
private Duration loginTimeout = Duration.ofSeconds(3);
// getters/setters ...
}
您应该只使用带有字段 Javadoc 的纯文本@ConfigurationProperties ,因为它们在添加到 JSON 之前不会被处理。 |
|
---|---|
以下是我们在内部遵循的一些规则,以确保描述一致:
- 不要以“The”或“A”开始描述。
- 对于
boolean
类型,以“是否”或“启用”开始描述。 - 对于基于集合的类型,以“逗号分隔列表”开始描述
- 如果与毫秒不同,则使用而
java.time.Duration
不是long
描述默认单位,例如“如果未指定持续时间后缀,将使用秒”。 - 不要在描述中提供默认值,除非它必须在运行时确定。
确保触发元数据生成,以便 IDE 帮助也可用于您的密钥。您可能想要查看生成的元数据 ( META-INF/spring-configuration-metadata.json
) 以确保您的密钥已正确记录。在兼容的 IDE 中使用您自己的启动程序也是验证元数据质量的好主意。
9.5.3. “自动配置”模块
该autoconfigure
模块包含开始使用该库所需的一切。它还可能包含配置键定义(例如@ConfigurationProperties
)和任何可用于进一步自定义组件初始化方式的回调接口。
您应该将库的依赖项标记为可选,以便您可以autoconfigure 更轻松地将模块包含在项目中。如果您这样做,则不会提供该库,并且默认情况下,Spring Boot 会退出。 |
|
---|---|
Spring Boot 使用注解处理器收集元数据文件 ( ) 中自动配置的条件META-INF/spring-autoconfigure-metadata.properties
。如果该文件存在,它将用于急切地过滤不匹配的自动配置,这将缩短启动时间。
使用 Maven 构建时,建议在包含自动配置的模块中添加以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
如果您直接在应用程序中定义了自动配置,请确保配置spring-boot-maven-plugin
以防止repackage
目标将依赖项添加到 fat jar 中:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
使用 Gradle,应在配置中声明依赖项annotationProcessor
,如以下示例所示:
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}
9.5.4. 入门模块
开胃菜实际上是一个空罐子。它的唯一目的是提供必要的依赖关系以使用该库。您可以将其视为对开始所需内容的固执己见的看法。
不要对添加了启动器的项目做出假设。如果您要自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很多,那么提供一组适当的默认依赖项可能会很困难,因为您应该避免包含库的典型使用所不需要的依赖项。换句话说,您不应该包含可选的依赖项。
无论哪种方式,您的启动器都必须直接或间接引用核心 Spring Boot 启动器(spring-boot-starter )(如果您的启动器依赖于另一个启动器,则无需添加它)。如果项目仅使用您的自定义启动器创建,则 Spring Boot 的核心功能将因核心启动器的存在而受到尊重。 |
|
---|---|
10.科特林支持
Kotlin是一种针对 JVM(和其他平台)的静态类型语言,它允许编写简洁优雅的代码,同时提供与用 Java 编写的现有库的互操作性。
Spring Boot 通过利用 Spring Framework、Spring Data 和 Reactor 等其他 Spring 项目中的支持来提供 Kotlin 支持。有关详细信息,请参阅Spring Framework Kotlin 支持文档。
开始使用 Spring Boot 和 Kotlin 的最简单方法是遵循这个综合教程。您可以使用start.spring.io创建新的 Kotlin 项目。如果您需要支持,请随时加入Kotlin Slack的#spring 频道或使用Stack Overflow上的spring
和标签提问。kotlin
10.1. 要求
Spring Boot 至少需要 Kotlin 1.3.x,并通过依赖管理来管理合适的 Kotlin 版本。要使用 Kotlin,org.jetbrains.kotlin:kotlin-stdlib
必须org.jetbrains.kotlin:kotlin-reflect
存在于类路径中。也可以使用变kotlin-stdlib
体kotlin-stdlib-jdk7
和。kotlin-stdlib-jdk8
由于Kotlin 类默认为 final,您可能希望配置kotlin-spring插件以自动打开 Spring 注释的类,以便它们可以被代理。
在 Kotlin 中序列化/反序列化 JSON 数据需要Jackson 的 Kotlin 模块。当在类路径中找到时,它会自动注册。如果 Jackson 和 Kotlin 存在但 Jackson Kotlin 模块不存在,则会记录一条警告消息。
如果在start.spring.io 上引导 Kotlin 项目,则默认提供这些依赖项和插件。 | |
---|---|
10.2. 零安全
Kotlin 的关键特性之一是null-safety。它在编译时处理null
值,而不是将问题推迟到运行时并遇到NullPointerException
. 这有助于消除常见的错误来源,而无需支付Optional
. Kotlin 还允许使用具有可为 null 值的函数构造,如Kotlin 中的 null-safety 综合指南中所述。
尽管 Java 不允许在其类型系统中表达空值安全性,但 Spring Framework、Spring Data 和 Reactor 现在通过工具友好的注释提供了它们的 API 的空值安全性。默认情况下,Kotlin 中使用的 Java API 中的类型被识别为放宽空值检查的 平台类型。Kotlin 对 JSR 305 注释的支持与可空性注释相结合,为 Kotlin 中的相关 Spring API 提供了空安全性。
-Xjsr305
可以通过使用以下选项添加编译器标志来配置 JSR 305 检查: -Xjsr305={strict|warn|ignore}
. 默认行为与-Xjsr305=warn
. 该strict
值需要在从 Spring API 推断的 Kotlin 类型中考虑空安全性,但在使用时应了解 Spring API 可空性声明甚至可以在次要版本之间演变,并且将来可能会添加更多检查)。
尚不支持通用类型参数、可变参数和数组元素可空性。有关最新信息,请参阅SPR-15942 。还要注意,Spring Boot 自带的 API还没有注解。 | |
---|---|
10.3. 科特林API
10.3.1。运行应用程序
Spring Boot 提供了一种惯用的方式来运行应用程序,runApplication<MyApplication>(*args)
如以下示例所示:
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
这是SpringApplication.run(MyApplication::class.java, *args)
. 它还允许自定义应用程序,如以下示例所示:
runApplication<MyApplication>(*args) {
setBannerMode(OFF)
}
10.3.2。扩展
Kotlin扩展提供了使用附加功能扩展现有类的能力。Spring Boot Kotlin API 利用这些扩展为现有 API 添加新的 Kotlin 特定便利。
TestRestTemplate
提供了类似于 Spring Framework 为RestOperations
Spring Framework 提供的扩展。除其他外,这些扩展使得利用 Kotlin 具体化类型参数成为可能。
10.4. 依赖管理
为了避免在类路径上混合不同版本的 Kotlin 依赖项,Spring Boot 导入了 Kotlin BOM。
使用 Maven,可以通过设置属性来定制 Kotlin 版本kotlin.version
,并为kotlin-maven-plugin
. 使用 Gradle,Spring Boot 插件会自动kotlin.version
与 Kotlin 插件的版本保持一致。
Spring Boot 还通过导入 Kotlin 协程 BOM 来管理协程依赖项的版本。可以通过设置属性来自定义版本kotlin-coroutines.version
。
org.jetbrains.kotlinx:kotlinx-coroutines-reactor 如果引导 Kotlin 项目至少有一个对start.spring.io 的反应依赖,则默认提供依赖。 |
|
---|---|
10.5。@配置属性
@ConfigurationProperties
@ConstructorBinding
当与具有不可变属性的支持类结合使用时,val
如以下示例所示:
@ConstructorBinding
@ConfigurationProperties("example.kotlin")
data class KotlinExampleProperties(
val name: String,
val description: String,
val myService: MyService) {
data class MyService(
val apiToken: String,
val uri: URI
)
}
要使用注释处理器生成您自己的元数据,kapt 应该配置依赖项spring-boot-configuration-processor 。请注意,由于 kapt 提供的模型的限制,某些功能(例如检测默认值或已弃用的项目)无法正常工作。 |
|
---|---|
10.6. 测试
虽然可以使用 JUnit 4 来测试 Kotlin 代码,但 JUnit 5 是默认提供的,建议使用。JUnit 5 使测试类能够被实例化一次并重新用于该类的所有测试。这使得在非静态方法上使用@BeforeAll
和@AfterAll
注释成为可能,这非常适合 Kotlin。
要模拟 Kotlin 类,建议使用MockK 。如果您需要MockK
Mockito 特定@MockBean
和@SpyBean
注释的等价物,您可以使用提供类似和注释的SpringMockK。@MockkBean``@SpykBean
10.7. 资源
10.7.1。延伸阅读
- Kotlin 语言参考
- Kotlin Slack(带有专用的#spring 频道)
spring
带有和kotlin
标签的 Stackoverflow- 在浏览器中试用 Kotlin
- 科特林博客
- 很棒的科特林
- 教程:使用 Spring Boot 和 Kotlin 构建 Web 应用程序
- 使用 Kotlin 开发 Spring Boot 应用程序
- 使用 Kotlin、Spring Boot 和 PostgreSQL 的地理空间信使
- 在 Spring Framework 5.0 中引入 Kotlin 支持
- Spring Framework 5 Kotlin API,功能方式
10.7.2。例子
- spring-boot-kotlin-demo:常规 Spring Boot + Spring Data JPA 项目
- mixit:Spring Boot 2 + WebFlux + Reactive Spring Data MongoDB
- spring-kotlin-fullstack:WebFlux Kotlin fullstack 示例,前端使用 Kotlin2js 而不是 JavaScript 或 TypeScript
- spring-petclinic-kotlin:Spring PetClinic 示例应用程序的 Kotlin 版本
- spring-kotlin-deepdive:从 Boot 1.0 + Java 逐步迁移到 Boot 2.0 + Kotlin
- spring-boot-coroutines-demo : 协程示例项目
11.接下来要读什么
如果您想了解有关本节中讨论的任何类的更多信息,请参阅Spring Boot API 文档或者您可以直接浏览源代码。如果您有具体问题,请参阅操作方法部分。
如果您熟悉 Spring Boot 的核心功能,您可以继续阅读生产就绪功能。
最后更新时间 2023-03-23 08:15:02 UTC