Servlet - 快速指南


Servlet - 概述

什么是 Servlet?

Java Servlet 是在 Web 或应用程序服务器上运行的程序,充当来自 Web 浏览器或其他 HTTP 客户端的请求与 HTTP 服务器上的数据库或应用程序之间的中间层。

使用 Servlet,您可以通过网页表单收集用户的输入,显示数据库或其他来源的记录,并动态创建网页。

Java Servlet 通常与使用通用网关接口 (CGI) 实现的程序具有相同的用途。但与 CGI 相比,Servlet 有几个优点。

  • 性能明显更好。

  • Servlet 在 Web 服务器的地址空间内执行。没有必要创建单独的进程来处理每个客户端请求。

  • Servlet 是平台无关的,因为它们是用 Java 编写的。

  • 服务器上的 Java 安全管理器强制执行一组限制来保护服务器计算机上的资源。因此 servlet 是可信的。

  • Java 类库的全部功能可供 servlet 使用。它可以通过您已经见过的套接字和 RMI 机制与小程序、数据库或其他软件进行通信。

Servlet 架构

下图显示了 Servlet 在 Web 应用程序中的位置。

Servlet 架构

Servlet 任务

Servlet 执行以下主要任务 -

  • 读取客户端(浏览器)发送的显式数据。这包括网页上的 HTML 表单,也可能来自小程序或自定义 HTTP 客户端程序。

  • 读取客户端(浏览器)发送的隐式 HTTP 请求数据。这包括浏览器理解的 cookie、媒体类型和压缩方案等等。

  • 处理数据并生成结果。此过程可能需要与数据库通信、执行 RMI 或 CORBA 调用、调用 Web 服务或直接计算响应。

  • 将显式数据(即文档)发送到客户端(浏览器)。该文档可以多种格式发送,包括文本(HTML 或 XML)、二进制(GIF 图像)、Excel 等。

  • 将隐式 HTTP 响应发送到客户端(浏览器)。这包括告诉浏览器或其他客户端正在返回什么类型的文档(例如 HTML)、设置 cookie 和缓存参数以及其他此类任务。

Servlet 包

Java Servlet 是由 Web 服务器运行的 Java 类,该服务器具有支持 Java Servlet 规范的解释器。

Servlet 可以使用javax.servletjavax.servlet.http包创建,它们是 Java 企业版的标准部分,是支持大型开发项目的 Java 类库的扩展版本。

这些类实现 Java Servlet 和 JSP 规范。在编写本教程时,版本为 Java Servlet 2.5 和 JSP 2.1。

Java servlet 的创建和编译就像任何其他 Java 类一样。安装 servlet 包并将其添加到计算机的类路径后,您可以使用 JDK 的 Java 编译器或任何其他当前编译器来编译 servlet。

下一步是什么?

我将逐步指导您设置环境以开始使用 Servlet。因此,请系好安全带,享受 Servlet 带来的美好驾驶体验。我确信您会非常喜欢本教程。

Servlet - 环境设置

开发环境是您开发 Servlet、测试它们并最终运行它们的地方。

与任何其他 Java 程序一样,您需要使用 Java 编译器javac编译 servlet ,编译 servlet 应用程序后,它将部署在配置好的环境中进行测试和运行。

此开发环境设置涉及以下步骤 -

设置Java开发工具包

此步骤涉及下载 Java 软件开发工具包 (SDK) 的实现并适当设置 PATH 环境变量。

您可以从 Oracle 的 Java 站点 - Java SE 下载下载 SDK 。

下载 Java 实现后,请按照给定的说明进行安装和配置设置。最后设置 PATH 和 JAVA_HOME 环境变量以引用包含 java 和 javac 的目录,通常分别为 java_install_dir/bin 和 java_install_dir。

如果您运行的是 Windows 并将 SDK 安装在 C:\jdk1.8.0_65 中,则应将以下行放入 C:\autoexec.bat 文件中。

set PATH = C:\jdk1.8.0_65\bin;%PATH% 
set JAVA_HOME = C:\jdk1.8.0_65 

或者,在 Windows NT/2000/XP 上,您也可以右键单击“我的电脑”,选择“属性”,然后选择“高级”,然后选择“环境变量”。然后,您将更新 PATH 值并按“确定”按钮。

在 Unix(Solaris、Linux 等)上,如果 SDK 安装在 /usr/local/jdk1.8.0_65 中并且您使用 C shell,则需要将以下内容放入 .cshrc 文件中。

setenv PATH /usr/local/jdk1.8.0_65/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk1.8.0_65

或者,如果您使用 Borland JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio 等集成开发环境 (IDE),请编译并运行一个简单的程序以确认 IDE 知道您安装 Java 的位置。

设置 Web 服务器 - Tomcat

市场上有许多支持 servlet 的 Web 服务器。一些 Web 服务器可以免费下载,Tomcat 就是其中之一。

