【问题标题】:Tomcat 7.0.29 servlet-api classloader issueTomcat 7.0.29 servlet-api 类加载器问题
【发布时间】:2012-11-25 16:33:26
【问题描述】:

我目前正在尝试将我们的构建从手动过程(MyEclipse / export as war)更改为自动 Maven 构建。

MyEclipse 构建的 war 应用程序在我们的 Tomcat 7.0.29 安装 (Windows 7) 上部署并运行良好。在 MyEclipse 构建路径中,我们配置了一个用户库(tomcat),里面包含了来自$CATALINA_HOME/lib的所有jar。

我们有一些使用 javax.servlet.http.* 类(HttpSessionEvent 等)的 servlet 侦听器和过滤器。它们被打包在WEB-INF\classes\com\mycompany\filters

在部署由 Maven 构建的战争时,我在 HttpSessionEvent 类上得到了 NoClassDefFoundError。我使用 -verbose:class JVM 选项进行了跟踪,我看到最后一个加载的类是我的过滤器 c:\apache\webapps\myapp\WEB-INF\classes\com\mycompany\filters 目录。然后我尝试加载/查找 HttpSessionEvent 并且无法这样做。

servlet-api.jar 当然在我的$CATALINA_HOME\lib 目录中。

在我的 pom.xml 我有这个依赖

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-servlet-api</artifactId>
        <version>7.0.29</version>
        <scope>provided</scope>
    </dependency>

我的路径/类路径中没有其他 servlet-api.jar 文件(也仔细检查了我的 jdk 和 jre 的 lib/ext 和背书目录)

我的 maven 依赖:树看起来像这样:

[INFO] +- log4j:log4j:jar:1.2.15:compile
[INFO] |  \- javax.mail:mail:jar:1.4:compile
[INFO] +- jstl:jstl:jar:1.2:compile
[INFO] +- org.jdom:jdom:jar:1.1:provided
[INFO] +- com.sun.xml.rpc:jaxrpc-impl:jar:1.1.3_01:provided
[INFO] |  +- javax.xml:jaxrpc-api:jar:1.1:provided
[INFO] |  +- com.sun.xml.messaging.saaj:saaj-impl:jar:1.3:provided
[INFO] |  |  \- javax.xml.soap:saaj-api:jar:1.3:provided
[INFO] |  +- com.sun.xml.rpc:jaxrpc-spi:jar:1.1.3_01:provided
[INFO] |  \- com.sun.xml.fastinfoset:FastInfoset:jar:1.0.2:provided
[INFO] +- org.apache.lucene:lucene-core:jar:3.6.0:compile
[INFO] +- org.springframework:spring-context:jar:3.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:3.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-core:jar:3.1.0.RELEASE:compile
[INFO] |  |  \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  +- org.springframework:spring-expression:jar:3.1.0.RELEASE:compile
[INFO] |  \- org.springframework:spring-asm:jar:3.1.0.RELEASE:compile
[INFO] +- org.springframework:spring-web:jar:3.1.0.RELEASE:compile
[INFO] |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] +- org.springframework:spring-orm:jar:3.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-jdbc:jar:3.1.0.RELEASE:compile
[INFO] |  \- org.springframework:spring-tx:jar:3.1.0.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:3.1.0.RELEASE:compile
[INFO] +- org.springframework:spring-test:jar:3.1.0.RELEASE:test
[INFO] +- org.aspectj:aspectjrt:jar:1.7.1:compile
[INFO] +- org.aspectj:aspectjweaver:jar:1.7.1:compile
[INFO] +- javax.faces:javax.faces-api:jar:2.1:compile
[INFO] +- com.sun.faces:jsf-impl:jar:2.1.15:compile
[INFO] +- org.primefaces:primefaces:jar:3.4.2:compile
[INFO] +- org.richfaces.core:richfaces-core-api:jar:4.2.3.Final:compile
[INFO] |  \- com.google.guava:guava:jar:11.0.2:compile
[INFO] |     \- com.google.code.findbugs:jsr305:jar:1.3.9:compile
[INFO] +- org.richfaces.ui:richfaces-components-ui:jar:4.2.3.Final:compile
[INFO] |  \- org.richfaces.ui:richfaces-components-api:jar:4.2.3.Final:compile
[INFO] +- org.apache.tomcat:tomcat-servlet-api:jar:7.0.29:provided
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.7.2:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.2:compile
[INFO] +- org.hibernate:hibernate-core:jar:3.6.2.Final:compile
[INFO] |  +- antlr:antlr:jar:2.7.6:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.1:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  +- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
[INFO] |  +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile
[INFO] |  \- javax.transaction:jta:jar:1.1:compile
[INFO] +- org.hibernate:hibernate-entitymanager:jar:3.6.2.Final:compile
[INFO] |  +- cglib:cglib:jar:2.2:compile
[INFO] |  |  \- asm:asm:jar:3.1:compile
[INFO] |  \- javassist:javassist:jar:3.12.0.GA:compile
[INFO] +- org.hibernate:hibernate-validator:jar:4.1.0.Final:compile
[INFO] |  \- javax.validation:validation-api:jar:1.0.0.GA:compile
[INFO] +- org.apache.commons:commons-email:jar:1.2:compile
[INFO] |  \- javax.activation:activation:jar:1.1:compile
[INFO] +- junit:junit:jar:4.11:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- com.h2database:h2:jar:1.3.170:test

