【问题标题】:ClassNotFoundException: how to find dependency conflict in JavaClassNotFoundException:如何在 Java 中查找依赖冲突
【发布时间】:2017-05-08 06:57:34
【问题描述】:

在使用 Atmosphere servlet 的测试 WebSocket 应用程序中,出现以下异常:

SEVERE: Servlet.service() for servlet AtmosphereServlet threw exception
java.lang.ClassNotFoundException: javax.servlet.AsyncContext
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)
    at org.atmosphere.cpr.AtmosphereServlet.doPost(AtmosphereServlet.java:191)
    at org.atmosphere.cpr.AtmosphereServlet.doGet(AtmosphereServlet.java:177)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)

从以下帖子中,我了解到这可能是由早于 Servlet 3.0 的 Servlet 容器版本引起的:

ClassNotFoundException: javax.servlet.AsyncContext in Jetty hello world

ClassNotFoundException: javax.servlet.AsyncContext in Jetty hello world in eclipse

Grails project - Servlet call - ClassNotFoundException: javax.servlet.AsyncContext

但是应用是在Tomcat7上运行的,在pom.xml中添加了如下依赖:

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

我检查了项目中的所有其他依赖项,但找不到与 Servlet 相关的任何其他内容。我仍然遇到异常。

问题:如何找到应用实际使用的jar文件?如何找到导致使用旧版本的依赖项?

【问题讨论】:

    标签: java maven tomcat servlets javax


    【解决方案1】:

    我终于能够通过执行以下操作来解决依赖冲突。

    为了找到应用程序使用的 jar 文件,我使用了以下简单代码:

    public void listJarFilesAndClassVersions() {    
        Class classToCheck = javax.servlet.ServletRequestWrapper.class;
        URL location = classToCheck.getResource('/'
            + classToCheck.getName().replace('.', '/') + ".class");
    
        System.out.println(location.toString());
    
        for(Package p : Package.getPackages()) {
            if (p.getName().startsWith("javax.servlet")) {
                System.out.println("Class: " + p.getName()
                    + ", version: " + p.getSpecificationVersion());
            }
        }
    }
    

    选择类 javax.servlet.ServletRequestWrapper 是因为它确实存在于旧的 Servlet 2.5 中。

    上述脚本的执行给了我以下信息:

    jar:file:/C:/Users/[username]/.m2/repository/org/apache/tomcat/servlet-api/6.0.29/servlet-api-6.0.29.jar!/javax/servlet/ServletRequestWrapper.class
    Class: javax.servlet.jsp, version: 2.1
    Class: javax.servlet, version: 2.5
    Class: javax.servlet.http, version: null
    

    所以,首先,它确认使用的是2.5版本的Servlet,其次,“坏”的jar位于tomcat目录下的maven仓库中。

    经过短暂的研究,我终于找到了根本原因:在部署和运行 maven 应用程序时,我需要指定 tomcat 的具体版本,否则 maven 使用版本 6 的 tomcat 中的库。所以修复对我来说是改变

    mvn -Dmaven.tomcat.port=8080 tomcat:run-war
    

    mvn -Dmaven.tomcat.port=8080 tomcat7:run-war
    

    现在,如果我执行上面的脚本,它会给出以下结果:

    jar:file:/C:/Users/[username]/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/7.0.47/tomcat-embed-core-7.0.47.jar!/javax/servlet/ServletRequestWrapper.class
    Class: javax.servlet.jsp, version: 2.2
    Class: javax.servlet, version: 7.0
    Class: javax.servlet.http, version: 7.0
    Class: javax.servlet.annotation, version: 7.0
    Class: javax.servlet.descriptor, version: 7.0
    

    希望它能帮助遇到同样问题的其他人。

    【讨论】:

      【解决方案2】:

      我通常会通过两种方式发现冲突。

      1. 如果您使用的是 Eclipse,请在 IDE 中打开 pom.xml,然后切换到“Dependency Hierarchy”选项卡。左侧面板是依赖关系树,右侧面板是实际使用的依赖项。在每个依赖项之后就是它的范围(例如,编译/测试/运行时/因冲突而省略)

      1. 在终端运行命令。 mvn dependency:tree 它将像在 Eclipse 中一样打印出依赖关系。

      【讨论】:

      • 投了答案,确实有用。但是 Eclipse 中的依赖层次结构并没有向我显示 maven tomcat 存储库中的实际库。命令 mvn dependency:tree 也没有。它们只显示与项目本身相关的库。
      • @Alexey 那么“并且在 pom.xml 中添加了以下依赖项”是什么意思?是否添加到 pom 中?
      • 是的,它被添加了,我可以在依赖层次结构中看到它。但它不被应用程序使用,如上所示。由于某种原因,Java 忽略了这种依赖关系并使用了 maven\tomcat 目录中的 jar。
      • @Alexey 嗯...这对我来说没有意义。即使忽略了pom中定义的版本,tomcat7也不太可能引入冲突。正如你在这里看到的tomcat.apache.org/whichversion.htmltomcat7 本身确实使用了具有AsyncContext 类的servlet-api 3.0
      • @Alexey 我认为这是您可以仔细检查的一件事。导航到 {tomcat_home}/lib,应该有一个 servlet-api.jar。运行这个命令unzip -p servlet-api.jar META-INF/MANIFEST.MF打印出tomcat自带的servlet-api版本
      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 2019-02-25
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      相关资源
      最近更新 更多