Apache Tomcat 是 Java Servlet 和 Java Server Pages 技术的开源软件实现,可以充当测试 servlet 的独立服务器,并且可以与 Apache Web 服务器集成。以下是在您的计算机上设置 Tomcat 的步骤 -

  • 从https://tomcat.apache.org/下载最新版本的 Tomcat 。

  • 下载安装后,将二进制发行版解压到一个方便的位置。例如,在 Windows 上的 C:\apache-tomcat-8.0.28 中,或在 Linux/Unix 上的 /usr/local/apache-tomcat-8.0.289 中,并创建指向这些位置的 CATALINA_HOME 环境变量。

Tomcat 可以通过在 Windows 机器上执行以下命令来启动 -

%CATALINA_HOME%\bin\startup.bat
or
C:\apache-tomcat-8.0.28\bin\startup.bat

Tomcat 可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来启动 -

$CATALINA_HOME/bin/startup.sh
or
/usr/local/apache-tomcat-8.0.28/bin/startup.sh

启动后,可以通过访问http://localhost:8080/ 来使用 Tomcat 附带的默认 Web 应用程序。如果一切正常那么它应该显示以下结果 -

雄猫主页

有关配置和运行 Tomcat 的更多信息可以在此处包含的文档以及 Tomcat 网站上找到 - http://tomcat.apache.org

可以通过在 Windows 机器上执行以下命令来停止 Tomcat -

C:\apache-tomcat-8.0.28\bin\shutdown 

可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来停止 Tomcat -

/usr/local/apache-tomcat-8.0.28/bin/shutdown.sh

设置 CLASSPATH

由于 servlet 不是 Java Platform, Standard Edition 的一部分,因此您必须向编译器标识 servlet 类。

如果您运行的是 Windows,则需要将以下行放入 C:\autoexec.bat 文件中。

set CATALINA = C:\apache-tomcat-8.0.28 
set CLASSPATH = %CATALINA%\common\lib\servlet-api.jar;%CLASSPATH% 

或者,在 Windows NT/2000/XP 上,您可以转到“我的电脑”->“属性”->“高级”->“环境变量”。然后,您将更新 CLASSPATH 值并按“确定”按钮。

在 Unix(Solaris、Linux 等)上,如果您使用 C shell,则应将以下几行放入 .cshrc 文件中。

setenv CATALINA = /usr/local/apache-tomcat-8.0.28
setenv CLASSPATH $CATALINA/common/lib/servlet-api.jar:$CLASSPATH

注意- 假设您的开发目录是 C:\ServletDevel (Windows) 或 /usr/ServletDevel (Unix),那么您需要以与上面添加类似的方式将这些目录添加到 CLASSPATH 中。

Servlet - 生命周期

Servlet 的生命周期可以定义为从创建到销毁的整个过程。以下是 servlet 遵循的路径。

  • Servlet 通过调用init()方法进行初始化。

  • Servlet 调用service()方法来处理客户端的请求。

  • Servlet 通过调用destroy()方法来终止。

  • 最后,servlet被JVM的垃圾收集器进行垃圾收集。

现在让我们详细讨论生命周期方法。

init() 方法

init 方法仅被调用一次。仅在创建 servlet 时调用它,之后不会为任何用户请求调用它。因此,它用于一次性初始化,就像小程序的 init 方法一样。

Servlet 通常是在用户首次调用与 Servlet 对应的 URL 时创建的,但您也可以指定在服务器首次启动时加载 Servlet。

当用户调用 servlet 时,将创建每个 servlet 的单个实例,每个用户请求都会产生一个新线程,该线程将根据需要移交给 doGet 或 doPost。init() 方法只是创建或加载一些将在 servlet 的整个生命周期中使用的数据。

init 方法定义如下 -

public void init() throws ServletException {
   // Initialization code...
}

service() 方法

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求并将格式化的响应写回客户端。

每次服务器收到对 servlet 的请求时,服务器都会生成一个新线程并调用服务。service()方法检查HTTP请求类型(GET、POST、PUT、DELETE等)并根据需要调用doGet、doPost、doPut、doDelete等方法。

这是该方法的签名 -

public void service(ServletRequest request, ServletResponse response) 
   throws ServletException, IOException {
}

service()方法由容器调用,service方法根据需要调用doGet、doPost、doPut、doDelete等方法。因此,您与 service() 方法无关,但您可以根据从客户端收到的请求类型来重写 doGet() 或 doPost() 。

doGet() 和 doPost() 是每个服务请求中最常用的方法。这是这两个方法的签名。

doGet() 方法

GET 请求源自对 URL 的正常请求或源自未指定 METHOD 的 HTML 表单,并且应由 doGet() 方法处理。

public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
   // Servlet code
}

doPost() 方法

POST 请求来自 HTML 表单,该表单专门将 POST 列为 METHOD,并且应由 doPost() 方法处理。

public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
   // Servlet code
}

