You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot替换Tomcat为Jetty引入JSP时JarScanner启动报错

问题根因

提示ServletContext中未配置org.apache.tomcat.JarScanner只是表象,不是问题触发的核心原因。引入org.eclipse.jetty:apache-jsp依赖后,JSP初始化阶段会触发Apache TLD标签库扫描逻辑,默认全量扫描classpath下所有jar包内的标签描述符、web片段资源。Firebase Java Admin SDK依赖的grpc系列jar(尤其是grpc-netty-shaded这类带嵌套类路径结构的shaded包),在Tomcat JarScanner默认实现下的路径解析规则和Jetty类加载结构不兼容,扫描时会将嵌套jar的虚拟路径识别为本地文件系统路径读取,最终抛出FileNotFoundException,手动补Tomcat JarScanner配置无法解决该问题,本质是类加载逻辑不匹配导致的扫描路径错误。

可行排查与解决方向
  • 方案1:优先推荐 配置Jetty JSP扫描的排除规则,跳过非必要jar的TLD扫描
    直接在Spring Boot配置类中注册JettyServerCustomizer,缩小JSP扫描的jar范围,只扫描JSP、JSTL相关的依赖包,从根源避免扫描到grpc、Firebase相关的结构特殊jar,示例配置:
    @Bean
    public JettyServerCustomizer jettyJspScanExcludeCustomizer() {
        return server -> {
            for (Handler handler : server.getHandlers()) {
                if (handler instanceof ServletContextHandler contextHandler) {
                    // 仅匹配JSP、JSTL相关jar参与TLD扫描
                    contextHandler.setAttribute(
                        "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                        ".*/[^/]*jstl.*\\.jar$|.*/[^/]*jetty.*jsp.*\\.jar$"
                    );
                }
            }
        };
    }
    
    该方案不需要调整依赖,改动量最小,绝大多数同类场景可直接生效。
  • 方案2:替换默认JarScanner实现,适配Jetty类加载逻辑
    不要硬注入Tomcat原生的JarScanner实现,在ServletContext初始化阶段注册适配Jetty路径规则的JarScanner,替换apache-jsp默认加载的Tomcat实现:
    @Bean
    public ServletContextInitializer scannerOverrideInitializer() {
        return servletContext -> {
            servletContext.setAttribute(
                "org.apache.tomcat.JarScanner",
                new JettyCompatJarScanner()
            );
        };
    }
    
    自定义的JettyCompatJarScanner实现JarScanner接口即可,重写扫描逻辑时遇到嵌套类路径资源直接跳过,或调用Jetty原生JarResource做路径解析,不要直接通过File类读取路径。
  • 方案3:排除apache-jsp中携带的Tomcat冲突依赖
    org.eclipse.jetty:apache-jsp会传递引入Tomcat embed核心包,这些类和Jetty容器本身的类加载逻辑存在冲突,引入时直接排除该传递依赖:
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>apache-jsp</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    如果项目仅使用基础JSTL标签,也可以将apache-jsp替换为和当前Jetty版本完全匹配的org.eclipse.jetty:jetty-jsp,从根源避免引入Tomcat原生扫描逻辑。
  • 方案4:调整Firebase Admin SDK依赖引入方式,替换shaded grpc包
    排除Firebase Admin SDK依赖的grpc-netty-shaded包,改用标准结构的非shaded grpc-netty依赖,这类jar是标准单文件结构,不会触发JarScanner的路径解析错误:
    <dependency>
        <groupId>com.google.firebase</groupId>
        <artifactId>firebase-admin</artifactId>
        <exclusions>
            <exclusion>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-netty-shaded</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty</artifactId>
        <version>与Firebase依赖的grpc核心包版本保持一致</version>
    </dependency>
    

排查注意:不要尝试手动声明Tomcat JarScanner的Bean注入Spring上下文,这类Tomcat原生组件在Jetty容器下无法被ServletContext正确识别,反而会加重类加载冲突。优先按方案1到方案4的顺序测试,90%以上的场景在方案1阶段即可解决问题。

内容的提问来源于stack exchange,提问作者Mark Su

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:18:30