Spring Boot MVC升级Java20/Tomcat10.1后第三方TLD库报错求助
问题:升级Spring Boot到Java 20/Tomcat 10.1后出现ClassNotFoundException
将Spring Boot应用升级至Java 20/Tomcat 10.1版本后,因依赖第三方TLD库,运行时抛出如下错误:
Servlet.service() for servlet [jsp] threw exception java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.BodyTagSupport at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1013) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:496) at java.base/java.lang.Class.forName(Class.java:475) at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:496) at java.base/java.lang.Class.forName(Class.java:475) at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadFromParent(TomcatEmbeddedWebappClassLoader.java:113) at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.doLoadClass(TomcatEmbeddedWebappClassLoader.java:86) at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:70) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165) ...
当前POM中的相关依赖:
<dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> </dependency>
原因
Tomcat 10.1基于Jakarta EE 9+规范,所有Servlet/JSP相关API的包名已从javax.*迁移至jakarta.*。错误中缺失的javax.servlet.jsp.tagext.BodyTagSupport是旧版javax下的类,说明你的第三方TLD库仍依赖旧版javax API,或当前依赖配置缺少必要的兼容桥接。
解决方案
1. 添加Jakarta到Java EE的桥接依赖
Tomcat提供了专门的桥接包,用于兼容依赖旧javax API的库:
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jakartaee-migration</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency>
如果是Spring Boot环境,也可以通过调整Tomcat嵌入依赖来实现兼容:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <exclusions> <exclusion> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </exclusion> <exclusion> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>10.1.x</version> <!-- 替换为你使用的Tomcat 10.1具体版本 --> <classifier>jakarta</classifier> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> <version>10.1.x</version> <!-- 替换为你使用的Tomcat 10.1具体版本 --> <classifier>jakarta</classifier> </dependency>
2. 升级第三方TLD库到Jakarta兼容版本
检查第三方TLD库是否有支持Jakarta EE 9+的版本,直接升级是最彻底的解决方案,可避免桥接包带来的潜在兼容性问题。
3. 调整tomcat-embed-jasper的作用域
当前tomcat-embed-jasper的scope设为provided,开发环境中可能导致依赖缺失。建议开发阶段改为compile,生产环境再恢复为provided:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>compile</scope> </dependency>
内容的提问来源于stack exchange,提问作者Jorge
相关产品推荐
相关产品推荐