destroy() 方法

destroy() 方法仅在 servlet 生命周期结束时调用一次。此方法使您的 servlet 有机会关闭数据库连接、停止后台线程、将 cookie 列表或命中计数写入磁盘以及执行其他此类清理活动。

调用 destroy() 方法后,servlet 对象被标记为垃圾回收。destroy 方法定义如下 -

public void destroy() {
   // Finalization code...
}

架构图

下图描述了一个典型的 servlet 生命周期场景。

  • 首先,到达服务器的 HTTP 请求被委托给 servlet 容器。

  • servlet 容器在调用 service() 方法之前加载 servlet。

  • 然后,servlet 容器通过生成多个线程来处理多个请求,每个线程执行 servlet 的单个实例的 service() 方法。

Servlet 生命周期

Servlet - 示例

Servlet 是为 HTTP 请求提供服务并实现javax.servlet.Servlet接口的 Java 类。Web 应用程序开发人员通常编写扩展 javax.servlet.http.HttpServlet 的 servlet,javax.servlet.http.HttpServlet 是一个实现 Servlet 接口的抽象类,专门设计用于处理 HTTP 请求。

示例代码

以下是 servlet 示例的示例源代码结构,用于显示 Hello World -

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

// Extend HttpServlet class
public class HelloWorld extends HttpServlet {
 
   private String message;

   public void init() throws ServletException {
      // Do required initialization
      message = "Hello World";
   }

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

      // Actual logic goes here.
      PrintWriter out = response.getWriter();
      out.println("<h1>" + message + "</h1>");
   }

   public void destroy() {
      // do nothing.
   }
}

编译 Servlet

让我们使用上面所示的代码创建一个名为 HelloWorld.java 的文件。将此文件放置在 C:\ServletDevel(在 Windows 中)或 /usr/ServletDevel(在 Unix 中)。在继续操作之前,必须将此路径位置添加到 CLASSPATH 中。

假设您的环境设置正确,请进入ServletDevel目录并编译 HelloWorld.java,如下所示 -

$ javac HelloWorld.java

如果 servlet 依赖于任何其他库,则还必须将这些 JAR 文件包含在 CLASSPATH 中。我只包含 servlet-api.jar JAR 文件,因为我没有在 Hello World 程序中使用任何其他库。

该命令行使用 Sun Microsystems Java 软件开发工具包 (JDK) 附带的内置 javac 编译器。为了使此命令正常工作,您必须在 PATH 环境变量中包含您正在使用的 Java SDK 的位置。

如果一切顺利,上面的编译将在同一目录中生成HelloWorld.class文件。下一节将解释如何在生产中部署已编译的 servlet。

Servlet 部署

默认情况下,servlet 应用程序位于路径 <Tomcat-installationdirectory>/webapps/ROOT,类文件将驻留在 <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes 中。

如果您有完全限定的类名com.myorg.MyServlet,则此 servlet 类必须位于 WEB-INF/classes/com/myorg/MyServlet.class 中。

现在,让我们将 HelloWorld.class 复制到 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中,并在位于 <Tomcat-installation-directory>/webapps/ROOT/WEB- 的web.xml文件中创建以下条目信息/

<servlet>
   <servlet-name>HelloWorld</servlet-name>
   <servlet-class>HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>HelloWorld</servlet-name>
   <url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>

上述条目将在 web.xml 文件中的 <web-app>...</web-app> 标签内创建。该表中可能有各种可用的条目,但没关系。

您快完成了,现在让我们使用 <Tomcat-installationdirectory>\bin\startup.bat (在 Windows 上)或 <Tomcat-installationdirectory>/bin/startup.sh (在 Linux/Solaris 等上)启动 tomcat 服务器,最后键入在浏览器地址框中输入http://localhost:8080/HelloWorld 。如果一切顺利,您将得到以下结果

Servlet 示例

Servlet - 表单数据

当您需要将一些信息从浏览器传递到 Web 服务器并最终传递到后端程序时,您一定遇到过很多情况。浏览器使用两种方法将此信息传递给 Web 服务器。这些方法是 GET 方法和 POST 方法。

获取方法

GET 方法发送附加到页面请求的编码用户信息。页面和编码信息由?分隔。(问号)符号如下 -

http://www.test.com/hello?key1 = value1&key2 = value2

GET 方法是从浏览器向 Web 服务器传递信息的默认方法,它会生成一个长字符串,显示在浏览器的 Location:box 中。如果您有密码或其他敏感信息要传递到服务器,切勿使用 GET 方法。GET 方法有大小限制:请求字符串中只能使用 1024 个字符。

此信息使用 QUERY_STRING 标头传递,并且可通过 QUERY_STRING 环境变量访问,Servlet 使用doGet()方法处理此类请求。

邮寄方式

