baeldung 2025-12-03
1. 概述
在本教程中,我们将学习如何将 Spring Boot 应用程序升级到 3.0 版本。要成功迁移至 Spring Boot 3,必须确保当前使用的 Spring Boot 版本为 2.7,且 Java 版本为 17。
2. 核心变更
Spring Boot 3.0 是该框架的一个重要里程碑,对其核心组件进行了多项重大修改。
2.1 配置属性(Configuration Properties)
部分配置属性的键名已更改:
spring.redis已移至spring.data.redisspring.data.cassandra已移至spring.cassandraspring.jpa.hibernate.use-new-id-generator已被移除server.max.http.header.size已更名为server.max-http-request-header-sizespring.security.saml2.relyingparty.registration.{id}.identity-provider的支持已被移除
为了识别这些属性,我们可以在 pom.xml 中添加 spring-boot-properties-migrator 依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
最新版本的
spring-boot-properties-migrator可从 Maven Central 获取。
该依赖会在应用启动时生成一份报告,列出所有已弃用的属性名称,并在运行时临时迁移这些属性。
2.2 Jakarta EE 10
Jakarta EE 10 的新版本为 Spring Boot 3 带来了相关依赖的更新:
- Servlet 规范升级至 6.0
- JPA 规范升级至 3.1
如果我们通过排除 spring-boot-starter 中的依赖来手动管理这些库,则需要确保它们已更新。
首先更新 JPA 依赖:
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
最新版本的
jakarta.persistence-api可从 Maven Central 获取。
接着更新 Servlet 依赖:
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
</dependency>
最新版本的
jakarta.servlet-api可从 Maven Central 获取。
除了依赖坐标的变化外,Jakarta EE 现在使用 jakarta 包名替代了原来的 javax。因此,在更新依赖后,可能还需要更新代码中的 import 语句。
2.3 Hibernate
如果我们通过排除 spring-boot-starter 中的依赖来手动管理 Hibernate,则需确保其版本已更新:
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.1.4.Final</version>
</dependency>
最新版本的
hibernate-core可从 Maven Central 获取。
2.4 其他变更
此外,本次发布还包含以下重要的核心层变更:
- 图像横幅(Image banner)支持被移除:现在仅支持通过
banner.txt文件定义自定义横幅。 - 日志日期格式器:Logback 和 Log4J2 的默认日期格式现为
yyyy-MM-dd’T’HH:mm:ss.SSSXXX。如果希望恢复旧格式,需在application.yaml中设置logging.pattern.dateformat属性。 @ConstructorBinding仅作用于构造函数级别:对于@ConfigurationProperties类,不再需要在类级别上使用@ConstructorBinding,应将其移除。但如果类或 record 有多个构造函数,则必须在目标构造函数上使用@ConstructorBinding来指定用于属性绑定的构造函数。
3. Web 应用变更
假设我们的应用是一个 Web 应用,还需考虑以下变更。
3.1 尾部斜杠匹配配置
新版本弃用了尾部斜杠匹配的配置选项,并默认将其设为 false。
例如,定义一个简单的控制器:
@RestController
@RequestMapping("/api/v1/todos")
@RequiredArgsConstructor
public class TodosController {
@GetMapping("/name")
public List<String> findAllName(){
return List.of("Hello","World");
}
}
现在访问 GET /api/v1/todos/name/(带尾部斜杠)将不再匹配,默认返回 HTTP 404 错误。
我们可以通过实现 WebMvcConfigurer(或响应式服务中的 WebFluxConfigurer)来启用尾部斜杠匹配:
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(true);
}
}
3.2 响应头大小限制
如前所述,server.max.http.header.size 已被弃用,取而代之的是 server.max-http-request-header-size,它仅限制请求头大小。若还需限制响应头大小,需定义如下 Bean:
@Configuration
public class ServerConfiguration implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setProperty("maxHttpResponseHeaderSize", "100000");
}
});
}
}
若使用 Jetty 而非 Tomcat,应将
TomcatServletWebServerFactory替换为JettyServletWebServerFactory。注意:其他内嵌 Web 容器不支持此功能。
3.3 其他变更
Web 应用层面还有以下重要变更:
- 优雅关闭阶段调整:
SmartLifecycle实现的优雅关闭阶段已更新。Spring 现在在SmartLifecycle.DEFAULT_PHASE – 2048阶段启动优雅关闭,并在SmartLifecycle.DEFAULT_PHASE – 1024阶段停止 Web 服务器。
4. Actuator 变更
Actuator 模块引入了一些重要变更。
4.1 Actuator 端点数据脱敏
在旧版本中,Spring Framework 会自动对 /env 和 /configprops 端点中某些敏感键的值进行掩码处理。而在新版本中,Spring 默认对所有键的值进行掩码,以增强安全性。
可通过以下属性自定义行为:
management.endpoint.env.show-values(用于/env端点)management.endpoint.configprops.show-values(用于/configprops端点)
可选值包括:
NEVER:不显示任何值ALWAYS:显示所有值WHEN_AUTHORIZED:仅在用户授权时显示所有值(JMX 下所有用户均视为授权;HTTP 下需特定角色)
4.2 其他变更
- JMX 端点暴露:JMX 默认仅暴露
health端点。可通过management.endpoints.jmx.exposure.include/exclude自定义。 httptrace端点重命名:/httptrace已重命名为/httpexchanges。- 独立的 ObjectMapper:Actuator 端点的响应序列化现在使用独立的
ObjectMapper实例。可通过设置management.endpoints.jackson.isolated-object-mapper=false禁用此行为。
5. Spring Security
Spring Boot 3 仅兼容 Spring Security 6。
在升级到 Spring Boot 3.0 之前,应先将 Spring Boot 2.7 应用升级到 Spring Security 5.8,然后再升级到 Spring Security 6 和 Spring Boot 3。
本版本引入了若干重要变更:
ReactiveUserDetailsService不再自动配置:当存在AuthenticationManagerResolver时,不再自动配置ReactiveUserDetailsService。- SAML2 依赖方配置变更:此前位于
spring.security.saml2.relyingparty.registration.{id}.identity-provider下的属性已不再支持。应改用新属性spring.security.saml2.relyingparty.registration.{id}.asserting-party。
6. Spring Batch
Spring Batch 模块也引入了若干重要变更。
6.1 @EnableBatchProcessing 不再推荐使用
过去可通过在配置类上添加 @EnableBatchProcessing 注解启用 Spring Batch 的自动配置。但在新版本中,若希望使用自动配置,则不建议使用此注解。
实际上,使用该注解(或定义实现了 DefaultBatchConfiguration 的 Bean)会导致自动配置“退避”(back off)。
6.2 多作业(Jobs)执行方式变更
过去可同时运行多个批处理作业。但新版本中,若自动配置检测到上下文中存在单个作业,则会在应用启动时自动执行。
若上下文中存在多个作业,则必须通过 spring.batch.job.name 属性指定启动时要执行的作业名称。因此,若需运行多个作业,应为每个作业创建独立的应用程序。
或者,也可使用 Quartz、Spring Scheduler 等调度器来安排作业执行。
7. HttpClient 变更
Spring Boot 3 将其内部 HTTP 栈升级为使用 Apache HttpClient 5.x,取代了旧版的 4.x。因此,若应用通过 RestTemplate 和 HttpComponentsClientHttpRequestFactory 自定义 HTTP 客户端,则需更新配置。
此升级引入了多项破坏性变更,尤其在 HttpClient 5.4 及更高版本中,采用了基于构建器(builder-based)的配置方式,并更紧密地对齐 Java 标准安全 API。
7.1 使用 HttpClient 4.x 的旧配置(已失效)
升级前的典型配置如下:
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate getRestTemplate() {
CloseableHttpClient httpClient = HttpClients.custom().build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
requestFactory.setConnectTimeout(30000);
requestFactory.setReadTimeout(30000);
requestFactory.setConnectionRequestTimeout(30000);
return new RestTemplate(requestFactory);
}
}
但在 Spring Boot 3 中,此方式因与 HttpClient 5 不兼容而失效。
7.2 为何在 Spring Boot 3 中失效
基于 Apache HttpClient 4.x 的自定义 HTTP 配置与 Spring Boot 3 所依赖的 HttpClient 5.x 不兼容,主要问题包括:
HttpComponentsClientHttpRequestFactory现在期望传入 5.x 的CloseableHttpClient,而非 4.x 版本。setConnectTimeout()、setReadTimeout()等超时方法已被弃用或静默忽略。- 运行时可能出现
NoSuchMethodError、ClassNotFoundException或org.apache.http.*类不兼容等问题。
这是因为底层 API 已被重新设计,而不仅仅是重构。例如,大多数类已从 org.apache.http.*(4.x)迁移到 org.apache.hc.*(5.x),且配置模型转向了构建器风格,并更贴近 Java 原生 SSL 概念。
为确保兼容性,必须更新依赖并重构 HTTP 客户端配置以匹配 HttpClient 5.x 的新 API。
7.3 迁移到 HttpClient 5.x(5.4 之前版本)
对于 5.4 之前的版本,可使用如下配置:
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(30))
.setResponseTimeout(Timeout.ofSeconds(30))
.setConnectionRequestTimeout(Timeout.ofSeconds(30))
.build();
CloseableHttpClient client = HttpClients.custom()
.setDefaultRequestConfig(config)
.build();
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
}
}
同时,需更新依赖:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
7.4 迁移到 HttpClient 5.4 及更高版本
从 HttpClient 5.4 开始,Apache 引入了更现代化、模块化的配置模型,更贴近 Java 平台 API,并弃用了如 setConnectTimeout() 和 setSSLHostnameVerifier() 等方法。客户端配置现在依赖构建器 API,提供更清晰的连接池、超时设置和扩展机制。
以下示例展示了如何使用 HttpClient 5.4+ 配置 RestTemplate:
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
try {
// 超时配置
SocketConfig socketConfig = SocketConfig.custom()
.setSoTimeout(Timeout.ofSeconds(30)) // 读取超时
.build();
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(30)) // 连接超时
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.ofSeconds(30)) // 连接池等待超时
.build();
// 连接池配置
PoolingHttpClientConnectionManager connectionManager =
PoolingHttpClientConnectionManagerBuilder.create()
.setMaxConnPerRoute(20)
.setMaxConnTotal(100)
.setDefaultSocketConfig(socketConfig)
.setDefaultConnectionConfig(connectionConfig)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
} catch (Exception e) {
throw new IllegalStateException("Failed to configure RestTemplate", e);
}
}
}
此新方法的关键变化包括:
- 超时配置:使用
TimeoutAPI 在SocketConfig、ConnectionConfig和RequestConfig中设置,取代旧的 setter 方法。 - 连接池:推荐使用
PoolingHttpClientConnectionManagerBuilder构建器,而非直接实例化PoolingHttpClientConnectionManager。 - 构建器风格配置:整体 API 设计更符合现代 Java 风格,强调关注点分离和更好的可扩展性。
通过迁移到此新配置模型,应用不仅能完全兼容 Spring Boot 3,还能受益于 HttpClient 5.4+ 引入的模块化、清晰性和安全性改进。
8. 结论
本文介绍了如何将 Spring Boot 2.7 应用迁移到 3.0 版本,重点涵盖了 Spring 环境的核心组件变更。此外,Spring Session、Micrometer、依赖管理等模块也发生了若干变化。