迁移至Spring6+Tomcat10.1后JSTL标签[c]无法找到的问题
Spring 6.0.11 + Tomcat 10.1.13 迁移后JSTL标签库无法定位问题
问题背景
将项目从Tomcat 9 + Java EE迁移至Spring 6.0.11 + Tomcat 10.1.13后,JSTL标签无法正常使用。已按Jakarta Standard Tag Library 3.0规范,将所有JSP中的标签库URI从http://java.sun.com/jsp/jstl/core修改为jakarta.tags.core,但调试发现TldCache中的URI映射未填充,导致TagLibraryInfoImpl的tldResourcePath为null,最终抛出标签库找不到的异常。
当前依赖配置
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0' implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1' implementation 'org.mortbay.jasper:apache-jsp:10.1.7' implementation("org.apache.tomcat:tomcat-jsp-api:10.1.13") compileOnly "jakarta.servlet:jakarta.servlet-api:6.0.0"
抛出的异常信息
org.apache.jasper.JasperException: Could not find taglib [c] for URI: [jakarta.tags.core] in org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:54) in org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:294) in org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:81) in org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:176) in org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:429) in org.apache.jasper.compiler.Parser.parseDirective(Parser.java:487) in org.apache.jasper.compiler.Parser.parseElements(Parser.java:1444) in org.apache.jasper.compiler.Parser.parse(Parser.java:138) in org.apache.jasper.compiler.ParserController.doParse(ParserController.java:245) in org.apache.jasper.compiler.ParserController.parse(ParserController.java:106) in org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:211) in org.apache.jasper.compiler.Compiler.compile(Compiler.java:396) in org.apache.jasper.compiler.Compiler.compile(Compiler.java:372) in org.apache.jasper.compiler.Compiler.compile(Compiler.java:356) in org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603) in org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:396) in org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380) in org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328) in jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) in org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) in org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) in org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) in org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) in org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) in org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) in org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) in org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
已尝试的额外依赖(未解决问题)
compileOnly 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.1' implementation 'org.mortbay.jasper:taglibs-standard:10.0.2' compileOnly 'jakarta.platform:jakarta.jakartaee-api:10.0.0'
排查方向与解决方案
移除冲突依赖:Tomcat 10.1自带适配Jakarta EE 10的Jasper编译器,额外引入
org.mortbay.jasper:apache-jsp会导致类加载冲突,覆盖原生TLD加载逻辑。同时tomcat-jsp-api为Tomcat自带依赖,需一并移除。检查JSTL实现包的TLD映射:确认
org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1包内包含:META-INF/c.tld文件,且文件内<uri>标签值为jakarta.tags.coreMETA-INF/tld-index.xml中已注册该URI与TLD的关联
精简后的依赖配置:
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0' implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1' compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0' compileOnly 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.1'验证Web应用配置:确保
web.xml使用Jakarta EE 10的命名空间与版本:<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0">TLD加载机制说明:Apache Jasper通过扫描classpath下所有jar中的
META-INF/*.tld文件和META-INF/tld-index.xml建立URI到TLD的映射,这些映射会自动缓存到TldCache中,无依赖冲突时即可正常填充。
内容的提问来源于stack exchange,提问作者Vooply
相关产品推荐
相关产品推荐