通常,将信息传递给后端程序的更可靠的方法是 POST 方法。这以与 GET 方法完全相同的方式打包信息,但不是在 ? 之后将其作为文本字符串发送。(问号)在 URL 中作为单独的消息发送。该消息以标准输入的形式到达后端程序,您可以对其进行解析并用于处理。Servlet 使用doPost()方法处理此类请求。

使用Servlet读取表单数据

Servlet 根据情况使用以下方法自动处理表单数据解析 -

  • getParameter() - 您调用 request.getParameter() 方法来获取表单参数的值。

  • getParameterValues() - 如果参数出现多次并返回多个值(例如复选框),则调用此方法。

  • getParameterNames() - 如果您想要当前请求中所有参数的完整列表,请调用此方法。

使用 URL 的 GET 方法示例

这是一个简单的 URL,它将使用 GET 方法将两个值传递给 HelloForm 程序。

http://localhost:8080/HelloForm?first_name = ZARA&last_name = ALI

下面给出的是HelloForm.java servlet 程序,用于处理 Web 浏览器给出的输入。我们将使用getParameter()方法,这使得访问传递的信息变得非常容易 -

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

// Extend HttpServlet class
public class HelloForm extends HttpServlet {
 
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Using GET Method to Read Form Data";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n";
         
      out.println(docType +
         "<html>\n" +
            "<head><title>" + title + "</title></head>\n" +
            "<body bgcolor = \"#f0f0f0\">\n" +
               "<h1 align = \"center\">" + title + "</h1>\n" +
               "<ul>\n" +
                  "  <li><b>First Name</b>: "
                  + request.getParameter("first_name") + "\n" +
                  "  <li><b>Last Name</b>: "
                  + request.getParameter("last_name") + "\n" +
               "</ul>\n" +
            "</body>" +
         "</html>"
      );
   }
}

假设您的环境设置正确,请按如下方式编译 HelloForm.java -

$ javac HelloForm.java

如果一切顺利,上面的编译将生成HelloForm.class文件。接下来,您必须将此类文件复制到 <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes 中,并在位于 <Tomcat-installation-directory>/webapps/ROOT/WEB- 的web.xml文件中创建以下条目信息/

<servlet>
   <servlet-name>HelloForm</servlet-name>
   <servlet-class>HelloForm</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>HelloForm</servlet-name>
   <url-pattern>/HelloForm</url-pattern>
</servlet-mapping>

现在在浏览器的 Location: 框中输入http://localhost:8080/HelloForm?first_name=ZARA&last_name=ALI并确保在浏览器中触发上述命令之前已经启动了 tomcat 服务器。这将产生以下结果 -

Using GET Method to Read Form Data

  • First Name: ZARA
  • Last Name: ALI

使用表单的 GET 方法示例

这是一个简单的示例,它使用 HTML FORM 和提交按钮传递两个值。我们将使用相同的 Servlet HelloForm 来处理此输入。

<html>
   <body>
      <form action = "HelloForm" method = "GET">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
   </body>
</html>

将此 HTML 保存在文件 Hello.htm 中,并将其放在 <Tomcat-installationdirectory>/webapps/ROOT 目录中。当您访问http://localhost:8080/Hello.htm时,以下是上述表单的实际输出。

名: 姓:

尝试输入名字和姓氏,然后单击提交按钮以在运行 tomcat 的本地计算机上查看结果。根据提供的输入,它将生成与上面示例中提到的类似的结果。

使用表单的 POST 方法示例

让我们对上面的 servlet 做一些修改,以便它可以处理 GET 以及 POST 方法。下面是HelloForm.java servlet 程序,用于使用 GET 或 POST 方法处理 Web 浏览器给出的输入。

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

// Extend HttpServlet class
public class HelloForm extends HttpServlet {

   // Method to handle GET method request.
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Using GET Method to Read Form Data";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " +
         "transitional//en\">\n";
         
      out.println(docType +
         "<html>\n" +
            "<head><title>" + title + "</title></head>\n" +
            "<body bgcolor = \"#f0f0f0\">\n" +
               "<h1 align = \"center\">" + title + "</h1>\n" +
               "<ul>\n" +
                  "  <li><b>First Name</b>: "
                  + request.getParameter("first_name") + "\n" +
                  "  <li><b>Last Name</b>: "
                  + request.getParameter("last_name") + "\n" +
               "</ul>\n" +
            "</body>"
         "</html>"
      );
   }

   // Method to handle POST method request.
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      doGet(request, response);
   }
}

现在编译并部署上述 Servlet,并使用 Hello.htm 和 POST 方法对其进行测试,如下所示 -

<html>
   <body>
      <form action = "HelloForm" method = "POST">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
   </body>
</html>

以下是上述表单的实际输出,尝试输入名字和姓氏,然后单击提交按钮以在运行 tomcat 的本地计算机上查看结果。

名: 姓:

根据提供的输入,它将生成与上述示例中提到的类似的结果。

将复选框数据传递给 Servlet 程序

