SpringBoot4.0弃用Undertow:性能王者的落幕
前言
Tomcat笑麻了,Jetty默默上位,Undertow用户哭了
最近在帮一个团队做Spring Boot 4.0升级评估的时候,发现了一个让他们措手不及的问题。
“我们项目里用的Undertow,升级到Spring Boot 4.0之后直接启动不了了,报错说找不到Undertow的实现类。这是什么情况?”
我一看报错信息,心里就有数了——Spring Boot 4.0正式移除了对Undertow的支持。
这个小伙伴当场就懵了。
“Undertow不是号称性能最好的嵌入式容器吗?Spring为什么要抛弃它?”
这个问题问得很到位。
今天这篇文章,我就把Spring Boot 4.0弃用Undertow的前因后果、底层原因、迁移方案从头到尾给你拆解一遍。
希望对你会有所帮助。
一、Undertow是怎么“上位”的?
在聊弃用之前,我们先花2分钟回顾一下Undertow是怎么进入Spring Boot生态的。
Spring Boot从很早就支持三种嵌入式Web容器:
Tomcat(默认)——Apache出品,生态最成熟,Spring Boot的亲儿子
Jetty——Eclipse基金会出品,轻量灵活,在某些场景下表现优异
Undertow——Red Hat出品,号称低内存占用、高并发吞吐、天然支持持久连接
Undertow之所以能进入Spring Boot的可选列表,靠的是它的性能优势。
在高并发场景下,Undertow的内存占用比Tomcat低、吞吐量更高,因此吸引了不少追求极致性能的企业项目。
但是,成也性能,败也规范。
二、为什么Spring Boot 4.0要弃用Undertow?
有些小伙伴可能会说:“Undertow性能这么好,Spring团队为什么要抛弃它?这不是自断一臂吗?”
这个问题的答案,不在Spring团队身上,在Servlet规范身上。
2.1 根本原因:Servlet 6.1不兼容
Spring Boot 4.0基于Spring Framework 7构建,强制依赖Servlet 6.1规范。
而Undertow尚未适配Servlet 6.1。
Spring团队在官方文档中明确说明了移除Undertow支持的技术原因:
“Spring Boot 4.0需要一个Servlet 6.1的基线,而Undertow目前尚不兼容。因此,我们放弃了对Undertow的支持。”
这不是Spring团队的主观决策,而是技术生态演进的必然结果。
2.2 深层次原因:Red Hat投入有限
Undertow的主要维护方是Red Hat。
而Red Hat对该项目的投入相对有限,导致Undertow无法及时跟进新规范。
在相关讨论中,Undertow团队成员表示Servlet 6.1的支持工作已经启动,但截至2025年10月,该工作仍处于早期阶段。
Spring Boot团队在GitHub上创建了专门的Issue(#46917)来跟踪这一变更。
在Issue中,团队指出:Undertow尚未适配Servlet 6.1,且其维护团队资源不足、迭代效率低,Spring Boot团队已无法承担过高的适配成本。
简单说就是:我等了你很久,但你一直跟不上,我只能先走了。
2.3 还有一些“隐情”:社区活跃度差距
除了技术兼容性问题,还有一些不那么“官方”的原因:
Undertow社区相对较小,文档、学习资料等方面都不如Tomcat、Jetty丰富
对传统Servlet模型的支持不够完善
Red Hat的资源重心可能在其他项目上
三、Servlet 6.1到底带来了什么变化?
有些小伙伴可能会问:“Servlet 6.1到底有什么新东西,值得Spring Boot这么大动干戈?”
Servlet 6.1于2024年4月作为Jakarta EE 11的核心子规范发布。
相比Servlet 6.0,它带来了多项重要改进:
① ByteBuffer支持
在ServletInputStream和ServletOutputStream中新增了ByteBuffer支持,显著改进了非阻塞I/O能力。
// 使用 ByteBuffer 读取请求数据 ByteBuffer buffer = ByteBuffer.allocate(1024); servletInputStream.read(buffer);② HTTP/2推送功能废弃
Servlet 6.1正式废弃了HTTP/2 Server Push支持。这个功能在现代Web应用中使用率持续下降。
③ 移除SecurityManager相关API
完全删除了对已废弃的Java SecurityManager及相关API的引用。
④ HTTP会话增强机制
提供了新机制,让应用程序能在标准HTTP请求处理之外与HTTP会话交互,特别是为WebSocket场景提供了更好的支持。
⑤ HTTP重定向控制增强
开发者现在对发出HTTP重定向时的状态码和响应体拥有更精细的控制权。
⑥ 敏感请求头安全处理
新增了HttpServlet.isSensitiveHeader方法,用于识别需要保护的敏感请求头。
四、对现有项目的影响:升级必看
如果你的项目当前使用了Undertow,升级到Spring Boot 4.0后会遇到什么问题?
4.1 典型报错
如果项目中包含以下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>升级到Spring Boot 4.0后,项目将无法启动,并抛出类似错误:
Caused by: java.lang.IllegalStateException: Unable to find Undertow-based WebServer implementation.4.2 三大风险点
风险项 | 说明 |
|---|---|
| 启动失败 | 缺少Undertow实现类,应用无法启动 |
| 配置失效 | server.undertow.*配置被完全忽略 |
| 性能回退 | 切换容器后需要重新压测和调优 |
五、迁移方案:如何平滑过渡?
别慌。Spring Boot 4.0仍然支持两种嵌入式Web容器,迁移并不复杂。
5.1 方案一:切换回Tomcat(最推荐)
Tomcat是Spring Boot的默认容器,生态成熟、文档丰富,且在Spring Boot 4中已全面适配Servlet 6.1。
步骤1:移除Undertow依赖
<!-- 删除以下依赖 --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> -->步骤2:显式添加Tomcat(通常无需添加)
spring-boot-starter-web已经默认包含了Tomcat:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency>步骤3:转换配置
将server.undertow.*配置转换为server.tomcat.*:
# 旧配置(Undertow) server: undertow: io-threads: 4 worker-threads: 20 buffer-size: 1024 # 新配置(Tomcat) server: tomcat: threads: max: 200 min-spare: 10 max-connections: 81925.2 方案二:改用Jetty
Jetty同样支持Servlet 6.1,在某些I/O密集型场景下表现优异。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>注意:需要排除Tomcat依赖,避免冲突:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>5.3 Spring Boot 4.0支持的容器版本
Spring Boot 4.0对嵌入式Web容器的支持如下:
容器 | 版本要求 | Servlet规范 | 支持状态 |
|---|---|---|---|
| Tomcat | 11.0.x | Servlet 6.1 | ✅ 支持 |
| Jetty | 12.1.x | Servlet 6.1 | ✅ 支持 |
| Undertow | — | — | ❌已移除 |
六、一张图看懂完整的变更
七、优缺点
Spring Boot 4.0移除Undertow的“好处”
1. 规范对齐,技术栈更清晰Spring Boot 4.0强制依赖Servlet 6.1,只保留兼容的容器,减少了技术栈的混乱。
2. 减少维护负担Spring Boot团队不再需要为Undertow维护兼容层,可以集中精力在核心功能上。
3. 推动生态向前这一决策倒逼Undertow社区加快适配Servlet 6.1的步伐。
4. 与Jakarta EE 11对齐Spring Boot 4.0全面升级至Jakarta EE 11,只保留兼容的容器是合理的架构决策。
对开发者的“代价”
1. 迁移成本使用Undertow的项目需要切换到Tomcat或Jetty,并重新配置和调优。
2. 性能不确定性如果之前是因为Undertow的性能优势才选择的它,切换到其他容器后可能需要重新压测和调优。
3. 配置需要重写server.undertow.*配置全部失效,需要转换为Tomcat或Jetty的配置格式。
4. 短期内的阵痛对于深度依赖Undertow特性的项目,迁移可能需要一定的开发时间。
八、适用场景与建议
如果你在用Undertow
场景 | 建议 |
|---|---|
| 正准备升级到Spring Boot 4.0 | 先切换到Tomcat或Jetty,再执行升级 |
| 尚未升级,还在Spring Boot 3.x | 可以继续用Undertow,但建议开始规划迁移 |
| 新项目从零开始 | 直接用Tomcat(默认)或Jetty,别碰Undertow |
选Tomcat还是Jetty?
对比维度 | Tomcat | Jetty |
|---|---|---|
| 生态成熟度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 文档丰富度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 默认支持 | ✅ 默认 | ❌ 需手动引入 |
| I/O密集型 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 企业级特性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
我的建议:大部分项目直接切回Tomcat就行,因为它是Spring Boot的默认容器,生态最成熟、文档最丰富。如果你的应用是I/O密集型的,可以考虑Jetty。
九、写在最后
回到最初的问题:Spring Boot 4.0为什么要弃用Undertow?
答案很清晰——不是Spring团队不待见Undertow,而是Undertow跟不上Servlet规范的演进速度。
Spring Boot 4.0强制依赖Servlet 6.1,而Undertow尚未适配。
Red Hat对Undertow的投入有限,导致其无法及时跟进新规范。
Spring Boot团队已经等了很久,但等不下去了。
Undertow会被永久抛弃吗?
不一定。
只要Undertow未来支持Servlet 6.1,Spring Boot仍有可能恢复对其支持。
Undertow团队已经在2025年10月发布了2.4.0.Alpha1,开始实现Jakarta Servlet 6.1。
但问题是——什么时候能正式支持?没有人知道确切的时间表。
对于正在做技术选型或准备升级的团队来说,等待Undertow适配不是一个明智的选择。
我的建议是:如果你正在使用Undertow,建议尽快规划迁移到Tomcat或Jetty。
尤其是新项目,直接用Tomcat(Spring Boot默认)是最省心的选择。