Spring Boot 4.0 正式发布:新一代起点到底"新"在哪?(Spring Framework 7 / Java 25 / JSpecify / API 版本管理 / HTTP Service Clients)
2025 年 11 月,Spring Boot 4.0.0 GA 悄悄发布。它不是"又一波依赖升级"那么简单,而是一次基线换代 + 体系补齐 :从 Java/Jakarta 基线、空安全体系,到 API 版本管理、声明式 HTTP Client,再到模块拆分与生态对齐,整体都更像 Spring Boot 进入了一个新世代。 (Home)
1. 先把结论摆在前面:4.0 是"换代",不是"升级"
Spring Framework 7.0 是 Spring 的新一代基础设施,它明确以 Java 25 为重点 、同时 保留 Java 17 baseline ,并升级到 Jakarta EE 11 (Servlet 6.1、JPA 3.2、Bean Validation 3.1 等),而 Spring Boot 4.0 正是建立在这套基线上。 (Home)
Spring Boot 4.0 发布公告把几个最关键点总结得很直白:代码库模块化 、JSpecify 空安全 、Java 25 一等公民支持 、以及 API 版本管理与 HTTP Service Clients 。 (Home)
2. 基线变化:你升级踩坑,大多都来自这里
2.1 Java 版本策略:Java 17 还能用,但"建议你上 25"
- Spring Boot 4.0 要求 Java 17+ 。 (GitHub)
- Spring Framework 7.0/Boot 4.0 强调对 Java 25 的拥抱 ,但同时保留 Java 17 baseline,便于企业逐步迁移。 (Home)
这意味着:
- 你的生产集群短期还在 Java 17:可以升级 Boot 4
- 但想吃到一些"新红利"(例如更顺滑的虚拟线程落地、生态最新适配),上 Java 25 会更舒服
2.2 Jakarta EE 11 + Servlet 6.1:服务器容器直接"换档"
Spring Framework 7.0 明确把 Servlet 6.1 作为 baseline,并指出需要部署到 Tomcat 11+ / Jetty 12.1+ 这类新容器。 (GitHub)
Undertow 为什么被移除?
因为 Undertow 还没兼容 Servlet 6.1 ,所以 Boot 4.0 直接砍掉 Undertow 支持 (包括 starter、embedded server 能力)。 (GitHub)
现实影响:以前
spring-boot-starter-undertow的项目,升级 4.0 基本等价于"必须换容器"。
3. 开发者最该关注的 6 个"真新特性"
3.1 HTTP Service Clients:终于不用手写一堆模板代码了
Boot 4.0 为 HTTP Service Clients 提供了自动配置与配置属性支持:你只写接口,Spring 帮你生成实现。 (GitHub)
接口定义示例(最小可用版) (与官方示例一致): (GitHub)
java
import java.util.Map;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;
@HttpExchange(url = "https://echo.zuplo.io")
public interface EchoService {
@PostExchange
Map<?, ?> echo(@RequestBody Map<String, String> message);
}
生产级写法:不要把 URL 写死在注解里(用"分组 + 配置")
Spring Boot 4 的文档给了更工程化的方式:用 @ImportHttpServices 把一组 Client 注册进来,然后用配置注入 base-url、超时、Header 等。 (Home)
注册 HTTP Services(扫描包 + 绑定 group) : (Home)
java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.service.registry.ImportHttpServices;
@SpringBootApplication
@ImportHttpServices(group = "echo", basePackages = "com.example.myclients")
public class MyApplication { }
配置 base-url(避免硬编码) : (Home)
properties
spring.http.serviceclient.echo.base-url=https://echo.zuplo.io
你还可以在同一组里统一配置超时、默认 header、SSL、甚至把 API 版本信息自动塞进请求头 (下面会讲)。 (Home)
3.2 原生 API 版本管理:终于不用各写各的"版本路由方案"了
Boot 4.0 为 Spring MVC / WebFlux 都加入了 API Versioning 的自动配置,核心配置入口是:
spring.mvc.apiversion.*spring.webflux.apiversion.*(GitHub)
Spring Boot 文档给了一个非常直接的例子:用 X-Version 请求头作为版本来源,默认版本为 1.0.0。 (Home)
properties
spring.mvc.apiversion.default=1.0.0
spring.mvc.apiversion.use.header=X-Version
并且,如果你要更强的控制能力,可以自己定义 ApiVersionResolver / ApiVersionParser / ApiVersionDeprecationHandler Bean 来接管解析与废弃策略。 (GitHub)
更"爽"的点:客户端也能自动插版本
HTTP Service Clients 那边同样支持通过配置,把版本自动插入 header: (Home)
properties
spring.http.serviceclient.echo.apiversion.default=1.0.0
spring.http.serviceclient.echo.apiversion.insert.header=X-Version
这很重要:以前你做版本管理,经常只做了"服务端路由",但调用端(服务间调用)依旧要手写版本 header;现在能用配置统一治理。
3.3 JSpecify 空安全:把 NPE 从"线上炸弹"变成"编译期问题"
Spring Framework 7.0 把 Spring 旧的 nullness 注解(JSR-305 语义)逐步转向 JSpecify ,并强调"全面空安全"。 (GitHub)
Boot 4.0 发布公告也把它列为核心变化之一:Portfolio-wide improvements for null safety with JSpecify 。 (Home)
你可以把它理解为:
- 在代码层更明确表达"默认不为 null,只有标注才可为 null"
- 配合静态分析(例如 NullAway 等)能把很多空指针风险提前拦截
对团队价值极高:尤其是多人协作的 SDK/公共组件层,空语义清晰会显著减少"靠约定"的沟通成本。
3.4 虚拟线程:不只是"能开",而是"默认帮你用到位"
Boot 4.0 release notes 里提到一个很实用的点:当你启用
spring.threads.virtual.enabled=true
自动配置的 JDK HttpClient 会默认使用虚拟线程。 (GitHub)
这意味着:
- IO 密集型服务(大量远程调用、数据库/Redis、第三方接口)在虚拟线程下更容易拿到吞吐提升
- 并且它不是"你得自己改一堆代码",而是更偏"配置即收益"
注意:虚拟线程不是银弹。你仍然要关注阻塞点是否可控、连接池是否合理、以及下游是否被你压垮。
3.5 Redis 静态主从:不再强迫你上 Sentinel/Cluster
Boot 4.0 新增 Redis Static Master/Replica 的自动配置(仅 Lettuce 支持),用一个新配置就能指定静态节点: (GitHub)
properties
spring.data.redis.masterreplica.nodes=host1:6379,host2:6379
适合这种场景:
- 你在一个相对稳定的 Redis 主从拓扑里(比如云厂商固定主从)
- 你不想引入 Sentinel/Cluster 的复杂度
- 你只需要"读写分离 / 主从切换由外部保障",应用侧只要正确连就行
3.6 Gradle 9 / 依赖大跃迁 / 模块化:工程侧变化非常集中
- Boot 4.0 明确 支持 Gradle 9 ,并保留 Gradle 8.14+ 支持。 (GitHub)
- 依赖升级极其集中:例如 Jackson 3.0、Hibernate 7.1、Kafka 4.1、Jetty 12.1、Tomcat 11、Kotlin 2.2.20 等都在"核心清单"里。 (GitHub)
- 并且 Boot 4.0 强调"更彻底的模块化",产出更小、更聚焦的 jar/模块。 (Home)
工程上的真实影响通常是:
- 依赖冲突更容易暴露(因为生态统一升级)
- 一些"你以前没显式引 starter 但也能跑"的能力,在模块拆分后可能需要你显式加 starter(Boot migration guide 已经点出来了)。 (GitHub)
4. 升级路线:别头铁,官方建议很明确
4.1 最推荐的路径:先到 3.5.x,再升 4.0
Migration Guide 直接写明:升级前先升到最新 3.5.x ,能显著减少坑(尤其是先清理 3.x 中已废弃 API,因为 4.0 会移除)。 (GitHub)
5. 一份"可复制"的升级 Checklist(建议你照着做)
Step 0:锁定升级窗口 + 做好回滚
- 这是大版本升级:建议以"一个服务一个分支"推进
- 先让 CI 跑通,再做预发/压测
Step 1:先升级到最新 3.5.x
- 目标:提前消化 3.x 的废弃项(4.0 会删) (GitHub)
Step 2:确认基线与容器
- Java ≥ 17(建议 Java 25) (GitHub)
- Servlet 6.1 容器:Tomcat 11+/Jetty 12.1+ (GitHub)
- Undertow:直接迁移(Boot 4.0 不支持) (GitHub)
Step 3:关注 Jackson 3 迁移
Migration Guide 强烈建议尽可能迁移到 Jackson 3,并提供了一个过渡模块 spring-boot-jackson2(但它是 stop-gap,会在未来移除)。 (GitHub)
这里通常是升级中最"费时间"的部分:你需要排查自定义序列化、老 API、以及某些三方库是否还绑死 Jackson 2。
Step 4:关注 HttpMessageConverters 相关变更
Boot 4.0 migration guide 提到 HttpMessageConverters 被弃用,并给了新的 client/server converter customizer 方式。 (GitHub)
如果你项目里有"自定义 converter 注入"之类的老写法,重点回归测试接口序列化。
Step 5:顺手把"新能力"纳入工程规范
- 内部服务调用:试点 HTTP Service Clients(至少替换一两个 RestTemplate/Feign 场景)
- API 演进:统一版本策略(header / param / path),把调用端版本注入也配置化 (Home)
- Redis:如果你是固定主从拓扑,考虑静态主从配置简化方案 (GitHub)
6. 总结:为什么说 Boot 4.0 更像"新世代起点"?
Spring Boot 4.0 的"新",不只是依赖升级,而是把很多过去"你自己造轮子/各团队各写各的"的能力,做成了标准能力:
- 声明式 HTTP Client + 配置化治理(URL/超时/header/版本) (GitHub)
- 原生 API 版本管理 (MVC/WebFlux/客户端一致性) (GitHub)
- JSpecify 空安全体系 ,把可维护性前移到编译期 (GitHub)
- Servlet 6.1 / Jakarta EE 11 基线落地,生态整体换挡(顺带清理 Undertow 等"跟不上"的模块) (GitHub)
- Gradle 9、依赖大跃迁、模块化 ,让工程更现代也更"讲规矩" (GitHub)
如果你愿意,我也可以按你当前项目情况,给你出一份更"落地"的 CSDN 后半篇:
- 从 Boot 3.5 升 4.0 的真实改动点清单(按 Web / Data / JSON / Test / Build 分类)
- 以及最常见的 10 个升级报错与修复示例(适合直接贴到文章里当"实战踩坑篇")。