当需要选择多个选项时,请使用复选框。

以下是示例 HTML 代码 CheckBox.htm,用于具有两个复选框的表单

<html>
   <body>
      <form action = "CheckBox" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> 
                                          Chemistry
         <input type = "submit" value = "Select Subject" />
      </form>
   </body>
</html>

这段代码的结果是以下形式

数学 物理 化学

下面给出的是 CheckBox.java servlet 程序,用于处理 Web 浏览器为复选框按钮提供的输入。

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

// Extend HttpServlet class
public class CheckBox extends HttpServlet {
 
   // Method to handle GET method request.
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Reading Checkbox Data";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n";

      out.println(docType +
         "<html>\n" +
            "<head><title>" + title + "</title></head>\n" +
            "<body bgcolor = \"#f0f0f0\">\n" +
               "<h1 align = \"center\">" + title + "</h1>\n" +
               "<ul>\n" +
                  "  <li><b>Maths Flag : </b>: "
                  + request.getParameter("maths") + "\n" +
                  "  <li><b>Physics Flag: </b>: "
                  + request.getParameter("physics") + "\n" +
                  "  <li><b>Chemistry Flag: </b>: "
                  + request.getParameter("chemistry") + "\n" +
               "</ul>\n" +
            "</body>"
         "</html>"
      );
   }

   // Method to handle POST method request.
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      doGet(request, response);
   }
}

对于上面的示例,它将显示以下结果 -

Reading Checkbox Data

  • Maths Flag : : on
  • Physics Flag: : null
  • Chemistry Flag: : on

读取所有表单参数

以下是使用 HttpServletRequest 的getParameterNames()方法读取所有可用表单参数的通用示例。此方法返回一个枚举,其中包含未指定顺序的参数名称

一旦我们有了一个枚举,我们就可以以标准方式循环枚举,使用hasMoreElements()方法来确定何时停止并使用nextElement()方法来获取每个参数名称。

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

// Extend HttpServlet class
public class ReadParams extends HttpServlet {
 
   // Method to handle GET method request.
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Reading All Form Parameters";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n";

      out.println(docType +
         "<html>\n" +
         "<head><title>" + title + "</title></head>\n" +
         "<body bgcolor = \"#f0f0f0\">\n" +
         "<h1 align = \"center\">" + title + "</h1>\n" +
         "<table width = \"100%\" border = \"1\" align = \"center\">\n" +
         "<tr bgcolor = \"#949494\">\n" +
            "<th>Param Name</th>"
            "<th>Param Value(s)</th>\n"+
         "</tr>\n"
      );

      Enumeration paramNames = request.getParameterNames();

      while(paramNames.hasMoreElements()) {
         String paramName = (String)paramNames.nextElement();
         out.print("<tr><td>" + paramName + "</td>\n<td>");
         String[] paramValues = request.getParameterValues(paramName);

         // Read single valued data
         if (paramValues.length == 1) {
            String paramValue = paramValues[0];
            if (paramValue.length() == 0)
               out.println("<i>No Value</i>");
               else
               out.println(paramValue);
         } else {
            // Read multiple valued data
            out.println("<ul>");

            for(int i = 0; i < paramValues.length; i++) {
               out.println("<li>" + paramValues[i]);
            }
            out.println("</ul>");
         }
      }
      out.println("</tr>\n</table>\n</body></html>");
   }
   
   // Method to handle POST method request.
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      doGet(request, response);
   }
}

现在,尝试使用以下形式的上述 servlet -

<html>
   <body>
      <form action = "ReadParams" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> Chem
         <input type = "submit" value = "Select Subject" />
      </form>
   </body>
</html>

现在使用上述形式调用 servlet 将生成以下结果 -

Reading All Form Parameters

Param Name Param Value(s)
maths on
chemistry on

您可以尝试上述 servlet 来读取具有其他对象(如文本框、单选按钮或下拉框等)的任何其他表单的数据。

Servlet - 客户端 HTTP 请求

当浏览器请求网页时,它会向 Web 服务器发送大量无法直接读取的信息,因为这些信息作为 HTTP 请求标头的一部分传输。您可以检查HTTP 协议以获取更多信息。

以下是来自浏览器端的重要标头信息,您在 Web 编程中会经常使用 -

先生。 标题和描述
1

接受

该标头指定浏览器或其他客户端可以处理的 MIME 类型。image/pngimage/jpeg的值是两种最常见的可能性。

2

接受字符集

该标头指定浏览器可用于显示信息的字符集。例如 ISO-8859-1。

3

接受编码

该标头指定浏览器知道如何处理的编码类型。gzipcompress的值是两种最常见的可能性。

4

接受语言

此标头指定客户端的首选语言,以防 servlet 可以以多种语言生成结果。例如 en、en-us、ru 等

5

授权

客户端在访问受密码保护的网页时使用此标头来识别自己的身份。

6

联系

