【问题标题】:java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequestjava.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
【发布时间】:2023-04-08 16:30:02
【问题描述】:

我正在开发一个 servlet,它接收包含多个文件内容的多部分请求,并且我正在使用 apache commons 文件上传库。

当我调用parseRequest(request); 方法时,servlet 抛出以下异常:

GRAVE: Servlet.service() for servlet DiffOntology threw exception
java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
    at org.apache.commons.fileupload.servlet.ServletRequestContext.getContentType(ServletRequestContext.java:73)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:882)
    at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:349)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
    at DiffOntology.doPost(DiffOntology.java:38)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:738)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)

我把所有的库都放在了WEB-INF/lib中。

编辑:

servlet-api.jar 位于正确的目录 (tomcat/lib) 中,所有其他库位于 WEB-INF/lib 中

我认为问题可能如下: 我在 Eclipse 中开发这个 web 项目,我在类路径中导入了文件上传库。

它怎么不工作?

我绝望了!!

【问题讨论】:

    标签: java eclipse tomcat servlets apache-commons-fileupload


    【解决方案1】:

    当我错误地将 Tomcat 10 Docker 映像用于我为 Tomcat 9 构建的 WAR 文件时,我收到了该错误。 我使用了一个没有特定标签的 Docker 镜像,它是最新的 Tomcat(在我的例子中是 10)(tomcat:jdk17-temurin)附带的。

    使用 Tomcat 10 需要调整为 Tomcat 10 doc states:

    Tomcat 9.0.x 和 Tomcat 10.0.x 之间存在重大的重大变化。规范 API 使用的 Java 包已从 javax... 更改为 jakarta.... 有必要针对新的 API 重新编译 Web 应用程序。

    在我的情况下,我只是通过指定具有特定 Tomcat 版本(例如tomcat:9.0.56-jdk17-temurin)的图像来解决该错误。

    【讨论】:

    • 替代方案可能会用 Servlet 3.0 中几乎相同的功能替换 commons-fileupload,例如 this question
    【解决方案2】:

    旧线程但仍然可以帮助某人。 我看到我在测试范围中包含的依赖项中有一个 javax-servlet jar。我做到了提供的范围。如果您使用的是 Eclipse +Maven,请检查依赖关系图。

    【讨论】:

    • 在 IntelliJ 中,这将在 Project Settings -&gt; Modules -&gt; Dependencies
    【解决方案3】:

    从 JRE/lib 或 JRE/lib/ext 中删除任何 servlet-api.jar 或上传帮助 jar commons。这帮助我解决了问题。

    【讨论】:

      【解决方案4】:

      当您将特定于服务器的库放置在 web 应用程序的 /WEB-INF/lib 或可能是 JRE/lib 时,可能会发生这种情况。您将Tomcat的/lib/servlet-api.jar复制到那里的机会很大。你不应该那样做。这只会导致类路径中的冲突,从而导致此类错误,并且会使您的 webapp 不可移植(即它只能在 Tomcat 上运行,您不能在 Glassfish、JBoss AS、Websphere 等其他服务器上运行它, 等等)。您应该将特定于服务器的库保留在其默认位置。从任何特定于服务器的库中清除 /WEB-INF/lib,并从任何第 3 方库中清除 JRE/lib

      您可能在那里复制了特定于服务器的库,因为您无法编译您的 servlet。复制/WEB-INF/lib 中的库是错误的解决方案。您基本上应该只在编译时类路径中指定这些库。由于您使用的是 Eclipse,这很容易做到:首先在 Servers 视图中添加 Tomcat,然后将您的 webapp 项目与集成的 Tomcat 实例相关联。这样 Eclipse 将自动将特定于服务器的库添加到项目的构建路径中。在全新的 Web 项目上,您可以在项目创建向导期间选择服务器。在现有的 Web 项目中,您可以在项目属性的 Targeted Runtimes 部分中对其进行修改。

      另见:

      【讨论】:

      • 将 servlet-api.jar 放在 WEB-INF/lib 中不会有任何效果,因为 Tomcat 将委托给 javax.servlet 的父类加载器。即使没有,异常也会是 ClassCastException,而不是 NoClassDefFoundError。
      • @bkail:公平点当然取决于类加载策略(这确实不适用于默认的 Tomcat 配置),但这值得否决吗?剩下的答案呢?这有点太苛刻了。要点仍然很清楚:不要使用特定于服务器的库污染 webapp/JRE 库
      • 对不起,我不是故意的。站点常见问题解答说要否决错误信息,并且说在 WEB-INF/lib 或 JRE/lib 中放置 servlet-api.jar(甚至“特定于服务器的库”)可能是 NoClassDefFoundError 的原因,这是错误信息,所以你的第一段只会导致用户花时间调查错误的事情。你的其余答案很好,所以修复它,当然我会删除反对票。
      • 感谢@BalusC,我遇到了同样的问题,但是当我将库从 JRE/lib 移动到其他路径时,它毫无例外地工作。
      【解决方案5】:

      您必须将 commons-fileupload.jar 错误地复制到 JRE/lib/extJRE/lib/endorsed,或者将其放置在对 servlet API 不可见的类路径中。使用-verbose:class 启动JVM,它将打印哪个类路径加载了ServletFileUpload 类。如果该类是从 WEB-INF/lib 以外的任何地方加载的,则需要将其删除。

      【讨论】:

      • 嗯?为什么建议将库放在JRE/lib 中?这可能有效,但这会使您的 webapp 不可移植。这当然不是正确的方法。这更像是一种黑客/解决方法。
      • “嗯?”确实 :-)。我的回答肯定措辞不佳,所以我更新了“不正确”这个词。我并不是说他应该将 jars 放在 JRE/lib 中,我是说为了获得 NoClassDefFoundError,他必须已经这样做了。他需要 only WEB-INF/lib 用于 commons-fileupload.jar,并且他需要删除他添加到其他类路径的所有 jar。
      猜你喜欢
      • 2021-10-20
      • 2022-12-22
      • 2012-02-09
      • 2016-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多