错误:未加载 Servlet Jar...违规类:javax/servlet/Servlet.class

2022-09-01 09:29:09

我收到以下错误:

INFO: validateJarFile(C:\dev\server\tomcat6\webapps Sempedia\WEB-INF\lib\servlet-api.jar) - jar not loaded.请参阅 Servlet Spec 2.3, sectoin 9.7.2。违规类:javax/servlet/Servlet.class

现有的资源说这是由于与servlet冲突.jar或者在我的情况下称为servlet-api.jar文件。我已经从/webapps文件夹中删除了所有其他项目,我已经取出了tomcat6 / lib目录中的servlet-api.jar文件,并将其仅添加到项目构建路径中,因此我看不到如何仍然存在冲突。

当我尝试运行应用程序时,我得到以下堆栈跟踪。

org.apache.jasper.JasperException: Unable to compile class for JSP:

在生成的 java 文件中的行 22 处发生错误 方法 getJspApplicationContext(ServletContext) 未为类型 JspFactory 定义

堆栈跟踪:

org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92) org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330) org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:439) org.apache.jasper.compiler.Compiler.compiler.compile(Compiler.java:334) org.apache.jasper.compiler.compile(Compiler.java:312) org.apache.jasper.compiler.compiler.compile(Compiler.java:299)org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:586) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.jspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)


答案 1

这是类路径污染的一个迹象。JSP/Servlet API 库依赖于 appserver 实现,属于文件夹中的 Tomcat 6,不应将任何位置移动或复制到其他位置。这是您现在遇到的类加载中的可移植性问题和冲突的秘诀。Web 应用中的库在类加载中具有优先级。如果在那里遇到,它反过来又在那里寻找它的依赖关系,但它们显然在那里丢失了。Tomcat/libservlet-api.jar

您必须从 Web 应用程序的 .您应该将特定于Webapp的库放在那里。将特定于应用程序的库保留在应用程序服务器自己的默认类路径中,这是您的情况。保持原封不动。您最多可以添加要在其中的所有Web应用程序之间共享的库,或者更好的是,为此配置in。Webapp/WEB-INF/libTomcat/libshared.loaderTomcat/conf/catalina.properties

还要从 和 文件夹中删除任何特定于应用服务器和特定于 Web 应用的库(如果有)。我经常看到一些启动器将库移动/复制到那里,因为“否则它无法编译”。切勿在其中复制非 JRK/JRE 特定的库。这也是便携性麻烦的秘诀。使用 编译类时,应使用参数来指定依赖库。JDK/libJRE/libjavac-cp

更新:对于IDE(您似乎在谈论“构建路径”时使用了一个IDE),您需要将Web项目与应用程序服务器相关联。例如,在 Eclipse 中,您可以选择在创建动态 Web 项目期间执行此操作。在创建项目之前,您需要在 Eclipse 中集成服务器实例。您可以通过视图执行此操作(假设您正在为Java EE开发人员使用Eclipse,否则请升级)。之后,还可以通过项目属性中的“服务器”条目对其进行更改。选择一个要用作“默认”服务器的服务器,然后其库将自动包含在项目的构建路径中。绝对没有必要将它们复制/移动到其他地方。另请参阅如何在我的 Eclipse 项目中导入 javax.servlet API?Servers


答案 2

正如其他答案所说,这是因为您的 WAR 包含 servlet API 类,但它不应该这样做。

如果您使用 Maven 构建项目,则需要告诉 Maven 在编译和测试时使 servlet API 可用,但不要将其包含在 WAR 中。正如 Maven 关于依赖关系范围的文档所说,您应该对 Servlet API 使用作用域:provided

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>

您可能还必须显式排除 Servlet API 作为传递依赖项,如果某些依赖项将 Servlet API 作为编译依赖项拉入:

    <dependency>
        <groupId>com.example</groupId>
        <artifactId>frob-driver-core</artifactId>
        <version>1.0.1</version>
        <exclusions>
            <exclusion>
                <artifactId>servlet-api</artifactId>
                <groupId>javax.servlet</groupId>
            </exclusion>
        </exclusions>
    </dependency>

推荐