该标头指示客户端是否可以处理持久 HTTP 连接。持久连接允许客户端或其他浏览器通过单个请求检索多个文件。Keep-Alive值意味着应使用持久连接。

7

内容长度

此标头仅适用于 POST 请求,并给出 POST 数据的大小(以字节为单位)。

8

曲奇饼

此标头将 cookie 返回到之前将 cookie 发送到浏览器的服务器。

9

主持人

此标头指定原始 URL 中给出的主机和端口。

10

如果-修改-自

此标头表明客户端仅需要在指定日期之后更改的页面。服务器发送代码 304,这意味着如果没有更新的结果可用,则未修改标头。

11

如果-未修改-自

该标头与 If-Modified-Since 相反;它指定仅当文档早于指定日期时操作才应成功。

12

推荐人

该标头指示引用网页的 URL。例如,如果您在网页 1 上单击指向网页 2 的链接,则当浏览器请求网页 2 时,网页 1 的 URL 将包含在 Referrer 标头中。

13

用户代理

此标头标识发出请求的浏览器或其他客户端,并可用于向不同类型的浏览器返回不同的内容。

读取 HTTP 标头的方法

有以下方法可用于读取 servlet 程序中的 HTTP 标头。这些方法可用于HttpServletRequest对象

先生。 方法及说明
1

Cookie[] getCookies()

返回一个数组,其中包含客户端通过此请求发送的所有 Cookie 对象。

2

枚举 getAttributeNames()

返回一个枚举,其中包含可用于此请求的属性的名称。

3

枚举 getHeaderNames()

返回此请求包含的所有标头名称的枚举。

4

枚举 getParameterNames()

返回包含此请求中包含的参数名称的字符串对象的枚举

5

HttpSession getSession()

返回与此请求关联的当前会话,或者如果该请求没有会话,则创建一个会话。

6

HttpSession getSession(布尔创建)

返回与此请求关联的当前 HttpSession,或者,如果没有当前会话且 create 值为 true,则返回一个新会话。

7

区域设置 getLocale()

根据 Accept-Language 标头,返回客户端接受内容的首选区域设置。

8

对象 getAttribute(字符串名称)

以对象形式返回指定属性的值,如果给定名称的属性不存在,则返回 null。

9

ServletInputStream 获取输入流()

使用 ServletInputStream 以二进制数据形式检索请求正文。

10

字符串 getAuthType()

返回用于保护 servlet 的身份验证方案的名称,例如“BASIC”或“SSL”,如果 JSP 不受保护,则返回 null。

11

字符串 getCharacterEncoding()

返回此请求正文中使用的字符编码的名称。

12

字符串 getContentType()

返回请求正文的 MIME 类型,如果类型未知,则返回 null。

13

字符串 getContextPath()

返回请求 URI 中指示请求上下文的部分。

14

String getHeader(字符串名称)

以字符串形式返回指定请求标头的值。

15

字符串获取方法()

返回发出此请求所使用的 HTTP 方法的名称,例如 GET、POST 或 PUT。

16

字符串获取参数(字符串名称)

以字符串形式返回请求参数的值,如果参数不存在则返回 null。

17 号

字符串 getPathInfo()

返回与客户端发出此请求时发送的 URL 关联的任何额外路径信息

18

字符串 getProtocol()

返回请求的协议的名称和版本。

19

字符串 getQueryString()

返回请求 URL 中路径后面包含的查询字符串。

20

字符串 getRemoteAddr()

返回发送请求的客户端的 Internet 协议 (IP) 地址。

21

字符串 getRemoteHost()

返回发送请求的客户端的完全限定名称。

22

字符串 getRemoteUser()

如果用户已通过身份验证,则返回发出此请求的用户的登录名;如果用户尚未通过身份验证,则返回 null。

23

字符串 getRequestURI()

返回此请求的 URL 部分,从协议名称到 HTTP 请求第一行中的查询字符串。

24

字符串 getRequestedSessionId()

返回客户端指定的会话 ID。

25

字符串 getServletPath()

返回此请求的 URL 中调用 JSP 的部分。

26

String[] getParameterValues(字符串名称)

返回一个 String 对象数组,其中包含给定请求参数的所有值;如果参数不存在,则返回 null。

27

布尔值 isSecure()

返回一个布尔值,指示此请求是否是使用安全通道(例如 HTTPS)发出的。

28

int getContentLength()

返回请求正文的长度(以字节为单位)并由输入流提供,如果长度未知,则返回 -1。

29

int getIntHeader(字符串名称)

以 int 形式返回指定请求标头的值。

30

int getServerPort()

返回接收此请求的端口号。

HTTP 标头请求示例

以下是使用 HttpServletRequest 的getHeaderNames()方法读取 HTTP 标头信息的示例。此方法返回一个枚举,其中包含与当前 HTTP 请求关联的标头信息。

