我的 IDE 无法识别我的 servlet 的 HTML 命令

My IDE is not recognizing HTML commands for my servlet

我正在学习如何创建一个使用 HTML 代码并在我的浏览器中制作程序的 servlet。 这段代码应该通过 HTML 在我的浏览器中输出一条简单的欢迎消息。但是,My eclipse IDE 无法识别此代码中的任何 HTML 命令。它表示无法访问导入,并且无法将 HTTP 变量解析为类型。我使用 tomcat 版本 10.0.12 和 Java 13 作为代码(我也有 java 16,但 eclipse 只给我使用 13 的选项)。我试过多次卸载和重新安装 Tomcat 并添加 servlet-api.jar 但其中的 none 改变了一些东西。我知道我缺少一个额外的步骤,但我不知道它是什么?

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.*;

public class WelcomeServlet extends HttpServlet {   
@Override
protected void doGet( HttpServletRequest request, 
                   HttpServletResponse response ) throws ServletException, IOException  {

   response.setContentType( "text/html" );
   PrintWriter out = response.getWriter(); 
   out.println( "<title>Welcome to Servlets!</title>" ); 
   {...}
   out.println( "</html>" );
   out.close();  // close stream to complete the page
   } 
}

你搞砸了你的导入。听起来您正在学习一个已有 20 多年历史的教程,您所做的很多事情 非常 已经过时了。网络是一个相当快速移动的环境。我极力建议不要使用这些旧教程。

正确的导入是import javax.servlet.http.HttpServletRequest;

关于您正在做的事情的一些注释是坏主意:

  • 不建议明星进口;人们很容易对事物存在于何处或从何处获取哪种类型感到困惑。您的 IDE 为您管理导入;让它吧。

  • 您不想在代码中的字符串中写入 HTML。使用模板引擎,例如 Freemarker、Velocity、Thymeleaf 或 Google Closure Templates。或者,使用大量 javascript 编写静态 HTML(可能使用基于客户端 javascript 的框架),并将服务器编写为 API 不 'answer' 就 HTML 个文件而言;它根据一些结构化数据格式回答,例如 JSON。您的静态(如不变;任何文件服务 HTTP 服务都可以提供它们)HTML+CSS+Javascript 完成调用您的 API 来获得此结构化的工作数据,然后你的 HTML+CSS+JavaScript 将它渲染成 HTML.

  • 原始 servlet 已过时; API 非常旧,它表明,例如,您甚至不能使用简单的 for-each 循环来遍历所有参数名称,因为 API returns 已过时的枚举而不是更现代的 Iterator 甚至 Stream。你既没有得到在字段中存储中间状态的好处(因为你不能保证每次调用一个实例),但你也不能只将它全部转储到静态字段中(因为规范不保证有永远只会是一个实例)——两全其美。查看 JAX-RS、Jersey、Dropwizard、sparkjava 或其他此类框架。

tl;博士

您的项目缺少包含 Jakarta Servlet 定义的 JAR API(一组 interfaces)。

jakarta.servlet-api 添加为项目的依赖项,以便在开发期间向 IDE 提供所需的 JAR 文件,但在最终构建的 WAR 文件中省略。

详情

您的 import 语句在开发时参考 Jakarta Servlet API. That API is not built into Java. So you must make a Servlet API JAR file available to your IDE

通常在 Java 开发中,我们使用 Maven or Gradle 等工具来帮助我们 IDE 获取外部依赖项,例如 Servlet API JAR。

如果您使用的是 Maven,请编辑您的 POM file to specify a dependency for the Servlet API JAR published as part of the Jakarta.ee 项目,由 Eclipse Foundation 提供。

<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>5.0.0</version>
    <scope>provided</scope>
</dependency>

注意 scope 元素,其值为 provided。这意味着应该下载 JAR 文件,在开发时供您 IDE 使用,但在构建时 不应 将其复制到最终产品中。

构建的输出通常是 WAR 文件(不是 JAR)。 provided 范围意味着我们 想要 WAR 中的 Servlet API JAR 的副本。原因是在开发 Jakarta EE web 应用程序时,我们希望部署到一个兼容的应用程序服务器,该服务器带有自己的 Servlet API 副本。 Jakarta EE 兼容服务器的每个“配置文件”都需要包含 Servlet API.

的实现

因此您的 POM 将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>work.basil.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>demo</name>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>

这里是一个简单的 servlet 的源代码。

package work.basil.example.demo;

import java.io.*;

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

@WebServlet ( name = "helloServlet", value = "/hello-servlet" )
public class HelloServlet extends HttpServlet
{
    private String message;

    public void init ( )
    {
        message = "Hello World!";
    }

    public void doGet ( HttpServletRequest request , HttpServletResponse response ) throws IOException
    {
        response.setContentType( "text/html" );

        // Hello
        PrintWriter out = response.getWriter();
        out.println( "<html><body>" );
        out.println( "<h1>" + message + "</h1>" );
        out.println( "</body></html>" );
    }

    public void destroy ( )
    {
    }
}

你说:

I've tried uninstalling and reinstalling Tomcat several times

我想这与你的问题完全无关。

Tomcat 的安装附带了 Servlet API 的 实现 。但是您的 IDE 在开发过程中不会“看到”Tomcat。您的 IDE 需要查看 Servlet API.

中定义的 interfaces

你的 IDE 并没有实际执行你的 servlet,所以它不需要实现,它只需要接口。当您 运行 来自 IDE 的 Servlet 时,Tomcat 被 外部 从 IDE 调用。 IDE 将调试器连接附加到 Tomcat 以促进交互式调试,但 IDE 和 Tomcat 实际上 运行 在主机 OS。正如我所说,Tomcat 捆绑了自己对这些接口的实现,因此您的 servlet 能够执行。


您说您正在使用 Java 13。请注意,不再支持 Java 13。您应该移动到最新版本的 Java(截至 2021-11 年为 17),或者移动到 Long-Term Support (LTS) 版本之一(8、11、17)。

如果使用 Java 11 或 17 而不是 8,我建议使用 Tomcat 10.1.x 而不是 Tomcat 10.0.x。 Tomcat 10.1.x 支持 Jakarta EE 9.1 和 10,后者支持 Java 11 及更高版本,而 Java 8.

参见Tomcat version comparison page