此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.3! |
开发时服务
开发时服务提供在开发应用程序时运行应用程序所需的外部依赖项。 它们只应在开发时使用,并在部署应用程序时禁用。
Spring Boot 支持两种开发时服务,即 Docker Compose 和 Testcontainers。 接下来的部分将提供有关它们的更多详细信息。
Docker Compose 支持
Docker Compose 是一种流行的技术,可用于为应用程序所需的服务定义和管理多个容器。
一个compose.yml
文件通常在定义和配置服务容器的应用程序旁边创建。
Docker Compose 的典型工作流是运行docker compose up
,在应用程序连接到已启动的服务的情况下处理应用程序,然后运行docker compose down
当你完成时。
这spring-boot-docker-compose
模块可以包含在项目中,以支持使用 Docker Compose 处理容器。
将模块依赖项添加到您的构建中,如以下 Maven 和 Gradle 清单所示:
<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 将执行以下作:
-
搜索
compose.yml
以及工作目录中的其他常见 compose 文件名 -
叫
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 插件时,将excludeDockerCompose property 设置为false .
使用 Gradle 插件时,配置任务的 Classpath 以包含developmentOnly 配置. |
服务连接
服务连接是与任何远程服务的连接。 Spring Boot 的自动配置可以使用服务连接的详细信息,并使用它们来建立与远程服务的连接。 执行此作时,连接详细信息优先于任何与连接相关的配置属性。
当使用 Spring Boot 的 Docker Compose 支持时,将建立与容器映射的端口的服务连接。
Docker Compose 的使用方式通常是将容器内的端口映射到计算机上的临时端口。 例如,Postgres 服务器可以使用端口 5432 在容器内运行,但在本地映射到完全不同的端口。 服务连接将始终发现并使用本地映射的端口。 |
使用容器的映像名称建立服务连接。 目前支持以下服务连接:
连接详细信息 | 匹配时间 |
---|---|
名为 “symptoma/activemq” 或 “apache/activemq-classic” 的容器 |
|
名为 “apache/activemq-artemis” 的容器 |
|
名为 “cassandra” 或 “bitnami/cassandra” 的容器 |
|
名为 “elasticsearch” 或 “bitnami/elasticsearch” 的容器 |
|
名为 “hazelcast/hazelcast” 的容器。 |
|
名为“clickhouse/clickhouse-server”、“bitnami/clickhouse”、“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“bitnami/mariadb”、“mssql/server”、“mysql”、“bitnami/mysql”、“postgres”或“bitnami/postgresql”的容器 |
|
名为 “osixia/openldap” 和 “lldap/lldap” 的容器 |
|
名为 “mongo” 或 “bitnami/mongodb” 的容器 |
|
名为 “neo4j” 或 “bitnami/neo4j” 的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 和 “grafana/otel-lgtm” 的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 和 “grafana/otel-lgtm” 的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 和 “grafana/otel-lgtm” 的容器 |
|
名为 “apachepulsar/pulsar” 的容器 |
|
名为“clickhouse/clickhouse-server”、“bitnami/clickhouse”、“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“bitnami/mariadb”、“mssql/server”、“mysql”、“bitnami/mysql”、“postgres”或“bitnami/postgresql”的容器 |
|
名为 “rabbitmq” 或 “bitnami/rabbitmq” 的容器 |
|
名为 “redis”、“bitnami/redis”、“redis/redis-stack” 或 “redis/redis-stack-server” 的容器 |
|
名为 “openzipkin/zipkin” 的容器。 |
SSL 支持
某些映像开箱即用地启用了 SSL,或者您可能希望为容器启用 SSL 以镜像您的生产设置。 Spring Boot 支持对支持的服务连接进行 SSL 配置。 请注意,您仍然需要自己在容器内运行的服务上启用 SSL,此功能仅在应用程序的客户端配置 SSL。
以下服务连接支持 SSL:
-
Cassandra
-
Couchbase
-
Elasticsearch
-
卡 夫 卡
-
MongoDB 数据库
-
RabbitMQ 函数
-
Redis
要为服务启用 SSL 支持,您可以使用服务标签。
对于基于 JKS 的密钥库和信任库,您可以使用以下容器标签:
-
org.springframework.boot.sslbundle.jks.key.alias
-
org.springframework.boot.sslbundle.jks.key.password
-
org.springframework.boot.sslbundle.jks.options.ciphers
-
org.springframework.boot.sslbundle.jks.options.enabled-protocols
-
org.springframework.boot.sslbundle.jks.protocol
-
org.springframework.boot.sslbundle.jks.keystore.type
-
org.springframework.boot.sslbundle.jks.keystore.provider
-
org.springframework.boot.sslbundle.jks.keystore.location
-
org.springframework.boot.sslbundle.jks.keystore.password
-
org.springframework.boot.sslbundle.jks.truststore.type
-
org.springframework.boot.sslbundle.jks.truststore.provider
-
org.springframework.boot.sslbundle.jks.truststore.location
-
org.springframework.boot.sslbundle.jks.truststore.password
这些标签反映了 SSL 捆绑包的可用属性。
对于基于 PEM 的密钥库和信任库,您可以使用以下容器标签:
-
org.springframework.boot.sslbundle.pem.key.alias
-
org.springframework.boot.sslbundle.pem.key.password
-
org.springframework.boot.sslbundle.pem.options.ciphers
-
org.springframework.boot.sslbundle.pem.options.enabled-protocols
-
org.springframework.boot.sslbundle.pem.protocol
-
org.springframework.boot.sslbundle.pem.keystore.type
-
org.springframework.boot.sslbundle.pem.keystore.certificate
-
org.springframework.boot.sslbundle.pem.keystore.private-key
-
org.springframework.boot.sslbundle.pem.keystore.private-key-password
-
org.springframework.boot.sslbundle.pem.truststore.type
-
org.springframework.boot.sslbundle.pem.truststore.certificate
-
org.springframework.boot.sslbundle.pem.truststore.private-key
-
org.springframework.boot.sslbundle.pem.truststore.private-key-password
这些标签反映了 SSL 捆绑包的可用属性。
以下示例为 redis 容器启用 SSL:
services:
redis:
image: 'redis:latest'
ports:
- '6379'
secrets:
- ssl-ca
- ssl-key
- ssl-cert
command: 'redis-server --tls-port 6379 --port 0 --tls-cert-file /run/secrets/ssl-cert --tls-key-file /run/secrets/ssl-key --tls-ca-cert-file /run/secrets/ssl-ca'
labels:
- 'org.springframework.boot.sslbundle.pem.keystore.certificate=client.crt'
- 'org.springframework.boot.sslbundle.pem.keystore.private-key=client.key'
- 'org.springframework.boot.sslbundle.pem.truststore.certificate=ca.crt'
secrets:
ssl-ca:
file: 'ca.crt'
ssl-key:
file: 'server.key'
ssl-cert:
file: 'server.crt'
自定义图像
有时,您可能需要使用自己的映像版本来提供服务。 您可以使用任何自定义映像,只要其行为方式与标准映像相同即可。 具体而言,标准映像支持的任何环境变量也必须在自定义映像中使用。
如果您的图像使用不同的名称,您可以在compose.yml
文件,以便 Spring Boot 可以提供服务连接。
使用名为org.springframework.boot.service-connection
以提供服务名称。
例如:
services:
redis:
image: 'mycompany/mycustomredis:7.0'
ports:
- '6379'
labels:
org.springframework.boot.service-connection: redis
跳过特定容器
如果您在compose.yml
,则不希望连接到您的应用程序,则可以使用标签来忽略它。
任何标有org.springframework.boot.ignore
将被 Spring Boot 忽略。
例如:
services:
redis:
image: 'redis:7.0'
ports:
- '6379'
labels:
org.springframework.boot.ignore: true
使用特定的 Compose 文件
如果您的 compose 文件与应用程序不在同一目录中,或者名称不同,则可以使用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
文件。
由于这种情况并不少见healthcheck
要省略的配置compose.yml
文件,Spring Boot 还会直接检查服务就绪情况。
默认情况下,当可以与容器的映射端口建立 TCP/IP 连接时,容器被视为准备就绪。
您可以通过添加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
您还可以在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 退出时停止它
此外,您还可以使用spring.docker.compose.start.command
属性来更改docker compose up
或docker compose start
被使用。
这spring.docker.compose.stop.command
允许您配置 ifdocker 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 配置文件,可以使用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 支持,请将 Docker Compose 的spring.docker.compose.skip.in-tests
自false
.
使用 Gradle 时,您还需要更改spring-boot-docker-compose
dependency from (依赖项)developmentOnly
自testAndDevelopmentOnly
:
dependencies {
testAndDevelopmentOnly("org.springframework.boot:spring-boot-docker-compose")
}
Testcontainers 支持
除了使用 Testcontainers 进行集成测试外,还可以在开发时使用它们。 接下来的部分将提供有关这方面的更多详细信息。
在开发时使用 Testcontainers
这种方法允许开发人员为应用程序所依赖的服务快速启动容器,无需手动预置数据库服务器等内容。 以这种方式使用 Testcontainers 可提供类似于 Docker Compose 的功能,但您的容器配置是 Java 而不是 YAML。
要在开发时使用 Testcontainers,您需要使用 “test” classpath 而不是 “main” 来启动应用程序。 这将允许您访问所有声明的测试依赖项,并为您提供一个自然的位置来编写测试配置。
要创建应用程序的测试可启动版本,您应该在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);
}
}
You’ll also need to define the Container
instances that you want to start along with your application.
To do this, you need to make sure that the spring-boot-testcontainers
module has been added as a test
dependency.
Once that has been done, you can create a @TestConfiguration
class that declares @Bean
methods for the containers you want to start.
You can also annotate your @Bean
methods with @ServiceConnection
in order to create ConnectionDetails
beans.
See the service connections section for details of the supported technologies.
A typical Testcontainers configuration would look like this:
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");
}
}
The lifecycle of Container
beans is automatically managed by Spring Boot.
Containers will be started and stopped automatically.
You can use the spring.testcontainers.beans.startup
property to change how containers are started.
By default sequential
startup is used, but you may also choose parallel
if you wish to start multiple containers in parallel.
Once you have defined your test configuration, you can use the with(…)
method to attach it to your test launcher:
import org.springframework.boot.SpringApplication;
public class TestMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main).with(MyContainersConfiguration.class).run(args);
}
}
You can now launch TestMyApplication
as you would any regular Java main
method application to start your application and the containers that it needs to run.
You can use the Maven goal spring-boot:test-run
or the Gradle task bootTestRun
to do this from the command line.
Contributing Dynamic Properties at Development Time
If you want to contribute dynamic properties at development time from your Container
@Bean
methods, define an additional DynamicPropertyRegistrar
bean.
The registrar should be defined using a @Bean
method that injects the container from which the properties will be sourced as a parameter.
This arrangement ensures that container has been started before the properties are used.
A typical configuration would look like this:
import org.testcontainers.containers.MongoDBContainer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistrar;
@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {
@Bean
public MongoDBContainer mongoDbContainer() {
return new MongoDBContainer("mongo:5.0");
}
@Bean
public DynamicPropertyRegistrar mongoDbProperties(MongoDBContainer container) {
return (properties) -> {
properties.add("spring.data.mongodb.host", container::getHost);
properties.add("spring.data.mongodb.port", container::getFirstMappedPort);
};
}
}
Using a @ServiceConnection
is recommended whenever possible, however, dynamic properties can be a useful fallback for technologies that don’t yet have @ServiceConnection
support.
Importing Testcontainers Declaration Classes
A common pattern when using Testcontainers is to declare Container
instances as static fields.
Often these fields are defined directly on the test class.
They can also be declared on a parent class or on an interface that the test implements.
For example, the following MyContainers
interface declares mongo
and neo4j
containers:
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");
}
If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining your containers as @Bean
methods.
To do so, add the @ImportTestcontainers
annotation to your test configuration class:
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
@TestConfiguration(proxyBeanMethods = false)
@ImportTestcontainers(MyContainers.class)
public class MyContainersConfiguration {
}
If you don’t intend to use the service connections feature but want to use @DynamicPropertySource
instead, remove the @ServiceConnection
annotation from the Container
fields.
You can also add @DynamicPropertySource
annotated methods to your declaration class.
Using DevTools with Testcontainers at Development Time
When using devtools, you can annotate beans and bean methods with @RestartScope
.
Such beans won’t be recreated when the devtools restart the application.
This is especially useful for Container
beans, as they keep their state despite the application restart.
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");
}
}
If you’re using Gradle and want to use this feature, you need to change the configuration of the spring-boot-devtools
dependency from developmentOnly
to testAndDevelopmentOnly
.
With the default scope of developmentOnly
, the bootTestRun
task will not pick up changes in your code, as the devtools are not active.