本节目标:把 3.5.x 与 4.1.x 的差异量化成一张对照表,并给出一套能直接用的决策标准,让选型不再靠感觉。
适用版本:Spring Boot 4.1.x(Java 21)
1.3 版本线的选择
前两节回答了两个问题:Boot 是什么、4.x 改了什么。现在那支团队要拍板了——重构用 3.5.x 还是 4.1.x? 选型不能只讲「新版本好」,得把两条线的差异摊开,逐项算账。
1.3.1 把两条线摆到一张表上
先看 pom.xml 里最直观的差别。3.5.x 的父 POM:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.16</version>
<relativePath/>
</parent>
4.1.x 只改版本号,其余结构一致:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
<relativePath/>
</parent>
版本号背后是一整条技术栈。下面这张表是本节的核心,建议反复对照:
| 维度 | 3.5.x(3.5.16) | 4.1.x(4.1.1) |
|---|---|---|
| Spring Framework | 6.2.19 | 7.0.9 |
| Java 基线 | 17+ | 17+(本系列用 21) |
| Jakarta EE | 10 | 11 |
| Servlet | 6.0 | 6.1 |
| Tomcat | 10.1 | 11.0 |
| Jackson | 2(com.fasterxml.jackson) | 3(tools.jackson) |
| Spring Security | 6.x | 7.0 |
| Spring Data | 2024.x | 2025.1 |
| Hibernate | 6.x | 7.2 |
| HikariCP | 5.x/6.x | 7.0 |
| Micrometer | 1.14 | 1.16(4.1 为 1.17) |
| 自动配置模块 | 单一 spring-boot-autoconfigure | 按技术拆分 |
| Web starter 名 | spring-boot-starter-web | spring-boot-starter-webmvc |
| 测试 Mock 注解 | 旧的注入注解(已移除) | 改用 Mockito 系列新注解 |
@SpringBootTest 的 MockMvc | 自带 | 需 @AutoConfigureMockMvc |
| 空安全注解 | org.springframework.lang.Nullable | org.jspecify.annotations.Nullable |
这张表里,真正会逼你改代码的是 Jackson、starter 名、Mock 注解、模块拆分四项;其余多数是「换版本号即可」的平滑升级。
1.3.2 逐项解释差异
光看表还不够,得知道每项差异会带来什么。
Spring Framework 6.2 → 7.0。 这是最大的底层跳跃。Framework 7 带来虚拟线程的深度支持、JSpecify 空安全注解、以及一批 API 的清理。对业务代码影响相对小,但对框架扩展点(自定义 BeanPostProcessor、WebMvcConfigurer)影响较大。
Servlet 6.0 → 6.1。 容器基线抬升会淘汰部分旧容器实现。如果你现在依赖的是非 Tomcat 的容器方案,升级前必须确认它在 Servlet 6.1 下是否仍受支持,这是硬门槛。
Jackson 2 → 3。 影响面最广,1.2 节已展开。简单说:包名换、ObjectMapper 换 JsonMapper、自定义 bean 不再覆盖自动配置。
模块拆分。 影响的是你的日志配置、logging.level、以及反射/扫描相关代码。日常业务开发感知不强,但排查问题时包名会不一样。
starter 改名。 影响 pom.xml,是一次性的机械改动,风险低。
Mock 注解变更。 影响所有测试代码,量大但改动规则清晰。
1.3.3 本机双线实测数据
理论差异讲完,看真实数据。我在同一台机器上(JDK 21.0.12.1+1 LTS + Maven 3.9.12,2026-10-09)用同一个最小 Web 应用分别跑了两条线:
| 指标 | 4.1.1(主线) | 3.5.16(迁移对照) |
|---|---|---|
| 首次构建(含拉依赖) | 73 s | 38 s |
| 后续构建(依赖已缓存) | ~38 s | 38 s |
| 启动耗时(Started in) | ~1.1 s | ~0.84 s |
| 内嵌 Tomcat 版本 | 11.0.24 | 10.1.x |
| HTTP 接口响应 | 正常 | 正常 |
| 首次构建产物大小 | 略大(模块更多) | 略小 |
几点解读:
- 首次构建 73 s 主要是拉依赖,4.x 模块拆细后需要下载的 JAR 数量更多,首次会更慢;依赖缓存后两条线差距很小。
- 启动耗时 4.1.1 比 3.5.16 慢约 0.2–0.3 s,差异在可接受范围内,且属于「启动一次、运行很久」的场景,对生产影响可忽略。
- 两条线在本机都跑通并有正常 HTTP 响应,说明 4.1.1 的可用性没有疑问。
下面是 4.1.1 的真实启动日志片段(原样贴出,方便你对照自己机器上的输出):
:: Spring Boot :: (v4.1.1)
2026-10-09T15:42:06.435+08:00 INFO 43496 --- [ main] com.example.probe.ProbeApplication : Starting ProbeApplication v0.0.1-SNAPSHOT using Java 21.0.12.1 with PID 43496
2026-10-09T15:42:07.059+08:00 INFO 43496 --- [ main] b.w.c.s.WebApplicationContextInitializer : Root WebApplicationContext: initialization completed in 589 ms
2026-10-09T15:42:07.285+08:00 INFO 43496 --- [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2026-10-09T15:42:07.421+08:00 INFO 43496 --- [ main] com.example.probe.ProbeApplication : Started ProbeApplication in 1.101 seconds (process running for 1.749)
Started ... in 1.101 seconds 就是上表「~1.1 s」的来源。
1.3.4 决策树:三类团队怎么选
把差异落到决策上。下面是一棵可以直接照着走的树:
问题 1:是全新项目吗?
├── 是 → 问题 2
└── 否(存量项目)→ 跳到问题 3
问题 2:团队能接受 Java 17+(最好是 21)吗?
├── 能 → 选 4.1.x ← 新项目默认推荐
└── 不能 → 先解决 JDK 升级,再选 4.1.x
问题 3(存量):当前项目依赖已移除的组件吗?
(部分旧容器实现、低使用率集成等)
├── 依赖 → 留在 3.5.x,先找替代方案
└── 不依赖 → 问题 4
问题 4(存量):是否属于受监管行业或有强制版本冻结流程?
├── 是 → 问题 5
└── 否 → 问题 6
问题 5:新大版本是否已通过内部合规审查?
├── 已通过 → 可规划升级 4.1.x
└── 未通过 → 留在 3.5.x,等审查完成
问题 6:Jackson 定制 / 第三方 SDK 是否已适配 4.x?
├── 已适配 → 升级 4.1.x
└── 未适配 → 留在 3.5.x,等生态跟进
三条结论:
| 团队类型 | 推荐 | 理由 |
|---|---|---|
| 新项目 / 教学 | 4.1.x | 无历史包袱,一次学新写法,避免二次迁移 |
| 一般存量项目 | 评估后升 4.1.x | 先做依赖与 Jackson 影响面评估,成本可控就升 |
| 受监管行业 / 依赖已移除组件 | 3.5.x | 合规周期与替代方案成本高于升级收益 |
1.3.5 存量项目迁移的推荐路径
如果那支团队决定从 3.x 升到 4.1,推荐按这个顺序推进,而不是一步到位:
- 先升到 3.5.16,在 3.x 内部把所有已废弃的写法清干净——这样升级 4.x 时少一类报错。
- 对齐 JDK 到 21,确认构建与测试在 21 上全绿。
- 用
spring-boot-starter-classic过渡,先让旧 starter 名能编过,再逐个替换成新名。 - 处理 Jackson 3:把自定义
ObjectMapper改成JsonMapperBuilderCustomizer,改import包名。 - 重写测试注解:换成 Mockito 系列新注解,并补上
@AutoConfigureMockMvc。 - 逐模块验证:从无状态服务开始,最后动有数据库与安全逻辑的模块。
这个顺序的核心是把「一次性大爆炸」拆成「可回滚的小步」。第 11 章会给出更完整的迁移清单,本节先建立路径感。
1.3.6 三个常见选型误区
选型阶段最容易踩的坑,往往不是技术判断错,而是被几个似是而非的说法带偏:
| 误区 | 为什么错 | 正确做法 |
|---|---|---|
| 「版本号越大越先进,无脑选最新的」 | 大版本升级有实际成本,收益不一定覆盖成本 | 按 1.3.4 的决策树逐项判断 |
| 「旧版本马上就没支持了,必须立刻升」 | 3.5.x 仍是受支持分支,不是「过期产品」 | 查官方支持周期,算清时间窗口再排期 |
| 「升级就是改个版本号,一天能搞定」 | Jackson 3、测试注解、starter 名都要动 | 预留至少一到两周,含回归测试 |
第三条尤其要警惕。1.3.1 那张表里,光「会逼你改代码」的就有四项,其中 Jackson 3 的包名迁移几乎会触碰所有序列化相关的文件。低估迁移工作量,是升级项目失败最常见的原因。
1.3.7 本套书怎么读
本套书主线是 4.1.x。所有正文示例、命令、输出,默认都按 4.1.x + Java 21 书写。这样做的理由很直接:新项目会越来越多地落在 4.x,教学应该对准未来。
但考虑到大量存量项目仍在 3.x,遇到两条线写法不同的地方,书中会单独标注。标注格式统一为:
3.x 差异:……(例如 Web starter 在 3.x 叫
spring-boot-starter-web,4.x 改为spring-boot-starter-webmvc)
你需要做的只有一件事:如果你是 3.x 读者,看到这类标注时切换成旧写法即可,其余内容通用。这样一本教材能同时服务两条线的读者,而不必拆成两本。
不同起点的读者可以按下面的方式取用本书:
| 你的情况 | 建议读法 |
|---|---|
| 完全新手,从零学 | 按顺序从头读,全部示例按 4.1.x 敲一遍 |
| 3.x 老手,只想补 4.x 差异 | 精读第 1 章与第 11 章,其余章节只看「3.x 差异」标注 |
| 正在做升级迁移 | 重点读第 1、4、7、11 章,其余作为查漏 |
| 只想快速上手写接口 | 读第 2、3、8 章,遇到不懂的原理再回看第 4、5 章 |
无论哪种读法,动手敲代码都是不可省略的一步。Spring Boot 的知识点密度不高,但自动配置的「隐性行为」很多,只有亲自跑过、看过日志,才会真正建立直觉。
1.3.8 一条通用建议:锁定版本
无论选哪条线,都建议锁定到具体补丁版本,而不是用范围。在 Maven 里,父 POM 写死 4.1.1 就够;不要用 [4.1.0,4.2.0) 这种区间。理由是:
- 补丁版本可能引入行为变更,锁定后升级是可预期的动作。
- CI 构建应当可复现,浮动版本会让「昨天能过、今天挂」变成常态。
- 升级动作应当显式提交,走代码评审,而不是构建时偷偷发生。
<!-- 推荐:写死补丁版本 -->
<version>4.1.1</version>
<!-- 不推荐:区间会随仓库变化而漂移 -->
<version>[4.1.0,4.2.0)</version>
对 4.x 这种仍在快速演进的大版本,锁定版本尤其重要——它把「升级」从一个不可控事件变成一个你能安排时间表的动作。
1.3.9 学完本节你应该能回答的问题
- 3.5.x 与 4.1.x 在 Spring Framework、Servlet、Tomcat 上分别是什么版本?(1.3.1)
- 哪四项差异会真正逼你改代码?(1.3.1)
- 本机实测里,4.1.1 的首次构建为什么比 3.5.16 慢?(1.3.3)
- 存量项目升级推荐按什么顺序推进?(1.3.5)
- 「升级就是改个版本号」为什么是误区?(1.3.6)
- 本套书的主线版本是哪条,3.x 读者该怎么读?(1.3.7)
把这三个问题串起来——Boot 是什么、4.x 改了什么、选哪条线——第 1 章的技术选型任务就完成了。接下来要动真格:搭一个能跑起来的环境。
小结
- 3.5.x(3.5.16)与 4.1.x(4.1.1)的核心差异集中在 Spring Framework(6.2.19 → 7.0.9)、Servlet(6.0 → 6.1)、Tomcat(10.1 → 11.0)、Jackson(2 → 3)四项。
- 真正需要改代码的是 Jackson 3、starter 改名、Mock 注解变更、模块拆分四处,其余多为平滑升级。
- 本机实测(JDK 21.0.12.1 + Maven 3.9.12):4.1.1 首次构建 73 s、后续 ~38 s、启动 ~1.1 s;3.5.16 构建 38 s、启动 ~0.84 s,两条线均跑通。
- 决策标准:新项目与教学选 4.1.x;一般存量项目评估后升级;受监管行业或依赖已移除组件的项目留在 3.5.x。
- 存量迁移推荐「先清废弃写法 → 对齐 JDK 21 → 过渡 starter → 改 Jackson → 改测试注解 → 逐模块验证」。
- 本套书主线为 4.1.x,两条线写法不同处会以「3.x 差异」标注。
- 无论选哪条线,都应锁定到具体补丁版本,保证构建可复现。
选型定了,就该把机器准备好。下一节我们从零开始装 JDK 21 与 Maven,并把第一条 Spring Boot 项目跑起来。
阅读导航:上一节:1.2 Spring Boot 4 带来了什么 · 下一节:2.1 JDK 21 与 Maven 环境准备 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。