一旦我们有了一个枚举,我们就可以以标准方式循环枚举,使用hasMoreElements()方法来确定何时停止并使用nextElement()方法来获取每个参数名称

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
 
// Extend HttpServlet class
public class DisplayHeader extends HttpServlet {
 
   // Method to handle GET method request.
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      // Set response content type
      response.setContentType("text/html");
 
      PrintWriter out = response.getWriter();
      String title = "HTTP Header Request Example";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n";

      out.println(docType +
         "<html>\n" +
         "<head><title>" + title + "</title></head>\n"+
         "<body bgcolor = \"#f0f0f0\">\n" +
         "<h1 align = \"center\">" + title + "</h1>\n" +
         "<table width = \"100%\" border = \"1\" align = \"center\">\n" +
         "<tr bgcolor = \"#949494\">\n" +
         "<th>Header Name</th><th>Header Value(s)</th>\n"+
         "</tr>\n"
      );
 
      Enumeration headerNames = request.getHeaderNames();
    
      while(headerNames.hasMoreElements()) {
         String paramName = (String)headerNames.nextElement();
         out.print("<tr><td>" + paramName + "</td>\n");
         String paramValue = request.getHeader(paramName);
         out.println("<td> " + paramValue + "</td></tr>\n");
      }
      out.println("</table>\n</body></html>");
   }
   
   // Method to handle POST method request.
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      doGet(request, response);
   }
}

现在调用上面的 servlet 将生成以下结果 -

HTTP Header Request Example

