JDK升级至17后嵌入式Jetty无法解析JSTL TLD的问题求助
解决方案:Jetty 9.2.x + JDK17 无web.xml环境下JSTL解析问题
1. 修正Maven依赖(避免冲突,确保正确的JSTL绑定)
Jetty的apache-jstl依赖已经包含了标准JSTL 1.2的实现,无需单独引入jstl-1.2.jar,否则会导致类路径冲突。保留以下依赖即可:
<dependencies> <!-- 嵌入式Jetty核心 --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.2.23.v20171218</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.2.23.v20171218</version> </dependency> <!-- Apache Jasper JSP引擎 + JSTL支持 --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jsp</artifactId> <version>9.2.23.v20171218</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jstl</artifactId> <version>9.2.23.v20171218</version> </dependency> </dependencies>
2. 编程式配置Jetty的JSP/JSTL加载逻辑(无web.xml替代方案)
因为项目没有web.xml和WEB-INF,需要在嵌入式Jetty的启动代码中手动配置JSP Servlet,并指定TLD扫描路径,确保JSTL的标签库能被识别:
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.webapp.WebAppContext; import org.apache.jasper.servlet.JspServlet; public class JettyStarter { public static void main(String[] args) throws Exception { Server server = new Server(8080); WebAppContext webApp = new WebAppContext(); // 设置项目根路径(根据你的实际资源位置调整) webApp.setResourceBase("src/main/webapp"); webApp.setContextPath("/"); // 配置JSP Servlet ServletHolder jspHolder = new ServletHolder("jsp", JspServlet.class); jspHolder.setInitParameter("fork", "false"); jspHolder.setInitParameter("xpoweredBy", "false"); // 关键:指定JSTL的TLD扫描路径,从依赖的jar包中读取 jspHolder.setInitParameter("org.eclipse.jetty.jsp.tldscan", "classpath:/META-INF/c.tld,classpath:/META-INF/fmt.tld"); webApp.addServlet(jspHolder, "*.jsp"); // 确保类加载器能优先访问JSTL的类 webApp.setParentLoaderPriority(true); server.setHandler(webApp); server.start(); server.join(); } }
3. 解决JDK17模块化访问限制
JDK17的模块化系统会限制非模块化代码(如Jetty 9.2.x)访问javax包的类,需要在启动时添加VM参数:
--add-modules java.servlet.jsp.jstl,java.xml.bind,java.activation --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.servlet/javax.servlet=ALL-UNNAMED --add-opens java.servlet.jsp/javax.servlet.jsp=ALL-UNNAMED --add-opens java.servlet.jsp.jstl/javax.servlet.jsp.jstl.core=ALL-UNNAMED
这些参数会开放Jetty和Jasper需要访问的模块,避免反射或类加载失败。
4. (可选)升级Jetty版本(推荐长期解决方案)
Jetty 9.2.x是2017年的版本,对JDK11+的兼容性存在先天不足。如果上述方法仍无效,建议升级到Jetty 9.4.x(支持JDK8-JDK17),新版本对模块化JDK的支持更好,且无需复杂的TLD手动配置。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

