Spring-web模块与Tomcat 10的兼容性及迁移ClassCastException问题咨询
Hey there! Let's tackle your questions about Spring Web and Tomcat 10 compatibility, plus that tricky ClassCastException you're hitting after migration.
Spring Web 与 Tomcat 10 的兼容性
- 核心兼容性逻辑: Tomcat 10 基于 Jakarta EE 9+ API 构建,所有相关包名从
javax.servlet切换为jakarta.servlet。而旧版 Spring Web(比如 Spring Framework 5.x)依赖传统 Java EE 的javax包,因此无法直接兼容 Tomcat 10。 - 兼容的 Spring 版本: 从Spring Framework 6.0开始,Spring 生态全面迁移到 Jakarta EE API,所以 Spring Web 6.0 及以上版本完全兼容 Tomcat 10(包括 10.0.x 和 10.1.x 分支)。如果使用 Spring Boot,基于 Spring Framework 6 的 Spring Boot 3.0+ 版本也原生支持 Tomcat 10。
迁移到 Tomcat 10 后出现
ClassCastException 的原因与解决方法 报错原因解析
你遇到的报错:
java.lang.ClassCastException: org.springframework.web.filter.DelegatingFilterProxy cannot be cast to jakarta.servlet.Filter
本质是包名切换导致的接口不匹配:
- Tomcat 9 要求过滤器实现
javax.servlet.Filter接口 - Tomcat 10 要求过滤器实现
jakarta.servlet.Filter接口
旧版 Spring Web(5.x 及以下)中的DelegatingFilterProxy实现的是旧的javax.servlet.Filter,在 Tomcat 10 环境下,容器期望的是jakarta包下的接口实例,因此抛出类型转换异常。
解决办法
方案1:升级到兼容 Jakarta 的 Spring 版本(推荐)
这是长期稳定的解决方案:
- 将项目升级到Spring Framework 6.0+或Spring Boot 3.0+
- 把所有
javax相关依赖替换为jakarta版本(例如将javax.servlet-api替换为jakarta.servlet-api4.0+) - 检查代码中直接引用
javax.servlet类的地方,统一替换为jakarta.servlet对应的类
方案2:使用 Tomcat 10 的遗留桥接(临时 workaround)
如果暂时无法升级 Spring,Tomcat 10 提供了遗留桥接功能来运行基于javax包的应用:
- 使用官方的
tomcat-jakartaee-migration工具自动转换项目依赖为桥接包 - 或手动添加 Tomcat 的 Jakarta EE 桥接依赖(比如
tomcat-jakarta-servlet-api)到项目中 - 注意:这只是短期过渡方案,桥接实现可能存在潜在兼容问题,长期来看还是建议升级到 Spring 6.x/Spring Boot 3.x
内容的提问来源于stack exchange,提问作者YN Raja




