从 2.x 和 3.x 迁移到 4.x
本教程共 48 篇 · 第 46 篇 · 更新于 2026-08-13 · 约 6 分钟阅读
本节目标:看懂 Spring Boot 2.x、3.x、4.x 之间的差异,学会按官方流程把老项目平滑升级到 4.1.0,并了解 4.x 带来了哪些新东西。
先看版本线
Spring Boot 的版本有自己的生命周期。升级不是选择题,而是迟早要做的事。
- 2.7.x 及更早:已停止维护,建议尽快离开。
- 3.5.16(2026-06-25):3.x 维护线的最后一个 OSS 补丁,社区支持已结束,仅剩商业支持。
- 4.0.7:4.0 维护线,负责修 4.0 的小问题。
- 4.1.0:2026-06-10 发布的 GA 版本,本教程的基线。
大版本升级会带来破坏性变化。2.x 到 3.x 是一次「伤筋动骨」,3.x 到 4.x 又是一次。本教程主线代码全部基于 4.1.0,这章专门讲「老代码怎么搬」。
2.x → 3.x:javax 到 jakarta 的大迁徙
2.x 升 3.x 最痛的改动,是把整个 Java EE 命名空间从 javax.* 换成了 jakarta.*。
原因是 Oracle 把 Java EE 捐给了 Eclipse 基金会,新名字叫 Jakarta EE。包名必须跟着改,否则依赖会冲突。
// 2.x 时代:javax 包
import javax.persistence.Entity;
import javax.servlet.http.HttpServletRequest;
// 3.x 起:jakarta 包
import jakarta.persistence.Entity;
import jakarta.servlet.http.HttpServletRequest;
改的不只是 import。3.x 还同时做了这些调整:
- Java 基线升到 17,Spring Framework 6。
- Spring Security 6:安全配置改为 Lambda DSL 写法。
- 配置键改名:
spring.redis.*移到spring.data.redis.*,server.max.http.header.size改为server.max-http-request-header-size。 - URL 尾斜杠默认不再匹配:
GET /user/不再等于GET /user。 - Actuator 的
/httptrace端点改名/httpexchanges。 - HTTP 客户端升级到 Apache HttpClient 5。
- MySQL 驱动坐标改为
com.mysql:mysql-connector-j。 - Hibernate 升到 6.x,JPA 规范升到 3.1。
这批改动里,配置键变化最容易踩坑。官方给了一个侦探工具,下一节讲。
3.x → 4.x:模块化与新基线
4.0(2025-11-20 发布)基于 Spring Framework 7,底层标准全面升级:
- Jakarta EE 11:Servlet 6.1、JPA 3.2、Bean Validation 3.1。
- 最低 Java 17,官方一等公民支持 Java 25,生产可选 21/25 LTS,Boot 4.x 支持至 26。
- Jackson 3:JSON 库换代,包名从
com.fasterxml.jackson改为tools.jackson。 - RestTemplate 正式弃用,主线用 RestClient / WebClient。
好消息是:3.x 已经是 jakarta.* 了,4.x 不需要再来一次大规模改名。
Starter 改名了
4.x 把框架做了模块化,一批 starter 改了名,语义更精确。最常见的:
| 3.x 旧名 | 4.x 新名 |
|---|---|
spring-boot-starter-web | spring-boot-starter-webmvc |
| 其余技术专属 starter | 同名保留或按新模块拆分 |
旧名字的 POM 会作为「classic」桥接依赖继续存在,但已标记弃用。升级时建议直接换新名,别用桥接凑合。
<!-- 3.x 写法 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 4.x 写法 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
4.x 移除或改名的东西
- 移除 Undertow 嵌入式服务器支持。
- 测试注解
@MockBean、@SpyBean被移除,改用@MockitoBean、@MockitoSpyBean。 @SpringBootTest不再自动装配 MockMvc,需要显式加@AutoConfigureMockMvc。- 移除嵌入式 init.d 风格启动脚本。
- 配置属性又有一轮改名/删除,靠迁移工具定位。
官方推荐的迁移步骤
迁移的节奏比内容更重要。官方建议:一次跨一个大版本,别一口气跳两级。
- 升级前检查。确认 Java 版本满足要求(4.x 需要 17+),构建工具(Maven/Gradle)够新,第三方依赖有 4.x 兼容版本。
- 先升到当前大版本的最后一个小版本。比如 2.7.x 先升 3.5.16,清理掉所有弃用警告,再升 4.1.0。3.x 里标弃用的 API,4.0 里可能直接删了。
- 加 properties-migrator 找配置问题。这是官方提供的运行时诊断工具。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
启动应用后,它会在日志里列出所有改名或删除的配置键,并在运行时临时帮你迁移。
Warning迁移完成后必须删掉这个依赖。它只是过渡工具,留在生产代码里是隐患。
- 批量处理代码差异。
javax.*换jakarta.*(2.x 用户)、Jackson 3 包名、测试注解更名、RestTemplate换RestClient。 - 更新构建文件。换新 starter 名,核对依赖坐标。
- 跑回归测试。接口行为、配置加载、启动日志逐项验证。
大型项目可以借助 OpenRewrite 这类自动化重构工具。它有一整套 Spring Boot 升级 recipe,能自动改包名和配置键,减少手工遗漏。
Note升级前先看一遍官方对应版本的迁移指南和 Release Notes(升级说明永远是发布说明里的第一项)。跨多个版本升级时,中间跳过的每个版本说明都要过一遍,很多坑就藏在里面。
常见坑位对照
迁移路上有几个高频坑,提前对照可以少走弯路。
Jackson 3 包名。4.x 默认 JSON 库换成 Jackson 3,包名从 com.fasterxml.jackson 变成 tools.jackson。代码里直接 new 的 ObjectMapper、自定义的序列化器都要改 import。
// 3.x:com.fasterxml.jackson 包
import com.fasterxml.jackson.databind.ObjectMapper;
// 4.x:tools.jackson 包
import tools.jackson.databind.ObjectMapper;
测试注解更名。@MockBean、@SpyBean 在 4.x 被移除,换成新注解:
// 3.x 写法(已移除)
@MockBean
private UserRepository userRepository;
// 4.x 写法
@MockitoBean
private UserRepository userRepository;
Spring Security 7。Boot 4 配套 Security 7,Security 6 的写法基本兼容,但 lambda DSL 是唯一推荐写法,老的链式 .and() 风格会直接编译不过。
第三方依赖。Lombok、MyBatis、各云厂商 SDK 这些不在 Boot 管理范围内的库,升级前先查它们有没有支持 4.x 的版本,否则会遇到莫名其妙的类冲突。
4.x 新特性总览
迁移不是纯受罪,4.x 也带来实打实的新能力。
- API 版本化:Spring MVC 支持
version属性,同一个路径按版本分发。配置在spring.mvc.apiversion.*,或用ApiVersionConfigurer定制。 - 官方 OpenTelemetry starter:
spring-boot-starter-opentelemetry,指标、链路、日志统一走 OTLP 协议导出,原生镜像也支持。 - HTTP Interface Client:Spring 6 引入、4.x 增强,用接口声明式调用远程 REST 服务,不再手写模板代码。
- JSpecify 编译期空安全:注解驱动,IDE 里就能抓到空指针隐患。
- GraalVM 原生镜像一等公民:AOT 编译路径更顺,启动更快。
- REST Test Client:测试 REST 接口的新客户端,和 HTTP Interface Client 配套使用。
来一个最小的 API 版本化示例,感受 4.x 的新写法:
@RestController
public class VersionController {
@GetMapping("/user", version = "1.0")
public String userV1() {
return "老版本接口";
}
@GetMapping("/user", version = "2.0")
public String userV2() {
return "新版本接口";
}
}
再配合配置选择版本策略:
# 支持哪些版本
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.default=1.0
# 用路径段策略:/1.0/user、/2.0/user
spring.mvc.apiversion.use.path-segment=1
访问路径为 /1.0/user、/2.0/user。path-segment 策略下,版本段由解析器消费,不会作为普通路径变量出现。
小结
迁移的关键词是「按部就班」:先升到老版本线的最新,清干净弃用警告,用 migrator 找配置键,再处理代码差异,最后回归测试。2.x 用户多一道 javax 到 jakarta 的工序;3.x 用户重点看 starter 改名、Jackson 3 和测试注解。升级完成后,记得尝尝 4.x 的 API 版本化和 OpenTelemetry 两道新菜。