我已经在互联网上搜索了一段时间,从我读到的内容来看,这一定与 tomcat 类加载器有关。我的战争包装很可能有问题。但是,我还没有找到解决方案。

任何指针将不胜感激!

【问题讨论】:

  • 我可能会克隆项目并删除除单个 servlet 或过滤器之外的所有内容,然后尝试它是否有效。和/或尝试将其部署到不同的引擎,例如 Jetty。

标签: java tomcat servlets classloader


【解决方案1】:

Classloading in Tomcat这会帮助你理解。

将你的 jar 放在 /WEB-INF/lib

Application Classloader — 为每个 Web 应用程序创建一个类加载器 部署在单个 Tomcat 实例中。所有未打包的类和 Web 应用程序的 /WEB-INF/classes 目录中的资源, 加上 /WEB-INF/lib 下 JAR 文件中的类和资源 您的 Web 应用程序的目录,对这个 Web 可见 应用程序,但不适用于其他应用程序。

【讨论】:

  • 谢谢,我从该链接中了解到,我的 webapp 获得了一个“Webapp”类加载器(它将从 WEB-INF/classes 和 WEB-INF/lib/*.jar 加载类)。类加载器继承自“Common”类加载器,它应该能够很好地加载 HttpSessionEvent 类。还是我的 webapp 类加载器在找不到类时没有委托给父类加载器(这根本没有意义)?
  • $CATALINA_HOME\**libs** 似乎不正确应该是$CATALINA_HOME\lib 问题中的目录名称无效?是一个错误还是真的罐子放在了 libs 目录中?在这种情况下,Common 类加载器将无法找到类。
  • 对不起,我的错误(错别字),$CATALINE_HOME = C:\apache-tomcat-7.0.29 它在目录 C:\apache-tomcat-7.0.29\lib
【解决方案2】:

您是否检查了已构建 .war 的 WEB-INF/lib 以绝对确定 servlet-api.jar 不存在?据我所知,Maven 依赖项具有正确的范围。

您在 pom.xml 中的 build 部分应与此类似:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <warName>war_name</warName>
            </configuration>
        </plugin>
    </plugins>
</build>

不,不要将servlet-api.jar 放在您的网络应用程序的WEB-INF/lib 文件夹中。 另外,我认为您不需要tomcat 用户库。您需要的唯一库是 JRE System Library xx 和 Maven Dependencies

【讨论】:

  • 感谢您的回复。是的,当然,构建的战争不包含 servlet-api.war。确实,servlet-api.jar 不应该放在 WEB-INF/lib 目录下,tomcat 无论如何都会忽略它。我的war插件版本是2.1.1,我会检查2.2版本是否修复了这个(这看起来很奇怪)
  • MyEclipse 构建的 .war 和 Maven 构建的 .war 有什么相关的区别吗? (顺便问一下,你最近有没有运行过mvn clean?)
  • 是的,由 MyEclipse 构建的战争包含更多的 jar,比如 apache commons 的东西、lucene 等...我可能在我的 maven 构建中缺少一些 jar,但考虑到项目已经在那里编译不会很多。顺便说一句,我已经尝试从爆炸的 WEB-INF/lib 目录中删除所有 jar,从 MyEclipse 战争中复制所有 jar 并重新部署。这也不起作用(HttpSessionEvent 上的 NoClassDefFoundError 也是如此)。
  • 哦,还有一件事,如果我用 MyEclipse 生成/编译的类替换过滤器/侦听器的类,我不再在 HttpSessionEvent 上得到 NoClassDefFoundError,而是在 Logger 上得到 NoClassDefFoundError(即一个 log4j 记录器,它也在 WEB-INF/lib 中)。奇怪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 2011-11-24
相关资源
最近更新 更多