Header Name Header Value(s)
accept */*
accept-language en-us
user-agent Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; MS-RTC LM 8)
accept-encoding gzip, deflate
host localhost:8080
connection Keep-Alive
cache-control no-cache

Servlet - 服务器 HTTP 响应

正如前一章所讨论的,当 Web 服务器响应 HTTP 请求时,响应通常由状态行、一些响应标头、空行和文档组成。典型的响应如下所示 -

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>
<html>
   <head>...</head>
   <body>
      ...
   </body>
</html>

状态行由 HTTP 版本(示例中为 HTTP/1.1)、状态代码(示例中为 200)以及与状态代码对应的非常短的消息(示例中为 OK)组成。

以下是最有用的 HTTP 1.1 响应标头的摘要,这些响应标头从 Web 服务器端返回到浏览器,您将在 Web 编程中非常频繁地使用它们 -

先生。 标题和描述
1

允许

该标头指定服务器支持的请求方法(GET、POST 等)。

2

缓存控制

该标头指定可以安全地缓存响应文档的环境。它可以具有publicprivateno-cache等值。 Public 表示文档可缓存, Private 表示文档适用于单个用户,只能存储在私有(非共享)缓存中, nocache 表示文档不应被缓存。

3

联系

该标头指示浏览器是否在 HTTP 连接中使用持久性。close值指示浏览器不使用持久 HTTP 连接,而keepalive表示使用持久连接。

4

内容处置

通过此标头,您可以请求浏览器要求用户将响应保存到磁盘上给定名称的文件中。

5

内容编码

该标头指定了传输期间页面的编码方式。

6

内容语言

该标题表示编写文档所用的语言。例如 en、en-us、ru 等

7

内容长度

该标头指示响应中的字节数。仅当浏览器使用持久(保持活动)HTTP 连接时才需要此信息。

8

内容类型

该标头给出了响应文档的 MIME(多用途 Internet 邮件扩展)类型。

9

过期

此标头指定内容应被视为过时并因此不再被缓存的时间。

10

上一次更改

此标头指示文档上次更改的时间。然后,客户端可以缓存该文档,并在以后的请求中通过If-Modified-Since请求标头提供日期。

11

地点

此标头应包含在状态代码在 300 秒内的所有响应中。这会通知浏览器文档地址。浏览器会自动重新连接到该位置并检索新文档。

12

刷新

此标头指定浏览器应多长时间请求更新页面。您可以指定刷新页面的时间(以秒为单位)。

13

之后重试

此标头可以与 503(服务不可用)响应结合使用,告诉客户端多久可以重复其请求。

14

设置Cookie

该标头指定与该页面关联的 cookie。

设置 HTTP 响应标头的方法

有以下方法可用于在 servlet 程序中设置 HTTP 响应标头。这些方法可用于HttpServletResponse对象。

先生。 方法及说明
1

字符串encodeRedirectURL(字符串url)

对指定的 URL 进行编码以在 sendRedirect 方法中使用,或者如果不需要编码,则返回未更改的 URL。

2

字符串编码URL(字符串url)

通过在其中包含会话 ID 来对指定的 URL 进行编码,或者,如果不需要编码,则返回原样的 URL。

3

布尔包含标题(字符串名称)

返回一个布尔值,指示指定的响应标头是否已设置。

4

布尔值 isCommited()

返回一个布尔值,指示响应是否已提交。

5

无效addCookie(Cookie cookie)

将指定的 cookie 添加到响应中。

6

void addDateHeader(字符串名称,长日期)

添加具有给定名称和日期值的响应标头。

7

void addHeader(字符串名称,字符串值)

添加具有给定名称和值的响应标头。

8

void addIntHeader(字符串名称, int 值)

添加具有给定名称和整数值的响应标头。

9

无效的flushBuffer()

强制将缓冲区中的任何内容写入客户端。

10

无效重置()

清除缓冲区中存在的所有数据以及状态代码和标头。

11

无效重置缓冲区()

清除响应中底层缓冲区的内容,而不清除标头或状态代码。

12

无效发送错误(int sc)

使用指定的状态代码向客户端发送错误响应并清除缓冲区。

13

无效sendError(int sc,字符串消息)

使用指定的状态向客户端发送错误响应。

14

无效sendRedirect(字符串位置)

使用指定的重定向位置 URL 向客户端发送临时重定向响应。

15

无效setBufferSize(int大小)

设置响应正文的首选缓冲区大小。

16

无效setCharacterEncoding(字符串字符集)

设置发送到客户端的响应的字符编码(MIME 字符集),例如,设置为 UTF-8。

17 号

无效设置内容长度(int len)

设置响应中内容正文的长度 在 HTTP servlet 中,此方法设置 HTTP Content-Length 标头。

18

void setContentType(字符串类型)

如果响应尚未提交,则设置发送到客户端的响应的内容类型。

19

void setDateHeader(字符串名称,长日期)

设置具有给定名称和日期值的响应标头。

20

void setHeader(字符串名称,字符串值)

设置具有给定名称和值的响应标头。

21

void setIntHeader(字符串名称, int 值)

设置具有给定名称和整数值的响应标头

22

void setLocale(区域设置 loc)

如果响应尚未提交,则设置响应的区域设置。

23

无效 setStatus(int sc)

设置此响应的状态代码

HTTP 标头响应示例

您已经在前面的示例中看到了 setContentType() 方法的工作原理,下面的示例也将使用相同的方法,此外我们将使用setIntHeader()方法来设置刷新标头。

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
 
// Extend HttpServlet class
public class Refresh extends HttpServlet {
 
   // Method to handle GET method request.
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   
      // Set refresh, autoload time as 5 seconds
      response.setIntHeader("Refresh", 5);
 
      // Set response content type
      response.setContentType("text/html");
 
      // Get current time
      Calendar calendar = new GregorianCalendar();
      String am_pm;
      int hour = calendar.get(Calendar.HOUR);
      int minute = calendar.get(Calendar.MINUTE);
      int second = calendar.get(Calendar.SECOND);
         
      if(calendar.get(Calendar.AM_PM) == 0)
         am_pm = "AM";
      else
         am_pm = "PM";
 
      String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
    
      PrintWriter out = response.getWriter();
      String title = "Auto Refresh Header Setting";
      String docType =
         "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n";

      out.println(docType +
         "<html>\n" +
         "<head><title>" + title + "</title></head>\n"+
         "<body bgcolor = \"#f0f0f0\">\n" +
         "<h1 align = \"center\">" + title + "</h1>\n" +
         "<p>Current Time is: " + CT + "</p>\n"
      );
   }
   
   // Method to handle POST method request.
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      
      doGet(request, response);
   }
}

现在调用上面的 servlet 将每 5 秒显示一次当前系统时间,如下所示。只需运行 servlet 并等待查看结果 -

Auto Refresh Header Setting

Current Time is: 9:44:50 PM

Servlet - Http 状态代码

HTTP 请求和 HTTP 响应消息的格式相似,并且具有以下结构 -

  • 初始状态行 + CRLF(回车 + 换行即换行)

  • 零个或多个标题行 + CRLF

  • 空行,即 CRLF

  • 可选的消息正文,例如文件、查询数据或查询输出。

例如,服务器响应标头如下所示 -

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>
<html>
   <head>...</head>
   <body>
      ...
   </body>
</html>

状态行由 HTTP 版本(示例中为 HTTP/1.1)、状态代码(示例中为 200)以及与状态代码对应的非常短的消息(示例中为 OK)组成。

以下是可能从 Web 服务器返回的 HTTP 状态代码和相关消息的列表 -

代码 信息 描述
100 继续 服务器只收到了部分请求,但只要没有被拒绝,客户端就应该继续请求
101 切换协议 服务器切换协议。
200 好的 请求没问题
201 已创建 请求完成,创建新资源
第202章 公认 请求已接受处理,但处理尚未完成。
203 非权威信息  
204 无内容  
205 重置内容  
206 部分内容  
300 多种选择 一个链接列表。用户可以选择一个链接并转到该位置。最多五个地址
301 永久搬家 请求的页面已移至新网址
第302章 成立 请求的页面已暂时移至新网址
303 查看其他 请求的页面可以在不同的 url 下找到
304 未修改  
305 使用代理服务器  
306 没用过