此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.0! |
开发时服务
开发时服务提供在开发应用程序时运行应用程序所需的外部依赖项。 它们只应在开发时使用,并在部署应用程序时禁用。
Spring Boot 支持两种开发时服务,即 Docker Compose 和 Testcontainers。 接下来的部分将提供有关它们的更多详细信息。
Docker Compose 支持
Docker Compose 是一种流行的技术,可用于为应用程序所需的服务定义和管理多个容器。
通常在应用程序旁边创建一个文件,用于定义和配置服务容器。compose.yml
Docker Compose 的典型工作流是运行,在应用程序上运行,将其连接到已启动的服务,然后在完成后运行。docker compose up
docker compose down
该模块可以包含在项目中,以支持使用 Docker Compose 处理容器。
将模块依赖项添加到您的构建中,如以下 Maven 和 Gradle 清单所示:spring-boot-docker-compose
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
dependencies {
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
}
当此模块作为依赖项包含在内时, Spring Boot 将执行以下操作:
-
在工作目录中搜索 a 和其他常见的 compose 文件名
compose.yml
-
与发现的
docker compose up
compose.yml
-
为每个支持的容器创建服务连接 Bean
-
应用程序关闭时调用
docker compose stop
如果在启动应用程序时 Docker Compose 服务已经在运行,则 Spring Boot 将仅为每个支持的容器创建服务连接 bean。
它不会再次调用,也不会在应用程序关闭时调用。docker compose up
docker compose stop
默认情况下,重新打包的存档不包含 Spring Boot 的 Docker Compose。
如果您想使用此支持,则需要包含它。
使用 Maven 插件时,请将属性设置为 。
使用 Gradle 插件时,请配置任务的 Classpath 以包含 developmentOnly 配置。excludeDockerCompose false |
服务连接
服务连接是与任何远程服务的连接。 Spring Boot 的自动配置可以使用服务连接的详细信息,并使用它们来建立与远程服务的连接。 执行此操作时,连接详细信息优先于任何与连接相关的配置属性。
当使用 Spring Boot 的 Docker Compose 支持时,将建立与容器映射的端口的服务连接。
Docker Compose 的使用方式通常是将容器内的端口映射到计算机上的临时端口。 例如,Postgres 服务器可以使用端口 5432 在容器内运行,但在本地映射到完全不同的端口。 服务连接将始终发现并使用本地映射的端口。 |
使用容器的映像名称建立服务连接。 目前支持以下服务连接:
连接详细信息 | 匹配时间 |
---|---|
名为 “symptoma/activemq” 或 “apache/activemq-classic” 的容器 |
|
名为 “apache/activemq-artemis” 的容器 |
|
名为 “cassandra” 或 “bitnami/cassandra” 的容器 |
|
名为 “elasticsearch” 或 “bitnami/elasticsearch” 的容器 |
|
名为“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“bitnami/mariadb”、“mssql/server”、“mysql”、“bitnami/mysql”、“postgres”或“bitnami/postgresql”的容器 |
|
名为 “osixia/openldap” 的容器 |
|
名为 “mongo” 或 “bitnami/mongodb” 的容器 |
|
名为 “neo4j” 或 “bitnami/neo4j” 的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 的容器 |
|
名为 “apachepulsar/pulsar” 的容器 |
|
名为“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“bitnami/mariadb”、“mssql/server”、“mysql”、“bitnami/mysql”、“postgres”或“bitnami/postgresql”的容器 |
|
名为 “rabbitmq” 或 “bitnami/rabbitmq” 的容器 |
|
名为 “redis” 或 “bitnami/redis” 的容器 |
|
名为 “openzipkin/zipkin” 的容器。 |
自定义图像
有时,您可能需要使用自己的映像版本来提供服务。 您可以使用任何自定义映像,只要其行为方式与标准映像相同即可。 具体而言,标准映像支持的任何环境变量也必须在自定义映像中使用。
如果您的映像使用不同的名称,则可以在文件中使用标签,以便 Spring Boot 可以提供服务连接。
使用 name 的标签提供服务名称。compose.yml
org.springframework.boot.service-connection
例如:
services:
redis:
image: 'mycompany/mycustomredis:7.0'
ports:
- '6379'
labels:
org.springframework.boot.service-connection: redis
跳过特定容器
如果您在 中定义了一个不希望连接到应用程序的容器镜像,则可以使用标签来忽略它。
任何带有 label with 的容器都将被 Spring Boot 忽略。compose.yml
org.springframework.boot.ignore
例如:
services:
redis:
image: 'redis:7.0'
ports:
- '6379'
labels:
org.springframework.boot.ignore: true
使用特定的 Compose 文件
如果您的 compose 文件与应用程序不在同一目录中,或者名称不同,则可以使用 in 或 来指向其他文件。
属性可以定义为精确路径或相对于应用程序的路径。spring.docker.compose.file
application.properties
application.yaml
例如:
-
Properties
-
YAML
spring.docker.compose.file=../my-compose.yml
spring:
docker:
compose:
file: "../my-compose.yml"
等待容器就绪
由 Docker Compose 启动的容器可能需要一些时间才能完全准备就绪。
检查就绪情况的推荐方法是在文件中的服务定义下添加一个部分。healthcheck
compose.yml
由于文件中省略配置的情况并不少见,因此 Spring Boot 还直接检查服务就绪情况。
默认情况下,当可以与容器的映射端口建立 TCP/IP 连接时,容器被视为准备就绪。healthcheck
compose.yml
您可以通过在文件中添加标签来按容器禁用此功能。org.springframework.boot.readiness-check.tcp.disable
compose.yml
例如:
services:
redis:
image: 'redis:7.0'
ports:
- '6379'
labels:
org.springframework.boot.readiness-check.tcp.disable: true
您还可以更改 or 文件中的超时值:application.properties
application.yaml
-
Properties
-
YAML
spring.docker.compose.readiness.tcp.connect-timeout=10s
spring.docker.compose.readiness.tcp.read-timeout=5s
spring:
docker:
compose:
readiness:
tcp:
connect-timeout: 10s
read-timeout: 5s
总超时可使用 进行配置。spring.docker.compose.readiness.timeout
控制 Docker Compose 生命周期
默认情况下, Spring Boot 会在应用程序启动时和关闭时调用。
如果您希望使用不同的生命周期管理,则可以使用该属性。docker compose up
docker compose stop
spring.docker.compose.lifecycle-management
支持以下值:
-
none
- 不要启动或停止 Docker Compose -
start-only
- 在应用程序启动时启动 Docker Compose 并保持运行 -
start-and-stop
- 在应用程序启动时启动 Docker Compose,在 JVM 退出时停止它
此外,还可以使用该属性来更改是否使用 or。
允许您配置 if 或 is used。spring.docker.compose.start.command
docker compose up
docker compose start
spring.docker.compose.stop.command
docker compose down
docker compose stop
以下示例显示了如何配置生命周期管理:
-
Properties
-
YAML
spring.docker.compose.lifecycle-management=start-and-stop
spring.docker.compose.start.command=start
spring.docker.compose.stop.command=down
spring.docker.compose.stop.timeout=1m
spring:
docker:
compose:
lifecycle-management: start-and-stop
start:
command: start
stop:
command: down
timeout: 1m
激活 Docker Compose 配置文件
Docker Compose 配置文件与 Spring 配置文件类似,因为它们允许您针对特定环境调整 Docker Compose 配置。
如果要激活特定的 Docker Compose 配置文件,可以在 or 文件中使用该属性:spring.docker.compose.profiles.active
application.properties
application.yaml
-
Properties
-
YAML
spring.docker.compose.profiles.active=myprofile
spring:
docker:
compose:
profiles:
active: "myprofile"
在测试中使用 Docker Compose
默认情况下,Spring Boot 的 Docker Compose 支持在运行测试时处于禁用状态。
要在测试中启用 Docker Compose 支持,请设置为 .spring.docker.compose.skip.in-tests
false
使用 Gradle 时,还需要将依赖项的配置从 更改为 :spring-boot-docker-compose
developmentOnly
testAndDevelopmentOnly
dependencies {
testAndDevelopmentOnly("org.springframework.boot:spring-boot-docker-compose")
}
Testcontainers 支持
除了使用 Testcontainers 进行集成测试外,还可以在开发时使用它们。 接下来的部分将提供有关这方面的更多详细信息。
在开发时使用 Testcontainers
这种方法允许开发人员为应用程序所依赖的服务快速启动容器,无需手动预置数据库服务器等内容。 以这种方式使用 Testcontainers 可提供类似于 Docker Compose 的功能,但您的容器配置是 Java 而不是 YAML。
要在开发时使用 Testcontainers,您需要使用 “test” classpath 而不是 “main” 来启动应用程序。 这将允许您访问所有声明的测试依赖项,并为您提供一个自然的位置来编写测试配置。
要创建应用程序的测试可启动版本,您应该在目录中创建一个 “Application” 类。
例如,如果您的主应用程序位于 中,则应创建src/test
src/main/java/com/example/MyApplication.java
src/test/java/com/example/TestMyApplication.java
该类可以使用该方法启动真实的应用程序:TestMyApplication
SpringApplication.from(…)
import org.springframework.boot.SpringApplication;
public class TestMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main).run(args);
}
}
您还需要定义要与应用程序一起启动的 Container
实例。
为此,您需要确保已将模块添加为依赖项。
完成后,您可以创建一个 @TestConfiguration
类,该类为要启动的容器声明@Bean
方法。spring-boot-testcontainers
test
您还可以使用 @ServiceConnection
注释 @Bean
方法,以便创建 ConnectionDetails
bean。
有关支持的技术的详细信息,请参阅服务连接部分。
典型的 Testcontainers 配置如下所示:
import org.testcontainers.containers.Neo4jContainer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {
@Bean
@ServiceConnection
public Neo4jContainer<?> neo4jContainer() {
return new Neo4jContainer<>("neo4j:5");
}
}
Container bean 的生命周期由 Spring Boot 自动管理。
容器将自动启动和停止。 |
您可以使用该属性来更改容器的启动方式。
默认情况下,使用启动,但您也可以选择是否希望并行启动多个容器。spring.testcontainers.beans.startup sequential parallel |
定义测试配置后,您可以使用该方法将其附加到测试Starters:with(…)
import org.springframework.boot.SpringApplication;
public class TestMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main).with(MyContainersConfiguration.class).run(args);
}
}
现在,您可以像启动任何常规 Java 方法应用程序一样启动应用程序,以启动应用程序及其需要运行的容器。TestMyApplication
main
您可以使用 Maven 目标或 Gradle 任务从命令行执行此操作。spring-boot:test-run bootTestRun |
在开发时提供动态属性
如果你想在开发时从 Container
@Bean
方法中提供动态属性,你可以通过注入 DynamicPropertyRegistry
来实现。
其工作方式与您可以在测试中使用的 @DynamicPropertySource
注解类似。
它允许您添加在容器启动后将变为可用的属性。
典型的配置如下所示:
import org.testcontainers.containers.MongoDBContainer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;
@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {
@Bean
public MongoDBContainer mongoDbContainer(DynamicPropertyRegistry properties) {
MongoDBContainer container = new MongoDBContainer("mongo:5.0");
properties.add("spring.data.mongodb.host", container::getHost);
properties.add("spring.data.mongodb.port", container::getFirstMappedPort);
return container;
}
}
建议尽可能使用 @ServiceConnection ,但是,对于尚不支持 @ServiceConnection 的技术,动态属性可能是一个有用的后备选项。 |
导入 Testcontainer 声明类
使用 Testcontainers 时的一种常见模式是将 Container
实例声明为静态字段。
通常,这些字段直接在 test 类上定义。
它们也可以在父类或测试实现的接口上声明。
例如,以下接口声明和容器:MyContainers
mongo
neo4j
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
public interface MyContainers {
@Container
@ServiceConnection
MongoDBContainer mongoContainer = new MongoDBContainer("mongo:5.0");
@Container
@ServiceConnection
Neo4jContainer<?> neo4jContainer = new Neo4jContainer<>("neo4j:5");
}
如果您已经以这种方式定义了容器,或者您只是喜欢这种样式,则可以导入这些声明类,而不是将容器定义为@Bean
方法。
为此,请将 @ImportTestcontainers
注解添加到您的测试配置类中:
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
@TestConfiguration(proxyBeanMethods = false)
@ImportTestcontainers(MyContainers.class)
public class MyContainersConfiguration {
}
如果您不打算使用服务连接功能,但想改用 @DynamicPropertySource ,请从 Container (容器 ) 字段中删除 @ServiceConnection 注释。
您还可以将 @DynamicPropertySource 带注释的方法添加到声明类中。 |
在开发时将 DevTools 与 Testcontainers 结合使用
使用 devtools 时,您可以使用 @RestartScope
注释 bean 和 bean 方法。
当 devtools 重新启动应用程序时,不会重新创建此类 bean。
这对于 Testcontainer Container
bean 特别有用,因为尽管应用程序重新启动,它们仍会保持其状态。
import org.testcontainers.containers.MongoDBContainer;
import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {
@Bean
@RestartScope
@ServiceConnection
public MongoDBContainer mongoDbContainer() {
return new MongoDBContainer("mongo:5.0");
}
}
如果你使用的是 Gradle 并希望使用此功能,则需要将依赖项的配置从 更改为 。
使用默认范围 ,该任务不会获取代码中的更改,因为 devtools 未处于活动状态。spring-boot-devtools developmentOnly testAndDevelopmentOnly developmentOnly bootTestRun |