java - 类未找到异常 : how to find dependency conflict in Java

标签 java maven tomcat servlets javax

在使用 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 容器版本早于 Servlet 3.0 引起的:

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 文件?如何找到导致使用旧版本的依赖项?

最佳答案

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

为了找到应用程序使用的 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

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

关于java - 类未找到异常 : how to find dependency conflict in Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41286715/

相关文章:

java - 使用 Java 计算文件中的单词和换行符?

java - 谁能帮助我解决 Hibernate 和 JSF 的这个缺点?

java - 碰撞检测矩阵-快速阵列移除和添加

java - maven 中的 neo4j EmbeddedNeo4j.java try-with-resources 错误

tomcat - tomcat使用的ClassLoader

Java try 和finally 多线程示例中的阻塞

Maven:在项目B中使用项目A的特定测试类

eclipse - 使用 Maven 和 Tomcat 将 servlet 文件放入 Eclipse 的最佳方法是什么?

java - 如何在java中从一个应用程序获取tomcat web绝对路径到centos中的另一个应用程序?

windows - 几个小时后 tomcat 6 挂起