Servlet 5.0 JAR 在 javax.servlet.* 上抛出编译错误,但 Servlet 4.0 JAR



我正在尝试从命令行编译和部署一个简单的Web应用程序。

来自Apache Tomcat的servlet-api.jar不能编译我的java文件,但是来自maven中央存储库的javax.servlet-api-4.0.1可以成功编译它。即便如此,当我部署应用程序并尝试在浏览器中使用它时,我还是会收到错误。

我正在使用:

  • 爪哇 11.0.8
  • Apache Tomcat 10.0 (servlet-api.jar 5.0)

Java文件:

package com.example.controllers;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class BeerSelect extends HttpServlet {

public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Beer Selection Advice <br>");
String c = request.getParameter("color");
out.println("<br>Got beer color " + c);
}               
} 

当我尝试使用 servlet-api 编译它时.jar我得到:

public class BeerSelect extends HttpServlet {
^
symbol: class HttpServlet
srccomexamplecontrollersBeerSelect.java:9: error: cannot find symbol
public void doPost(HttpServletRequest request,
^
symbol:   class HttpServletRequest
location: class BeerSelect
srccomexamplecontrollersBeerSelect.java:10: error: cannot find symbol
HttpServletResponse response)
^
symbol:   class HttpServletResponse
location: class BeerSelect
srccomexamplecontrollersBeerSelect.java:11: error: cannot find symbol
throws IOException, ServletException {
^
symbol:   class ServletException
location: class BeerSelect
srccomexamplecontrollersBeerSelect.java:3: error: package javax.servlet does not exist
import javax.servlet.*;
^
srccomexamplecontrollersBeerSelect.java:4: error: package javax.servlet.http does not exist
import javax.servlet.http.*;
^
6 errors 

但是,javax.servlet-api-4.0.1 成功编译该文件。注意:我已经测试并排除了命令行命令作为问题的可能原因。

当我将.class文件放在相应的Tomcat目录中,启动服务器并尝试与应用程序交互时,出现以下异常:

Exception
jakarta.servlet.ServletException: Error instantiating servlet class [com.example.controllers.BeerSelect]
Root Cause
java.lang.NoClassDefFoundError: javax/servlet/http/HttpServlet
Root Cause
java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet

我尝试将javax.servlet-api-4.0.1放在Tomcat/lib目录中,但后来我得到:

Exception
jakarta.servlet.ServletException: Class [com.example.controllers.BeerSelect] is not a Servlet
Root Cause
java.lang.ClassCastException: class com.example.controllers.BeerSelect cannot be cast to class jakarta.servlet.Servlet (com.example.controllers.BeerSelect is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @7862f56; jakarta.servlet.Servlet is in unnamed module of loader java.net.URLClassLoader @4b4523f8)

不确定最后一个是否有意义,但我没有想法了。

任何帮助都非常受欢迎!

当我将.class文件放在相应的Tomcat目录中,启动服务器并尝试与应用程序交互时,我得到以下异常:

java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet

我尝试将javax.servlet-api-4.0.1放在Tomcat/lib目录中,但随后我得到:

java.lang.ClassCastException: class com.example.controllers.BeerSelect
cannot be cast to class jakarta.servlet.Servlet

jakarta.servlet.Servlet是 Servlet API 版本 5.0 的一部分,而 Servlet API 版本 5.0 又是 Jakarta EE 版本 9 的一部分。您的 servlet 实际上是从javax.servlet.Servlet扩展而来的,而又是旧 JEE 版本的一部分,而您的目标运行时 (Tomcat 10.x) 实际上不支持该版本。

您有 2 个选项:

  1. 将代码中的导入javax.servlet.*替换为jakarta.servlet.*导入。

    import jakarta.servlet.*;
    import jakarta.servlet.http.*;
    

    然后,您可以针对基于 Servlet 5.0 的目标运行时中的库进行编译。

  2. 或者,将 Servlet 容器从 Servlet API 版本 5.0 降级到以前的版本,至少是仍然具有javax.servlet.*包名称的版本。Tomcat 9.x是最新的仍然具有旧软件包的版本。

技术原因是,在从 Java/Jakarta EE 8 到 Jakarta EE 9 的步骤中,所有javax.*包都已重命名为jakarta.*包。因此,自Jakarta EE 9以来不再向后兼容。

因此,当您在使用 Tomcat 10 或更高版本时,遵循任何仍然使用旧javax.servlet.*包的 servlet 教程时,您需要手动将代码示例中使用的包换成jakarta.servlet.*包。一般来说,它会正常工作。

绝对不要在Tomcat/lib中随机放置/交换API JAR文件。您基本上需要升级或降级整个Tomcat安装本身。

另请参阅:

  • Apache Tomcat - 版本
  • 如何在 Maven pom.xml for Tomcat 中正确配置 Jakarta EE 库?(此答案包含Tomcat 10+,Tomcat 9-,JEE 9+和JEE 8-的正确pom.xml声明的完整示例,以防万一您使用的是Maven)。

我已经测试并设法在Apache Tomcat 9.0.39上编译java文件。

目前,Apache Tomcat 10 正在开发中,没有稳定版本: http://tomcat.apache.org/whichversion.html

降级你的Apache Tomcat版本应该可以解决这个问题。

Sree Kumar 在另一个重复的问题上写了这条评论,为我解决了这个问题:

右键单击项目 -> 构建路径 -> 配置构建路径... ->库

(选项卡) -> 选择类路径 -> 添加库 ->服务器运行时 -> 选择您必须为 Tomcat 10 添加的那个。

最新更新