 
- Servlet 教程
- Servlet - 主页
- Servlet - 概述
- Servlet - 环境设置
- Servlet - 生命周期
- Servlet - 示例
- Servlet - 表单数据
- Servlet - 客户端请求
- Servlet - 服务器响应
- Servlet - Http 代码
- Servlet - 编写过滤器
- Servlet - 例外
- Servlet - Cookie 处理
- Servlet - 会话跟踪
- Servlet - 数据库访问
- Servlet - 文件上传
- Servlet - 处理日期
- Servlet - 页面重定向
- Servlet - 点击计数器
- Servlet - 自动刷新
- Servlet - 发送电子邮件
- Servlet - 包装
- Servlet - 调试
- Servlet - 国际化
- Servlet - 注释
- Servlet 有用资源
- Servlet - 问题与解答
- Servlet - 快速指南
- Servlet - 有用的资源
- Servlet - 讨论
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 执行以下主要任务 -
- 读取客户端(浏览器)发送的显式数据。这包括网页上的 HTML 表单,也可能来自小程序或自定义 HTTP 客户端程序。 
- 读取客户端(浏览器)发送的隐式 HTTP 请求数据。这包括浏览器理解的 cookie、媒体类型和压缩方案等等。 
- 处理数据并生成结果。此过程可能需要与数据库通信、执行 RMI 或 CORBA 调用、调用 Web 服务或直接计算响应。 
- 将显式数据(即文档)发送到客户端(浏览器)。该文档可以多种格式发送,包括文本(HTML 或 XML)、二进制(GIF 图像)、Excel 等。 
- 将隐式 HTTP 响应发送到客户端(浏览器)。这包括告诉浏览器或其他客户端正在返回什么类型的文档(例如 HTML)、设置 cookie 和缓存参数以及其他此类任务。 
Servlet 包
Java Servlet 是由 Web 服务器运行的 Java 类,该服务器具有支持 Java Servlet 规范的解释器。
Servlet 可以使用javax.servlet和javax.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 是为 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 - 表单数据
当您需要将一些信息从浏览器传递到 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/png或image/jpeg的值是两种最常见的可能性。 | 
| 2 | 接受字符集 该标头指定浏览器可用于显示信息的字符集。例如 ISO-8859-1。 | 
| 3 | 接受编码 该标头指定浏览器知道如何处理的编码类型。gzip或compress的值是两种最常见的可能性。 | 
| 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 | 缓存控制 该标头指定可以安全地缓存响应文档的环境。它可以具有public、private或no-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 | 没用过 | 
