Spring Boot 4.0 正式发布:新一代起点到底“新”在哪?(Spring Framework 7 / Java 25 / JSpecify / API 版本管理 / HTTP Service

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)

工程上的真实影响通常是:

  1. 依赖冲突更容易暴露(因为生态统一升级)
  2. 一些"你以前没显式引 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 个升级报错与修复示例(适合直接贴到文章里当"实战踩坑篇")。
相关推荐
m0_5649149215 小时前
Altium Designer,AD如何修改原理图右下角图纸标题栏?如何自定义标题栏?自定义原理图模版的使用方法
java·服务器·前端
飞升不如收破烂~15 小时前
# Spring Boot 跨域请求未到达后端问题排查记录
java·spring boot·后端
AllData公司负责人15 小时前
【亲测好用】数据集成管理能力演示
java·大数据·数据库·开源
一路向阳~负责的男人15 小时前
PyTorch / CUDA 是什么?它们的关系?
人工智能·pytorch·python
brevity_souls15 小时前
SQL Server 窗口函数简介
开发语言·javascript·数据库
阿蒙Amon15 小时前
C#每日面试题-值传递和引用传递的区别
java·面试·c#
aloha_78916 小时前
乐信面试准备
java·spring boot·python·面试·职场和发展·maven
火云洞红孩儿16 小时前
零基础:100个小案例玩转Python软件开发!第六节:英语教学软件
开发语言·python
2401_8414956416 小时前
深度卷积生成对抗网络(DCGAN)
人工智能·python·深度学习·神经网络·机器学习·生成对抗网络·深度卷积生成对抗网络
Knight_AL16 小时前
Spring Boot 多模块项目中优雅实现自动配置(基于 AutoConfiguration.imports)
java·spring boot·mybatis