Spring 6与Tomcat 10集成Sitemesh 2.4时NoClassDefFoundError问题解决
Spring 6 + Tomcat 10 适配 Sitemesh 问题的解决办法
问题根源
Tomcat 10和Spring 6都全面切换到了Jakarta EE规范,原来的javax.servlet.*包全改成了jakarta.servlet.*,但你用的Sitemesh 2.4.2是基于旧Javax Servlet API开发的,无法识别新的Jakarta包路径,所以才会抛出java.lang.NoClassDefFoundError: javax/servlet/Filter错误。
具体解决步骤
1. 换用Sitemesh的Jakarta兼容版
Sitemesh官方已经推出适配Jakarta的分支版本,别再用2.4.2了,直接替换成这个:
- Maven依赖配置如下:
<dependency> <groupId>org.sitemesh</groupId> <artifactId>sitemesh-jakarta</artifactId> <version>3.2.0</version> </dependency>
这个版本完全适配Jakarta Servlet API,能直接在你的环境里运行。
2. 处理冲突的servlet-api依赖
你当前用的servlet-api 6会和Tomcat自带的Jakarta Servlet API冲突,因为Tomcat 10本身已经提供了该API的实现。要么删除这个依赖,要么将其标记为provided范围,让容器提供:
<dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency>
provided表示该依赖不会打包到应用中,避免和Tomcat自带版本产生冲突。
3. 更新ContextListener的包引用
如果你的自定义ContextListener是基于旧的javax.servlet.ServletContextListener实现的,要把包路径换成jakarta.servlet开头的:
// 原代码 import javax.servlet.ServletContextListener; import javax.servlet.ServletContextEvent; // 修改后代码 import jakarta.servlet.ServletContextListener; import jakarta.servlet.ServletContextEvent;
所有和Servlet相关的API引用,都要从javax.servlet替换为jakarta.servlet。
4. 临时过渡方案:用Tomcat迁移工具转换旧Jar
如果暂时不想替换Sitemesh版本,可以用Tomcat自带的迁移工具把旧的Sitemesh Jar转换成适配Jakarta的版本:
- 找到Tomcat安装目录
bin文件夹里的tomcat-jakarta-migration.jar - 执行命令转换:
java -jar tomcat-jakarta-migration.jar sitemesh-2.4.2.jar sitemesh-2.4.2-jakarta.jar
- 把转换后的Jar替换原来的依赖包即可。不过这只是临时 workaround,长期来看还是建议使用官方适配的版本更稳定。
内容的提问来源于stack exchange,提问作者Tomatopedas
相关产品推荐
相关产品推荐

