Servlets 简明教程

Servlets - Quick Guide

Servlets - Overview

What are Servlets?

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

Java Servlets are programs that run on a Web or Application server and act as a middle layer between a requests coming from a Web browser or other HTTP client and databases or applications on the HTTP server.

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

Using Servlets, you can collect input from users through web page forms, present records from a database or another source, and create web pages dynamically.

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

Java Servlets often serve the same purpose as programs implemented using the Common Gateway Interface (CGI). But Servlets offer several advantages in comparison with the CGI.

  1. Performance is significantly better.

  2. Servlets execute within the address space of a Web server. It is not necessary to create a separate process to handle each client request.

  3. Servlets are platform-independent because they are written in Java.

  4. Java security manager on the server enforces a set of restrictions to protect the resources on a server machine. So servlets are trusted.

  5. The full functionality of the Java class libraries is available to a servlet. It can communicate with applets, databases, or other software via the sockets and RMI mechanisms that you have seen already.

Servlets Architecture

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

The following diagram shows the position of Servlets in a Web Application.

servlet arch

Servlets Tasks

Servlet 执行以下主要任务 -

Servlets perform the following major tasks −

  1. Read the explicit data sent by the clients (browsers). This includes an HTML form on a Web page or it could also come from an applet or a custom HTTP client program.

  2. Read the implicit HTTP request data sent by the clients (browsers). This includes cookies, media types and compression schemes the browser understands, and so forth.

  3. Process the data and generate the results. This process may require talking to a database, executing an RMI or CORBA call, invoking a Web service, or computing the response directly.

  4. Send the explicit data (i.e., the document) to the clients (browsers). This document can be sent in a variety of formats, including text (HTML or XML), binary (GIF images), Excel, etc.

  5. Send the implicit HTTP response to the clients (browsers). This includes telling the browsers or other clients what type of document is being returned (e.g., HTML), setting cookies and caching parameters, and other such tasks.

Servlets Packages

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

Java Servlets are Java classes run by a web server that has an interpreter that supports the Java Servlet specification.

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

Servlets can be created using the javax.servlet and javax.servlet.http packages, which are a standard part of the Java’s enterprise edition, an expanded version of the Java class library that supports large-scale development projects.

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

These classes implement the Java Servlet and JSP specifications. At the time of writing this tutorial, the versions are Java Servlet 2.5 and JSP 2.1.

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

Java servlets have been created and compiled just like any other Java class. After you install the servlet packages and add them to your computer’s Classpath, you can compile servlets with the JDK’s Java compiler or any other current compiler.

What is Next?

我将一步步带您设置环境以开始使用 Servlet。因此,系好安全带,享受与 Servlet 的驾驶乐趣。我相信您会非常喜欢本教程。

I would take you step by step to set up your environment to start with Servlets. So fasten your belt for a nice drive with Servlets. I’m sure you are going to enjoy this tutorial very much.

Servlets - Environment Setup

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

A development environment is where you would develop your Servlet, test them and finally run them.

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

Like any other Java program, you need to compile a servlet by using the Java compiler javac and after compilation the servlet application, it would be deployed in a configured environment to test and run..

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

This development environment setup involves the following steps −

Setting up Java Development Kit

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

This step involves downloading an implementation of the Java Software Development Kit (SDK) and setting up PATH environment variable appropriately.

您可从 Oracle 的 Java 网站下载 SDK− Java SE Downloads

You can download SDK from Oracle’s Java site − Java SE Downloads.

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

Once you download your Java implementation, follow the given instructions to install and configure the setup. Finally set PATH and JAVA_HOME environment variables to refer to the directory that contains java and javac, typically java_install_dir/bin and java_install_dir respectively.

如果您在 Windows 上运行且将 SDK 安装在 C:\jdk1.8.0_65 中,则需要将以下行放在 C:\autoexec.bat 文件中。

If you are running Windows and installed the SDK in C:\jdk1.8.0_65, you would put the following line in your C:\autoexec.bat file.

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

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

Alternatively, on Windows NT/2000/XP, you could also right-click on My Computer, select Properties, then Advanced, then Environment Variables. Then, you would update the PATH value and press the OK button.

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

On Unix (Solaris, Linux, etc.), if the SDK is installed in /usr/local/jdk1.8.0_65 and you use the C shell, you would put the following into your .cshrc file.

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

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

Alternatively, if you use an Integrated Development Environment (IDE) like Borland JBuilder, Eclipse, IntelliJ IDEA, or Sun ONE Studio, compile and run a simple program to confirm that the IDE knows where you installed Java.

Setting up Web Server − Tomcat

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

A number of Web Servers that support servlets are available in the market. Some web servers are freely downloadable and Tomcat is one of them.

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

Apache Tomcat is an open source software implementation of the Java Servlet and Java Server Pages technologies and can act as a standalone server for testing servlets and can be integrated with the Apache Web Server. Here are the steps to setup Tomcat on your machine −

  1. Download latest version of Tomcat from https://tomcat.apache.org/.

  2. Once you downloaded the installation, unpack the binary distribution into a convenient location. For example in C:\apache-tomcat-8.0.28 on windows, or /usr/local/apache-tomcat-8.0.289 on Linux/Unix and create CATALINA_HOME environment variable pointing to these locations.

可以通过在 Windows 计算机上执行以下命令启动 Tomcat:

Tomcat can be started by executing the following commands on windows machine −

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

可以通过在 Unix(Solaris、Linux 等)计算机上执行以下命令启动 Tomcat:

Tomcat can be started by executing the following commands on Unix (Solaris, Linux, etc.) machine −

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

启动后,可以通过访问 http://localhost:8080/ 获得 Tomcat 附带的默认 Web 应用程序。如果一切正常,则应显示以下结果:

After startup, the default web applications included with Tomcat will be available by visiting http://localhost:8080/. If everything is fine then it should display following result −

tomcathomepage

有关配置和运行 Tomcat 的更多信息,请参阅此处附带的文档以及 Tomcat 网站:[role="bare"] [role="bare"]http://tomcat.apache.org

Further information about configuring and running Tomcat can be found in the documentation included here, as well as on the Tomcat web site − [role="bare"]http://tomcat.apache.org

可以通过在 Windows 计算机上执行以下命令停止 Tomcat:

Tomcat can be stopped by executing the following commands on windows machine −

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

可以通过在 Unix(Solaris、Linux 等)计算机上执行以下命令停止 Tomcat:

Tomcat can be stopped by executing the following commands on Unix (Solaris, Linux, etc.) machine −

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

Setting Up the CLASSPATH

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

Since servlets are not part of the Java Platform, Standard Edition, you must identify the servlet classes to the compiler.

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

If you are running Windows, you need to put the following lines in your C:\autoexec.bat file.

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

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

Alternatively, on Windows NT/2000/XP, you could go to My Computer −> Properties −> Advanced −> Environment Variables. Then, you would update the CLASSPATH value and press the OK button.

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

On Unix (Solaris, Linux, etc.), if you are using the C shell, you would put the following lines into your .cshrc file.

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

NOTE − 假设您的开发目录是 C:\ServletDevel(Windows)或 /usr/ServletDevel(Unix),则您需要以类似于上面添加的方式将这些目录添加到 CLASSPATH 中。

NOTE − Assuming that your development directory is C:\ServletDevel (Windows) or /usr/ServletDevel (Unix) then you would need to add these directories as well in CLASSPATH in similar way as you have added above.

Servlets - Life Cycle

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

A servlet life cycle can be defined as the entire process from its creation till the destruction. The following are the paths followed by a servlet.

  1. The servlet is initialized by calling the init() method.

  2. The servlet calls service() method to process a client’s request.

  3. The servlet is terminated by calling the destroy() method.

  4. Finally, servlet is garbage collected by the garbage collector of the JVM.

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

Now let us discuss the life cycle methods in detail.

The init() Method

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

The init method is called only once. It is called only when the servlet is created, and not called for any user requests afterwards. So, it is used for one-time initializations, just as with the init method of applets.

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

The servlet is normally created when a user first invokes a URL corresponding to the servlet, but you can also specify that the servlet be loaded when the server is first started.

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

When a user invokes a servlet, a single instance of each servlet gets created, with each user request resulting in a new thread that is handed off to doGet or doPost as appropriate. The init() method simply creates or loads some data that will be used throughout the life of the servlet.

init 方法的定义如下:

The init method definition looks like this −

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

The service() Method

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

The service() method is the main method to perform the actual task. The servlet container (i.e. web server) calls the service() method to handle requests coming from the client( browsers) and to write the formatted response back to the client.

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

Each time the server receives a request for a servlet, the server spawns a new thread and calls service. The service() method checks the HTTP request type (GET, POST, PUT, DELETE, etc.) and calls doGet, doPost, doPut, doDelete, etc. methods as appropriate.

此方法的签名如下:

Here is the signature of this method −

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

service() 方法是由容器调用,而 service 方法会根据需要调用 doGet、doPost、doPut、doDelete 等方法。因此,你无需操作 service() 方法,但可以根据从客户端收到的请求类型覆盖 doGet() 或 doPost()。

The service () method is called by the container and service method invokes doGet, doPost, doPut, doDelete, etc. methods as appropriate. So you have nothing to do with service() method but you override either doGet() or doPost() depending on what type of request you receive from the client.

doGet() 和 doPost() 是各个 service 请求中使用最多的方法。以下是这两个方法的签名。

The doGet() and doPost() are most frequently used methods with in each service request. Here is the signature of these two methods.

The doGet() Method

GET 请求来自对 URL 的常规请求或未指定 METHOD 的 HTML 表单,应当由 doGet() 方法处理。

A GET request results from a normal request for a URL or from an HTML form that has no METHOD specified and it should be handled by doGet() method.

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

The doPost() Method

POST 请求来自明确列出 POST 为 METHOD 的 HTML 表单,应当由 doPost() 方法处理。

A POST request results from an HTML form that specifically lists POST as the METHOD and it should be handled by doPost() method.

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

The destroy() Method

destroy() 方法仅在 servlet 生命周期的末尾调用一次。此方法可以让你的 servlet 有机会关闭数据库连接、停止后台线程、将 cookie 列表或点击数写入磁盘,以及执行其他此类清理活动。

The destroy() method is called only once at the end of the life cycle of a servlet. This method gives your servlet a chance to close database connections, halt background threads, write cookie lists or hit counts to disk, and perform other such cleanup activities.

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

After the destroy() method is called, the servlet object is marked for garbage collection. The destroy method definition looks like this −

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

Architecture Diagram

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

The following figure depicts a typical servlet life-cycle scenario.

  1. First the HTTP requests coming to the server are delegated to the servlet container.

  2. The servlet container loads the servlet before invoking the service() method.

  3. Then the servlet container handles multiple requests by spawning multiple threads, each thread executing the service() method of a single instance of the servlet.

servlet lifecycle

Servlets - Examples

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

Servlets are Java classes which service HTTP requests and implement the javax.servlet.Servlet interface. Web application developers typically write servlets that extend javax.servlet.http.HttpServlet, an abstract class that implements the Servlet interface and is specially designed to handle HTTP requests.

Sample Code

以下为显示 Hello World 的 servlet 示例的示例源代码结构 -

Following is the sample source code structure of a servlet example to show 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.
   }
}

Compiling a Servlet

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

Let us create a file with name HelloWorld.java with the code shown above. Place this file at C:\ServletDevel (in Windows) or at /usr/ServletDevel (in Unix). This path location must be added to CLASSPATH before proceeding further.

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

Assuming your environment is setup properly, go in ServletDevel directory and compile HelloWorld.java as follows −

$ javac HelloWorld.java

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

If the servlet depends on any other libraries, you have to include those JAR files on your CLASSPATH as well. I have included only servlet-api.jar JAR file because I’m not using any other library in Hello World program.

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

This command line uses the built-in javac compiler that comes with the Sun Microsystems Java Software Development Kit (JDK). For this command to work properly, you have to include the location of the Java SDK that you are using in the PATH environment variable.

如果一切都正常,上述编译将在同一目录中生成 HelloWorld.class 文件。下一部分将说明如何将已编译的 servlet 部署到生产环境中。

If everything goes fine, above compilation would produce HelloWorld.class file in the same directory. Next section would explain how a compiled servlet would be deployed in production.

Servlet Deployment

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

By default, a servlet application is located at the path <Tomcat-installationdirectory>/webapps/ROOT and the class file would reside in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes.

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

If you have a fully qualified class name of com.myorg.MyServlet, then this servlet class must be located in WEB-INF/classes/com/myorg/MyServlet.class.

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

For now, let us copy HelloWorld.class into <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes and create following entries in web.xml file located in <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/

<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-app>…​</web-app> web.xml 文件内。此表格中可能已经存在各种条目,但不必担心。

Above entries to be created inside <web-app>…​</web-app> tags available in web.xml file. There could be various entries in this table already available, but never mind.

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

You are almost done, now let us start tomcat server using <Tomcat-installationdirectory>\bin\startup.bat (on Windows) or <Tomcat-installationdirectory>/bin/startup.sh (on Linux/Solaris etc.) and finally type http://localhost:8080/HelloWorld in the browser’s address box. If everything goes fine, you would get the following result

servlet example

Servlets - Form Data

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

You must have come across many situations when you need to pass some information from your browser to web server and ultimately to your backend program. The browser uses two methods to pass this information to web server. These methods are GET Method and POST Method.

GET Method

GET 方法将编码后的用户信息附加到页面请求中发送。页面和编码后的信息通过 ? (问号)符号分隔,如下所示 -

The GET method sends the encoded user information appended to the page request. The page and the encoded information are separated by the ? (question mark) symbol as follows −

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

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

The GET method is the default method to pass information from browser to web server and it produces a long string that appears in your browser’s Location:box. Never use the GET method if you have password or other sensitive information to pass to the server. The GET method has size limitation: only 1024 characters can be used in a request string.

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

This information is passed using QUERY_STRING header and will be accessible through QUERY_STRING environment variable and Servlet handles this type of requests using doGet() method.

POST Method

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

A generally more reliable method of passing information to a backend program is the POST method. This packages the information in exactly the same way as GET method, but instead of sending it as a text string after a ? (question mark) in the URL it sends it as a separate message. This message comes to the backend program in the form of the standard input which you can parse and use for your processing. Servlet handles this type of requests using doPost() method.

Reading Form Data using Servlet

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

Servlets handles form data parsing automatically using the following methods depending on the situation −

  1. getParameter() − You call request.getParameter() method to get the value of a form parameter.

  2. getParameterValues() − Call this method if the parameter appears more than once and returns multiple values, for example checkbox.

  3. getParameterNames() − Call this method if you want a complete list of all parameters in the current request.

GET Method Example using URL

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

Here is a simple URL which will pass two values to HelloForm program using GET method.

下面是 HelloForm.java servlet 程序来处理 web 浏览器给定的输入。我们准备使用 getParameter() 方法,该方法使得访问传递的信息变得非常容易 −

Given below is the HelloForm.java servlet program to handle input given by web browser. We are going to use getParameter() method which makes it very easy to access passed information −

// 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 −

Assuming your environment is set up properly, compile HelloForm.java as follows −

$ javac HelloForm.java

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

If everything goes fine, above compilation would produce HelloForm.class file. Next you would have to copy this class file in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes and create following entries in web.xml file located in <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/

<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>

现在在浏览器的“位置:”框中键入 [role="bare"] [role="bare"]http://localhost:8080/HelloForm?first_name=ZARA&last_name=ALI ,在浏览器中执行上述命令之前,请确保您已经启动了 tomcat 服务器。这将生成以下结果 −

Now type [role="bare"]http://localhost:8080/HelloForm?first_name=ZARA&last_name=ALI in your browser’s Location:box and make sure you already started tomcat server, before firing above command in the browser. This would generate following result −

Using GET Method to Read Form Data

First Name: ZARA
Last Name: ALI

GET Method Example Using Form

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

Here is a simple example which passes two values using HTML FORM and submit button. We are going to use same Servlet HelloForm to handle this input.

<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 目录中。当您访问 [role="bare"] [role="bare"]http://localhost:8080/Hello.htm 时,以下就是上述表单的实际输出。

Keep this HTML in a file Hello.htm and put it in <Tomcat-installationdirectory>/webapps/ROOT directory. When you would access [role="bare"]http://localhost:8080/Hello.htm, here is the actual output of the above form.

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

Try to enter First Name and Last Name and then click submit button to see the result on your local machine where tomcat is running. Based on the input provided, it will generate similar result as mentioned in the above example.

POST Method Example Using Form

让我们对上述 servlet 进行一点修改,以便它可以处理 GET 和 POST 方法。以下是 HelloForm.java servlet 程序来处理使用 GET 或 POST 方法由 web 浏览器给定的输入。

Let us do little modification in the above servlet, so that it can handle GET as well as POST methods. Below is HelloForm.java servlet program to handle input given by web browser using GET or POST methods.

// 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 对其进行测试,方法如下 −

Now compile and deploy the above Servlet and test it using Hello.htm with the POST method as follows −

<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 运行的本地计算机上的结果。

Here is the actual output of the above form, Try to enter First and Last Name and then click submit button to see the result on your local machine where tomcat is running.

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

Based on the input provided, it would generate similar result as mentioned in the above examples.

Passing Checkbox Data to Servlet Program

如果要求选择多个选项,则使用复选框。

Checkboxes are used when more than one option is required to be selected.

这是一个带两个复选框的表单的 HTML 代码示例,CheckBox.htm

Here is example HTML code, CheckBox.htm, for a form with two checkboxes

<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>

此代码的结果是以下表单

The result of this code is the following form

下面是 CheckBox.java servlet 程序来处理复选框按钮的 web 浏览器给定的输入。

Given below is the CheckBox.java servlet program to handle input given by web browser for checkbox button.

// 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);
   }
}

对于上述示例,它会显示以下结果 −

For the above example, it would display following result −

Reading Checkbox Data

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

Reading All Form Parameters

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

Following is the generic example which uses getParameterNames() method of HttpServletRequest to read all the available form parameters. This method returns an Enumeration that contains the parameter names in an unspecified order

获得枚举后,我们可以使用 hasMoreElements() 方法来确定何时停止,并使用 nextElement() 方法来获取每个参数名称,从而以标准方式向下遍历枚举。

Once we have an Enumeration, we can loop down the Enumeration in standard way by, using hasMoreElements() method to determine when to stop and using nextElement() method to get each parameter name.

// 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 −

Now, try the above servlet with the following form −

<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 将生成以下结果 −

Now calling servlet using the above form would generate the following result −

Reading All Form Parameters


Param Name
Param Value(s)


maths
on


chemistry
on

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

You can try the above servlet to read any other form’s data having other objects like text box, radio button or drop down box etc.

Servlets - Client HTTP Request

当浏览器请求一个网页时,它会向 Web 服务器发送很多无法直接读取的信息,因为这些信息作为 HTTP 请求标头的组成部分进行传输。您可以参阅 HTTP Protocol 以获得更多相关信息。

When a browser requests for a web page, it sends lot of information to the web server which cannot be read directly because this information travel as a part of header of HTTP request. You can check HTTP Protocol for more information on this.

以下是来自浏览器端的重要标头信息,您将在 Web 编程中非常频繁地使用它们 −

Following is the important header information which comes from browser side and you would use very frequently in web programming −

Sr.No.

Header & Description

1

Accept This header specifies the MIME types that the browser or other clients can handle. Values of image/png or image/jpeg are the two most common possibilities.

2

Accept-Charset This header specifies the character sets the browser can use to display the information. For example ISO-8859-1.

3

Accept-Encoding This header specifies the types of encodings that the browser knows how to handle. Values of gzip or compress are the two most common possibilities.

4

Accept-Language This header specifies the client’s preferred languages in case the servlet can produce results in more than one language. For example en, en-us, ru, etc

5

Authorization This header is used by clients to identify themselves when accessing password-protected Web pages.

6

Connection This header indicates whether the client can handle persistent HTTP connections. Persistent connections permit the client or other browser to retrieve multiple files with a single request. A value of Keep-Alive means that persistent connections should be used.

7

Content-Length This header is applicable only to POST requests and gives the size of the POST data in bytes.

8

Cookie This header returns cookies to servers that previously sent them to the browser.

9

Host This header specifies the host and port as given in the original URL.

10

If-Modified-Since This header indicates that the client wants the page only if it has been changed after the specified date. The server sends a code, 304 which means Not Modified header if no newer result is available.

11

If-Unmodified-Since This header is the reverse of If-Modified-Since; it specifies that the operation should succeed only if the document is older than the specified date.

12

Referer This header indicates the URL of the referring Web page. For example, if you are at Web page 1 and click on a link to Web page 2, the URL of Web page 1 is included in the Referrer header when the browser requests Web page 2.

13

User-Agent This header identifies the browser or other client making the request and can be used to return different content to different types of browsers.

Methods to read HTTP Header

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

There are following methods which can be used to read HTTP header in your servlet program. These methods are available with HttpServletRequest object

Sr.No.

Method & Description

1

Cookie[] getCookies() Returns an array containing all of the Cookie objects the client sent with this request.

2

Enumeration getAttributeNames() Returns an Enumeration containing the names of the attributes available to this request.

3

Enumeration getHeaderNames() Returns an enumeration of all the header names this request contains.

4

Enumeration getParameterNames() Returns an Enumeration of String objects containing the names of the parameters contained in this request

5

HttpSession getSession() Returns the current session associated with this request, or if the request does not have a session, creates one.

6

HttpSession getSession(boolean create) Returns the current HttpSession associated with this request or, if if there is no current session and value of create is true, returns a new session.

7

Locale getLocale() Returns the preferred Locale that the client will accept content in, based on the Accept-Language header.

8

*Object getAttribute(String name) * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.

9

ServletInputStream getInputStream() Retrieves the body of the request as binary data using a ServletInputStream.

10

String getAuthType() Returns the name of the authentication scheme used to protect the servlet, for example, "BASIC" or "SSL," or null if the JSP was not protected.

11

String getCharacterEncoding() Returns the name of the character encoding used in the body of this request.

12

String getContentType() Returns the MIME type of the body of the request, or null if the type is not known.

13

String getContextPath() Returns the portion of the request URI that indicates the context of the request.

14

*String getHeader(String name) * Returns the value of the specified request header as a String.

15

*String getMethod() * Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.

16

String getParameter(String name) Returns the value of a request parameter as a String, or null if the parameter does not exist.

17

String getPathInfo() Returns any extra path information associated with the URL the client sent when it made this request

18

*String getProtocol() * Returns the name and version of the protocol the request.

19

*String getQueryString() * Returns the query string that is contained in the request URL after the path.

20

String getRemoteAddr() Returns the Internet Protocol (IP) address of the client that sent the request.

21

*String getRemoteHost() * Returns the fully qualified name of the client that sent the request.

22

*String getRemoteUser() * Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated.

23

*String getRequestURI() * Returns the part of this request’s URL from the protocol name up to the query string in the first line of the HTTP request.

24

String getRequestedSessionId() Returns the session ID specified by the client.

25

*String getServletPath() * Returns the part of this request’s URL that calls the JSP.

26

*String[] getParameterValues(String name) * Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does not exist.

27

*boolean isSecure() * Returns a Boolean indicating whether this request was made using a secure channel, such as HTTPS.

28

*int getContentLength() * Returns the length, in bytes, of the request body and made available by the input stream, or -1 if the length is not known.

29

int getIntHeader(String name) Returns the value of the specified request header as an int.

30

int getServerPort() Returns the port number on which this request was received.

HTTP Header Request Example

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

Following is the example which uses getHeaderNames() method of HttpServletRequest to read the HTTP header information. This method returns an Enumeration that contains the header information associated with the current HTTP request.

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

Once we have an Enumeration, we can loop down the Enumeration in the standard manner, using hasMoreElements() method to determine when to stop and using nextElement() method to get each parameter name

// 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 将生成以下结果:

Now calling the above servlet would generate the following result −

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

Servlets - Server HTTP Response

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

As discussed in the previous chapter, when a Web server responds to an HTTP request, the response typically consists of a status line, some response headers, a blank line, and the document. A typical response looks like this −

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)组成。

The status line consists of the HTTP version (HTTP/1.1 in the example), a status code (200 in the example), and a very short message corresponding to the status code (OK in the example).

以下是对最常用的 HTTP 1.1 响应头部的总结,这些响应头部从 Web 服务器端返回到浏览器,并且在 Web 编程中会非常频繁地使用:

Following is a summary of the most useful HTTP 1.1 response headers which go back to the browser from web server side and you would use them very frequently in web programming −

Sr.No.

Header & Description

1

Allow This header specifies the request methods (GET, POST, etc.) that the server supports.

2

Cache-Control This header specifies the circumstances in which the response document can safely be cached. It can have values public, private or no-cache etc. Public means document is cacheable, Private means document is for a single user and can only be stored in private (non-shared) caches and nocache means document should never be cached.

3

Connection This header instructs the browser whether to use persistent in HTTP connections or not. A value of close instructs the browser not to use persistent HTTP connections and keepalive means using persistent connections.

4

Content-Disposition This header lets you request that the browser ask the user to save the response to disk in a file of the given name.

5

Content-Encoding This header specifies the way in which the page was encoded during transmission.

6

Content-Language This header signifies the language in which the document is written. For example en, en-us, ru, etc

7

Content-Length This header indicates the number of bytes in the response. This information is needed only if the browser is using a persistent (keep-alive) HTTP connection.

8

Content-Type This header gives the MIME (Multipurpose Internet Mail Extension) type of the response document.

9

Expires This header specifies the time at which the content should be considered out-of-date and thus no longer be cached.

10

Last-Modified This header indicates when the document was last changed. The client can then cache the document and supply a date by an If-Modified-Since request header in later requests.

11

Location This header should be included with all responses that have a status code in the 300s. This notifies the browser of the document address. The browser automatically reconnects to this location and retrieves the new document.

12

Refresh This header specifies how soon the browser should ask for an updated page. You can specify time in number of seconds after which a page would be refreshed.

13

Retry-After This header can be used in conjunction with a 503 (Service Unavailable) response to tell the client how soon it can repeat its request.

14

Set-Cookie This header specifies a cookie associated with the page.

Methods to Set HTTP Response Header

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

There are following methods which can be used to set HTTP response header in your servlet program. These methods are available with HttpServletResponse object.

Sr.No.

Method & Description

1

String encodeRedirectURL(String url) Encodes the specified URL for use in the sendRedirect method or, if encoding is not needed, returns the URL unchanged.

2

String encodeURL(String url) Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL unchanged.

3

boolean containsHeader(String name) Returns a Boolean indicating whether the named response header has already been set.

4

*boolean isCommitted() * Returns a Boolean indicating if the response has been committed.

5

void addCookie(Cookie cookie) Adds the specified cookie to the response.

6

void addDateHeader(String name, long date) Adds a response header with the given name and date-value.

7

void addHeader(String name, String value) Adds a response header with the given name and value.

8

void addIntHeader(String name, int value) Adds a response header with the given name and integer value.

9

*void flushBuffer() * Forces any content in the buffer to be written to the client.

10

void reset() Clears any data that exists in the buffer as well as the status code and headers.

11

void resetBuffer() Clears the content of the underlying buffer in the response without clearing headers or status code.

12

void sendError(int sc) Sends an error response to the client using the specified status code and clearing the buffer.

13

void sendError(int sc, String msg) Sends an error response to the client using the specified status.

14

void sendRedirect(String location) Sends a temporary redirect response to the client using the specified redirect location URL.

15

*void setBufferSize(int size) * Sets the preferred buffer size for the body of the response.

16

void setCharacterEncoding(String charset) Sets the character encoding (MIME charset) of the response being sent to the client, for example, to UTF-8.

17

*void setContentLength(int len) * Sets the length of the content body in the response In HTTP servlets, this method sets the HTTP Content-Length header.

18

*void setContentType(String type) * Sets the content type of the response being sent to the client, if the response has not been committed yet.

19

*void setDateHeader(String name, long date) * Sets a response header with the given name and date-value.

20

*void setHeader(String name, String value) * Sets a response header with the given name and value.

21

*void setIntHeader(String name, int value) * Sets a response header with the given name and integer value

22

void setLocale(Locale loc) Sets the locale of the response, if the response has not been committed yet.

23

*void setStatus(int sc) * Sets the status code for this response

HTTP Header Response Example

您已经在前面的示例中看到 setContentType() 方法正在工作,并且后面的示例也会使用同样的方法,此外,我们会使用 setIntHeader() 方法来设置 Refresh 头。

You already have seen setContentType() method working in previous examples and following example would also use same method, additionally we would use setIntHeader() method to set Refresh header.

// 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 并等待查看结果 -

Now calling the above servlet would display current system time after every 5 seconds as follows. Just run the servlet and wait to see the result −

Auto Refresh Header Setting
Current Time is: 9:44:50 PM

Servlets - Http Status Codes

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

The format of the HTTP request and HTTP response messages are similar and will have following structure −

  1. An initial status line + CRLF ( Carriage Return + Line Feed i.e. New Line )

  2. Zero or more header lines + CRLF

  3. A blank line, i.e., a CRLF

  4. An optional message body like file, query data or query output.

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

For example, a server response header looks as follows −

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)组成。

The status line consists of the HTTP version (HTTP/1.1 in the example), a status code (200 in the example), and a very short message corresponding to the status code (OK in the example).

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

Following is a list of HTTP status codes and associated messages that might be returned from the Web Server −

Code

Message

Description

100

Continue

Only a part of the request has been received by the server, but as long as it has not been rejected, the client should continue with the request

101

Switching Protocols

The server switches protocol.

200

OK

The request is OK

201

Created

The request is complete, and a new resource is created

202

Accepted

The request is accepted for processing, but the processing is not complete.

203

Non-authoritative Information

204

No Content

205

Reset Content

206

Partial Content

300

Multiple Choices

A link list. The user can select a link and go to that location. Maximum five addresses

301

Moved Permanently

The requested page has moved to a new url

302

Found

The requested page has moved temporarily to a new url

303

See Other

The requested page can be found under a different url

304

Not Modified

305

Use Proxy

306

Unused

This code was used in a previous version. It is no longer used, but the code is reserved

307

Temporary Redirect

The requested page has moved temporarily to a new url.

400

Bad Request

The server did not understand the request

401

Unauthorized

The requested page needs a username and a password

402

Payment Required

You cannot use this code yet

403

Forbidden

Access is forbidden to the requested page

404

Not Found

The server cannot find the requested page.

405

Method Not Allowed

The method specified in the request is not allowed.

406

Not Acceptable

The server can only generate a response that is not accepted by the client.

407

Proxy Authentication Required

You must authenticate with a proxy server before this request can be served.

408

Request Timeout

The request took longer than the server was prepared to wait.

409

Conflict

The request could not be completed because of a conflict.

410

Gone

The requested page is no longer available.

411

Length Required

The "Content-Length" is not defined. The server will not accept the request without it.

412

Precondition Failed

The precondition given in the request evaluated to false by the server.

413

Request Entity Too Large

The server will not accept the request, because the request entity is too large.

414

Request-url Too Long

The server will not accept the request, because the url is too long. Occurs when you convert a "post" request to a "get" request with a long query information.

415

Unsupported Media Type

The server will not accept the request, because the media type is not supported.

417

Expectation Failed

500

Internal Server Error

The request was not completed. The server met an unexpected condition.

501

Not Implemented

The request was not completed. The server did not support the functionality required.

502

Bad Gateway

The request was not completed. The server received an invalid response from the upstream server.

503

Service Unavailable

The request was not completed. The server is temporarily overloading or down.

504

Gateway Timeout

The gateway has timed out.

505

HTTP Version Not Supported

The server does not support the "http protocol" version.

Methods to Set HTTP Status Code

以下方法可用于在 servlet 程序中设置 HTTP 状态代码。这些方法在 HttpServletResponse 对象中可用。

The following methods can be used to set HTTP Status Code in your servlet program. These methods are available with HttpServletResponse object.

Sr.No.

Method & Description

1

public void setStatus ( int statusCode ) This method sets an arbitrary status code. The setStatus method takes an int (the status code) as an argument. If your response includes a special status code and a document, be sure to call setStatus before actually returning any of the content with the PrintWriter.

2

public void sendRedirect(String url) This method generates a 302 response along with a Location header giving the URL of the new document

3

public void sendError(int code, String message) This method sends a status code (usually 404) along with a short message that is automatically formatted inside an HTML document and sent to the client.

HTTP Status Code Example

以下是向客户端浏览器发送 407 错误代码的示例,浏览器将向您显示“需要授权!!!”消息。

Following is the example which would send a 407 error code to the client browser and browser would show you "Need authentication!!!" message.

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

// Extend HttpServlet class
public class showError extends HttpServlet {

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

      // Set error code and reason.
      response.sendError(407, "Need authentication!!!" );
   }

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

      doGet(request, response);
   }
}

现在,调用上述 servlet 将显示以下结果 −

Now calling the above servlet would display the following result −

HTTP Status 407 - Need authentication!!!
type Status report
messageNeed authentication!!!
descriptionThe client must first authenticate itself with the proxy (Need authentication!!!).
Apache Tomcat/5.5.29

Servlets - Writing Filters

Servlet 过滤器是可以在 Servlet 编程中用于以下目的的 Java 类 −

Servlet Filters are Java classes that can be used in Servlet Programming for the following purposes −

  1. To intercept requests from a client before they access a resource at back end.

  2. To manipulate responses from server before they are sent back to the client.

规范建议了多种类型的过滤器 −

There are various types of filters suggested by the specifications −

  1. Authentication Filters.

  2. Data compression Filters.

  3. Encryption Filters.

  4. Filters that trigger resource access events.

  5. Image Conversion Filters.

  6. Logging and Auditing Filters.

  7. MIME-TYPE Chain Filters.

  8. Tokenizing Filters .

  9. XSL/T Filters That Transform XML Content.

过滤器部署在部署描述符文件 web.xml 中,然后映射到应用程序部署描述符中的 servlet 名称或 URL 模式。

Filters are deployed in the deployment descriptor file web.xml and then map to either servlet names or URL patterns in your application’s deployment descriptor.

当 Web 容器启动 Web 应用程序时,它将创建在部署描述符中声明的每个过滤器的实例。这些过滤器将按照在部署描述符中声明的顺序执行。

When the web container starts up your web application, it creates an instance of each filter that you have declared in the deployment descriptor. The filters execute in the order that they are declared in the deployment descriptor.

Servlet Filter Methods

过滤器只是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了如下三个方法 −

A filter is simply a Java class that implements the javax.servlet.Filter interface. The javax.servlet.Filter interface defines three methods −

Sr.No.

Method & Description

1

public void doFilter (ServletRequest, ServletResponse, FilterChain) This method is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

2

public void init(FilterConfig filterConfig) This method is called by the web container to indicate to a filter that it is being placed into service.

3

public void destroy() This method is called by the web container to indicate to a filter that it is being taken out of service.

Servlet Filter − Example

下面是 Servlet 过滤器示例,它将打印客户端的 IP 地址和当前日期时间。此示例将让您了解 Servlet 过滤器基础知识,但您可使用相同概念编写更复杂过滤器应用程序 −

Following is the Servlet Filter Example that would print the clients IP address and current date time. This example would give you basic understanding of Servlet Filter, but you can write more sophisticated filter applications using the same concept −

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

// Implements Filter class
public class LogFilter implements Filter  {
   public void  init(FilterConfig config) throws ServletException {

      // Get init parameter
      String testParam = config.getInitParameter("test-param");

      //Print the init parameter
      System.out.println("Test Param: " + testParam);
   }

   public void  doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws java.io.IOException, ServletException {

      // Get the IP address of client machine.
      String ipAddress = request.getRemoteAddr();

      // Log the IP address and current timestamp.
      System.out.println("IP "+ ipAddress + ", Time " + new Date().toString());

      // Pass request back down the filter chain
      chain.doFilter(request,response);
   }

   public void destroy( ) {
      /* Called before the Filter instance is removed from service by the web container*/
   }
}

按照通常方式编译 LogFilter.java ,并将类文件放在 <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes

Compile LogFilter.java in usual way and put your class file in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes

Servlet Filter Mapping in Web.xml

过滤器经过定义并映射到 URL 或 Servlet,方式与将 Servlet 定义并映射到 URL 模式大致相同。在部署描述文件 web.xml 中创建过滤器标记以下条目

Filters are defined and then mapped to a URL or Servlet, in much the same way as Servlet is defined and then mapped to a URL pattern. Create the following entry for filter tag in the deployment descriptor file web.xml

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

上述过滤器适用于所有 servlet,因为我们在配置中指定 / *。如果您只想对少数 servlet 应用过滤器,则可以指定特定 servlet 路径。

The above filter would apply to all the servlets because we specified /* in our configuration. You can specicy a particular servlet path if you want to apply filter on few servlets only.

现在,尝试以惯常方式调用任何 servlet,您会在 Web 服务器日志中看到生成的日志。您可以使用 Log4J 记录器将上述日志记录到单独文件中。

Now try to call any servlet in usual way and you would see generated log in your web server log. You can use Log4J logger to log above log in a separate file.

Using Multiple Filters

您的 Web 应用程序可能针对特定目的定义多个不同的过滤器。假设您定义了两个过滤器 AuthenFilter 和 LogFilter。除了需要创建不同的映射外(如下所述),其余过程将保持上述说明 −

Your web application may define several different filters with a specific purpose. Consider, you define two filters AuthenFilter and LogFilter. Rest of the process would remain as explained above except you need to create a different mapping as mentioned below −

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter>
   <filter-name>AuthenFilter</filter-name>
   <filter-class>AuthenFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Filters Application Order

web.xml 中 filter-mapping 元素的顺序决定 Web 容器将过滤器应用于 servlet 的顺序。要逆转过滤器的顺序,您只需要逆转 web.xml 文件中的 filter-mapping 元素。

The order of filter-mapping elements in web.xml determines the order in which the web container applies the filter to the servlet. To reverse the order of the filter, you just need to reverse the filter-mapping elements in the web.xml file.

例如,上述示例将首先应用 LogFilter,然后将其应用任何 servlet,但以下示例将逆转顺序 −

For example, above example would apply LogFilter first and then it would apply AuthenFilter to any servlet but the following example would reverse the order −

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Servlets - Exception Handling

当 servlet 引发异常时,Web 容器会搜索 web.xml 中使用 exception-type 元素匹配引发异常类型的配置。

When a servlet throws an exception, the web container searches the configurations in web.xml that use the exception-type element for a match with the thrown exception type.

您需要在 web.xml 中使用 error-page 元素,以指定根据特定 exceptions 或 HTTP status codes 来调用 servlet。

You would have to use the error-page element in web.xml to specify the invocation of servlets in response to certain exceptions or HTTP status codes.

web.xml Configuration

假设您有一个 ErrorHandler servlet,它将在出现任何已定义异常或错误时被调用。下面是在 web.xml 中创建的条目。

Consider, you have an ErrorHandler servlet which would be called whenever there is any defined exception or error. Following would be the entry created in web.xml.

<!-- servlet definition -->
<servlet>
   <servlet-name>ErrorHandler</servlet-name>
   <servlet-class>ErrorHandler</servlet-class>
</servlet>

<!-- servlet mappings -->
<servlet-mapping>
   <servlet-name>ErrorHandler</servlet-name>
   <url-pattern>/ErrorHandler</url-pattern>
</servlet-mapping>

<!-- error-code related error pages -->
<error-page>
   <error-code>404</error-code>
   <location>/ErrorHandler</location>
</error-page>

<error-page>
   <error-code>403</error-code>
   <location>/ErrorHandler</location>
</error-page>

<!-- exception-type related error pages -->
<error-page>
   <exception-type>
      javax.servlet.ServletException
   </exception-type >
   <location>/ErrorHandler</location>
</error-page>

<error-page>
   <exception-type>java.io.IOException</exception-type >
   <location>/ErrorHandler</location>
</error-page>

如果您想针对所有异常使用通用错误处理程序,则应该定义以下 error-page,而不是针对每个异常定义单独的 error-page 元素 −

If you want to have a generic Error Handler for all the exceptions then you should define following error-page instead of defining separate error-page elements for every exception −

<error-page>
   <exception-type>java.lang.Throwable</exception-type >
   <location>/ErrorHandler</location>
</error-page>

以下是在 Exception Handling 的 web.xml 中要注意的要点 −

Following are the points to be noted about above web.xml for Exception Handling −

  1. The servlet ErrorHandler is defined in usual way as any other servlet and configured in web.xml.

  2. If there is any error with status code either 404 (Not Found) or 403 (Forbidden ), then ErrorHandler servlet would be called.

  3. If the web application throws either ServletException or IOException, then the web container invokes the /ErrorHandler servlet.

  4. You can define different Error Handlers to handle different type of errors or exceptions. Above example is very much generic and hope it serve the purpose to explain you the basic concept.

Request Attributes − Errors/Exceptions

以下是错误处理 servlet 可访问的请求属性列表,用于分析错误/异常的本质。

Following is the list of request attributes that an error-handling servlet can access to analyze the nature of error/exception.

Sr.No.

Attribute & Description

1

*javax.servlet.error.status_code * This attribute give status code which can be stored and analyzed after storing in a java.lang.Integer data type.

2

*javax.servlet.error.exception_type * This attribute gives information about exception type which can be stored and analysed after storing in a java.lang.Class data type.

3

*javax.servlet.error.message * This attribute gives information exact error message which can be stored and analyzed after storing in a java.lang.String data type.

4

*javax.servlet.error.request_uri * This attribute gives information about URL calling the servlet and it can be stored and analysed after storing in a java.lang.String data type.

5

*javax.servlet.error.exception * This attribute gives information about the exception raised, which can be stored and analysed.

6

*javax.servlet.error.servlet_name * This attribute gives servlet name which can be stored and analyzed after storing in a java.lang.String data type.

Error Handler Servlet Example

此示例将使您基本了解 Servlet 中的异常处理,但是您可以使用相同概念编写更复杂的筛选器应用程序−

This example would give you basic understanding of Exception Handling in Servlet, but you can write more sophisticated filter applications using the same concept −

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

// Extend HttpServlet class
public class ErrorHandler extends HttpServlet {

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

      // Analyze the servlet exception
      Throwable throwable = (Throwable)
      request.getAttribute("javax.servlet.error.exception");
      Integer statusCode = (Integer)
      request.getAttribute("javax.servlet.error.status_code");
      String servletName = (String)
      request.getAttribute("javax.servlet.error.servlet_name");

      if (servletName == null) {
         servletName = "Unknown";
      }
      String requestUri = (String)
      request.getAttribute("javax.servlet.error.request_uri");

      if (requestUri == null) {
         requestUri = "Unknown";
      }

      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Error/Exception Information";
      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");

      if (throwable == null && statusCode == null) {
         out.println("<h2>Error information is missing</h2>");
         out.println("Please return to the <a href=\"" +
            response.encodeURL("http://localhost:8080/") +
            "\">Home Page</a>.");
      } else if (statusCode != null) {
         out.println("The status code : " + statusCode);
      } else {
         out.println("<h2>Error information</h2>");
         out.println("Servlet Name : " + servletName + "</br></br>");
         out.println("Exception Type : " + throwable.getClass( ).getName( ) + "</br></br>");
         out.println("The request URI: " + requestUri + "<br><br>");
         out.println("The exception message: " + throwable.getMessage( ));
      }
      out.println("</body>");
      out.println("</html>");
   }

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

      doGet(request, response);
   }
}

使用通常方法编译 ErrorHandler.java ,然后将您的类文件放入/webapps/ROOT/WEB-INF/classes 中。

Compile ErrorHandler.java in usual way and put your class file in /webapps/ROOT/WEB-INF/classes.

让我们在 web.xml 中添加以下配置来处理异常 −

Let us add the following configuration in web.xml to handle exceptions −

<servlet>
   <servlet-name>ErrorHandler</servlet-name>
   <servlet-class>ErrorHandler</servlet-class>
</servlet>

<!-- servlet mappings -->
<servlet-mapping>
   <servlet-name>ErrorHandler</servlet-name>
   <url-pattern>/ErrorHandler</url-pattern>
</servlet-mapping>

<error-page>
   <error-code>404</error-code>
   <location>/ErrorHandler</location>
</error-page>

<error-page>
   <exception-type>java.lang.Throwable</exception-type >
   <location>/ErrorHandler</location>
</error-page>

现在尝试使用引发任何异常或键入错误 URL 的 servlet,这将触发 Web 容器调用 ErrorHandler servlet 并显示适当的编程信息。例如,如果您键入一个错误的 URL,则会显示以下结果 −

Now try to use a servlet which raise any exception or type a wrong URL, this would trigger Web Container to call ErrorHandler servlet and display an appropriate message as programmed. For example, if you type a wrong URL then it would display the following result −

The status code : 404

上述代码可能无法与某些 Web 浏览器配合使用。因此,请尝试使用 Mozilla 和 Safari,它应该可以正常工作。

The above code may not work with some web browsers. So try with Mozilla and Safari and it should work.

Servlets - Cookies Handling

Cookie 是存储在客户端计算机上的文本文件,用于跟踪各种信息。Java Servlet 透明地支持 HTTP Cookie。

Cookies are text files stored on the client computer and they are kept for various information tracking purpose. Java Servlets transparently supports HTTP cookies.

识别返回用户涉及三个步骤 −

There are three steps involved in identifying returning users −

  1. Server script sends a set of cookies to the browser. For example name, age, or identification number etc.

  2. Browser stores this information on local machine for future use.

  3. When next time browser sends any request to web server then it sends those cookies information to the server and server uses that information to identify the user.

本章将教您如何设置或重置 Cookie、如何访问它们以及如何删除它们。

This chapter will teach you how to set or reset cookies, how to access them and how to delete them.

Cookie 通常设置在 HTTP 标头中(尽管 JavaScript 也可以在浏览器上直接设置 Cookie)。设置 Cookie 的 servlet 可能会发送类似以下内容的标头 −

Cookies are usually set in an HTTP header (although JavaScript can also set a cookie directly on a browser). A servlet that sets a cookie might send headers that look something like this −

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name = xyz; expires = Friday, 04-Feb-07 22:03:38 GMT;
   path = /; domain = tutorialspoint.com
Connection: close
Content-Type: text/html

如您所见,Set-Cookie 标头包含一个名称值对、一个 GMT 日期、一个路径和一个域名。名称和值将经过 URL 编码。expires 字段是指示浏览器在给定时间和日期后“忘记”Cookie 的指令。

As you can see, the Set-Cookie header contains a name value pair, a GMT date, a path and a domain. The name and value will be URL encoded. The expires field is an instruction to the browser to "forget" the cookie after the given time and date.

如果浏览器配置为存储 Cookie,它将保留此信息,直至过期日期。如果用户在任何匹配该 Cookie 的路径和域名的页面上指向浏览器,它将向服务器重新发送该 Cookie。浏览器的标头可能看起来像 −

If the browser is configured to store cookies, it will then keep this information until the expiry date. If the user points the browser at any page that matches the path and domain of the cookie, it will resend the cookie to the server. The browser’s headers might look something like this −

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name = xyz

然后 Servlet 可以通过请求方法 request.getCookies() 访问该 Cookie,这会返回 Cookie 对象的数组。

A servlet will then have access to the cookie through the request method request.getCookies() which returns an array of Cookie objects.

Servlet Cookies Methods

以下是可以在 Servlet 中操作 Cookie 时使用的有用方法列表。

Following is the list of useful methods which you can use while manipulating cookies in servlet.

Sr.No.

Method & Description

1

*public void setDomain(String pattern) * This method sets the domain to which cookie applies, for example tutorialspoint.com.

2

*public String getDomain() * This method gets the domain to which cookie applies, for example tutorialspoint.com.

3

public void setMaxAge(int expiry) This method sets how much time (in seconds) should elapse before the cookie expires. If you don’t set this, the cookie will last only for the current session.

4

public int getMaxAge() This method returns the maximum age of the cookie, specified in seconds, By default, -1 indicating the cookie will persist until browser shutdown.

5

public String getName() This method returns the name of the cookie. The name cannot be changed after creation.

6

*public void setValue(String newValue) * This method sets the value associated with the cookie

7

*public String getValue() * This method gets the value associated with the cookie.

8

*public void setPath(String uri) * This method sets the path to which this cookie applies. If you don’t specify a path, the cookie is returned for all URLs in the same directory as the current page as well as all subdirectories.

9

public String getPath() This method gets the path to which this cookie applies.

10

public void setSecure(boolean flag) This method sets the boolean value indicating whether the cookie should only be sent over encrypted (i.e. SSL) connections.

11

*public void setComment(String purpose) * This method specifies a comment that describes a cookie’s purpose. The comment is useful if the browser presents the cookie to the user.

12

public String getComment() This method returns the comment describing the purpose of this cookie, or null if the cookie has no comment.

Setting Cookies with Servlet

通过 Servlet 设置 Cookie 涉及三个步骤 −

Setting cookies with servlet involves three steps −

(1) Creating a Cookie object − 使用 Cookie 名称和 Cookie 值调用 Cookie 构造函数,两者均为字符串。

(1) Creating a Cookie object − You call the Cookie constructor with a cookie name and a cookie value, both of which are strings.

Cookie cookie = new Cookie("key","value");

记住,名称或值都不应包含空格或以下任何字符 −

Keep in mind, neither the name nor the value should contain white space or any of the following characters −

[ ] ( ) = , " / ? @ : ;

(2) Setting the maximum age − 使用 setMaxAge 指定 Cookie 应有效多长时间(以秒为单位)。以下将设置一个 24 小时的 Cookie。

(2) Setting the maximum age − You use setMaxAge to specify how long (in seconds) the cookie should be valid. Following would set up a cookie for 24 hours.

cookie.setMaxAge(60 * 60 * 24);

(3) Sending the Cookie into the HTTP response headers − 您使用 response.addCookie 在 HTTP 响应头中添加 cookie,如下所示:

(3) Sending the Cookie into the HTTP response headers − You use response.addCookie to add cookies in the HTTP response header as follows −

response.addCookie(cookie);

Example

我们修改我们的 Form Example 以设置 first 和 last name 的 cookie。

Let us modify our Form Example to set the cookies for first and last name.

// 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 {

      // Create cookies for first and last names.
      Cookie firstName = new Cookie("first_name", request.getParameter("first_name"));
      Cookie lastName = new Cookie("last_name", request.getParameter("last_name"));

      // Set expiry date after 24 Hrs for both the cookies.
      firstName.setMaxAge(60*60*24);
      lastName.setMaxAge(60*60*24);

      // Add both the cookies in the response header.
      response.addCookie( firstName );
      response.addCookie( lastName );

      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Setting Cookies 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" +
               "<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>"
      );
   }
}

编译上面的 servlet HelloForm 并创建 web.xml 文件中的相应条目,最后尝试以下 HTML 页面以调用 servlet。

Compile the above servlet HelloForm and create appropriate entry in web.xml file and finally try following HTML page to call servlet.

<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 安装目录>/webapps/ROOT 目录中。在您访问时 [role="bare"] [role="bare"]http://localhost:8080/Hello.htm ,以下是上面表单的实际输出。

Keep above HTML content in a file Hello.htm and put it in <Tomcat-installationdirectory>/webapps/ROOT directory. When you would access [role="bare"]http://localhost:8080/Hello.htm, here is the actual output of the above form.

尝试输入 First Name 和 Last Name,然后点击提交按钮。将显示您的屏幕上的 first name 和 last name,同时将设置两个 cookies(firstName 和 lastName),下次按下提交按钮时将传回服务器。

Try to enter First Name and Last Name and then click submit button. This would display first name and last name on your screen and same time it would set two cookies firstName and lastName which would be passed back to the server when next time you would press Submit button.

下一部分将向您解释如何在 Web 应用程序中访问这些 cookie。

Next section would explain you how you would access these cookies back in your web application.

Reading Cookies with Servlet

要读取 cookie,需要通过调用 HttpServletRequest 的 getCookies() 方法,创建一个 javax.servlet.http.Cookie 对象的数组。然后循环数组,并使用 getName() 和 getValue() 方法来访问每个 cookie 和关联的值。

To read cookies, you need to create an array of javax.servlet.http.Cookie objects by calling the getCookies() method of HttpServletRequest. Then cycle through the array, and use getName() and getValue() methods to access each cookie and associated value.

Example

我们读取在先前示例中设置的 cookie −

Let us read cookies which we have set in previous example −

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

// Extend HttpServlet class
public class ReadCookies extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      Cookie cookie = null;
      Cookie[] cookies = null;

      // Get an array of Cookies associated with this domain
      cookies = request.getCookies();

      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Reading Cookies 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" );

      if( cookies != null ) {
         out.println("<h2> Found Cookies Name and Value</h2>");

         for (int i = 0; i < cookies.length; i++) {
            cookie = cookies[i];
            out.print("Name : " + cookie.getName( ) + ",  ");
            out.print("Value: " + cookie.getValue( ) + " <br/>");
         }
      } else {
         out.println("<h2>No cookies founds</h2>");
      }
      out.println("</body>");
      out.println("</html>");
   }
}

编译上面 servlet ReadCookies 并创建 web.xml 文件中的相应条目。如果您将 first_name cookie 设置为“John”,将 last_name cookie 设置为“Player”,则运行 [role="bare"] [role="bare"]http://localhost:8080/ReadCookies 将显示以下结果 −

Compile above servlet ReadCookies and create appropriate entry in web.xml file. If you would have set first_name cookie as "John" and last_name cookie as "Player" then running [role="bare"]http://localhost:8080/ReadCookies would display the following result −

 Found Cookies Name and Value
Name : first_name, Value: John
Name : last_name,  Value: Player

Delete Cookies with Servlet

删除 cookie 非常简单。如果您希望删除 cookie,只需按照以下三个步骤操作:

To delete cookies is very simple. If you want to delete a cookie then you simply need to follow up following three steps −

  1. Read an already existing cookie and store it in Cookie object.

  2. Set cookie age as zero using setMaxAge() method to delete an existing cookie

  3. Add this cookie back into response header.

Example

以下示例将删除名为“first_name”的现有 cookie,当您下次运行 ReadCookies servlet 时,它将为 first_name 返回空值。

The following example would delete and existing cookie named "first_name" and when you would run ReadCookies servlet next time it would return null value for first_name.

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

// Extend HttpServlet class
public class DeleteCookies extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      Cookie cookie = null;
      Cookie[] cookies = null;

      // Get an array of Cookies associated with this domain
      cookies = request.getCookies();

      // Set response content type
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      String title = "Delete Cookies 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" );

      if( cookies != null ) {
         out.println("<h2> Cookies Name and Value</h2>");

         for (int i = 0; i < cookies.length; i++) {
            cookie = cookies[i];

            if((cookie.getName( )).compareTo("first_name") == 0 ) {
               cookie.setMaxAge(0);
               response.addCookie(cookie);
               out.print("Deleted cookie : " + cookie.getName( ) + "<br/>");
            }
            out.print("Name : " + cookie.getName( ) + ",  ");
            out.print("Value: " + cookie.getValue( )+" <br/>");
         }
      } else {
         out.println("<h2>No cookies founds</h2>");
      }
      out.println("</body>");
      out.println("</html>");
   }
}

编译上面 servlet DeleteCookies 并创建 web.xml 文件中的相应条目。现在,运行 [role="bare"] [role="bare"]http://localhost:8080/DeleteCookies 将显示以下结果 −

Compile above servlet DeleteCookies and create appropriate entry in web.xml file. Now running [role="bare"]http://localhost:8080/DeleteCookies would display the following result −

Cookies Name and Value
Deleted cookie : first_name
Name : first_name, Value: John
Name : last_name,  Value: Player

现在,尝试运行 [role="bare"] [role="bare"]http://localhost:8080/ReadCookies ,它将只显示一个如下所示的 cookie −

Now try to run [role="bare"]http://localhost:8080/ReadCookies and it would display only one cookie as follows −

 Found Cookies Name and Value
Name : last_name,  Value: Player

您可以在 Internet Explorer 中手动删除 cookie。从工具菜单开始,然后选择 Internet 选项。要删除所有 cookie,请按删除 Cookies。

You can delete your cookies in Internet Explorer manually. Start at the Tools menu and select Internet Options. To delete all cookies, press Delete Cookies.

Servlets - Session Tracking

HTTP 是一种“无状态”协议,这意味着每次客户端检索网页时,客户端都会打开与 Web 服务器的独立连接,该服务器不会自动保留以前客户端请求的任何记录。

HTTP is a "stateless" protocol which means each time a client retrieves a Web page, the client opens a separate connection to the Web server and the server automatically does not keep any record of previous client request.

仍然有以下三种方法来维持 Web 客户端与 Web 服务器之间的会话:

Still there are following three ways to maintain session between web client and web server −

Cookies

Web 服务器可以为每个网络客户端分配一个作为 cookie 的唯一会话 ID,并且在接收到 cookie 后,可用于识别客户的后续请求。

A webserver can assign a unique session ID as a cookie to each web client and for subsequent requests from the client they can be recognized using the recieved cookie.

这可能不是一个有效的方法,因为很多时候浏览器不支持 cookie,因此我建议不要使用这些步骤来维护会话。

This may not be an effective way because many time browser does not support a cookie, so I would not recommend to use this procedure to maintain the sessions.

Hidden Form Fields

Web 服务器可以结合唯一会话 ID 发送隐藏的 HTML 表单字段,如下所示:

A web server can send a hidden HTML form field along with a unique session ID as follows −

<input type = "hidden" name = "sessionid" value = "12345">

此条目表示,提交表单时,指定的名称和值将自动包含在 GET 或 POST 数据中。每次 Web 浏览器发送请求时,都可以使用 session_id 值来跟踪不同的 Web 浏览器。

This entry means that, when the form is submitted, the specified name and value are automatically included in the GET or POST data. Each time when web browser sends request back, then session_id value can be used to keep the track of different web browsers.

这可能是跟踪会话的有效方法,但单击常规(<A HREF…​>)超文本链接不会导致表单提交,因此隐藏表单字段也不能支持常规会话跟踪。

This could be an effective way of keeping track of the session but clicking on a regular (<A HREF…​>) hypertext link does not result in a form submission, so hidden form fields also cannot support general session tracking.

URL Rewriting

你可以在每个 URL 的末尾附加一些额外的数据来标识会话,并且服务器可以将该会话标识符与它存储的有关该会话的数据相关联。

You can append some extra data on the end of each URL that identifies the session, and the server can associate that session identifier with data it has stored about that session.

例如,对于 [role="bare"] [role="bare"]http://tutorialspoint.com/file.htm;sessionid = 12345,会话标识符附加为 sessionid = 12345,可从 Web 服务器访问以识别客户端。

For example, with [role="bare"]http://tutorialspoint.com/file.htm;sessionid = 12345, the session identifier is attached as sessionid = 12345 which can be accessed at the web server to identify the client.

URL 重写是维护会话的更好方法,即使浏览器不支持 cookie,它也能发挥作用。URL 重写的缺点是即使对于简单的静态 HTML 页面,你也必须动态生成每个 URL 以分配会话 ID。

URL rewriting is a better way to maintain sessions and it works even when browsers don’t support cookies. The drawback of URL re-writing is that you would have to generate every URL dynamically to assign a session ID, even in case of a simple static HTML page.

The HttpSession Object

除了上述三种方法外,servlet 还提供了 HttpSession Interface,它提供了一种跨多个页面请求或访问网站识别用户并存储有关该用户信息的方法。

Apart from the above mentioned three ways, servlet provides HttpSession Interface which provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user.

servlet 容器使用此接口来创建 HTTP 客户端与 HTTP 服务器之间的会话。会话会在一个指定的时间段内保持,跨多个来自用户的连接或页面请求。

The servlet container uses this interface to create a session between an HTTP client and an HTTP server. The session persists for a specified time period, across more than one connection or page request from the user.

你可以通过调用 HttpServletRequest 的公共方法 getSession() 来获取 HttpSession 对象,如下所示:

You would get HttpSession object by calling the public method getSession() of HttpServletRequest, as below −

HttpSession session = request.getSession();

在向客户端发送任何文档内容之前,你需要调用 request.getSession()。以下是通过 HttpSession 对象可用的重要方法的摘要:

You need to call request.getSession() before you send any document content to the client. Here is a summary of the important methods available through HttpSession object −

Sr.No.

Method & Description

1

*public Object getAttribute(String name) * This method returns the object bound with the specified name in this session, or null if no object is bound under the name.

2

public Enumeration getAttributeNames() This method returns an Enumeration of String objects containing the names of all the objects bound to this session.

3

*public long getCreationTime() * This method returns the time when this session was created, measured in milliseconds since midnight January 1, 1970 GMT.

4

*public String getId() * This method returns a string containing the unique identifier assigned to this session.

5

*public long getLastAccessedTime() * This method returns the last accessed time of the session, in the format of milliseconds since midnight January 1, 1970 GMT

6

*public int getMaxInactiveInterval() * This method returns the maximum time interval (seconds), that the servlet container will keep the session open between client accesses.

7

*public void invalidate() * This method invalidates this session and unbinds any objects bound to it.

8

*public boolean isNew( * This method returns true if the client does not yet know about the session or if the client chooses not to join the session.

9

*public void removeAttribute(String name) * This method removes the object bound with the specified name from this session.

10

*public void setAttribute(String name, Object value) * This method binds an object to this session, using the name specified.

11

*public void setMaxInactiveInterval(int interval) * This method specifies the time, in seconds, between client requests before the servlet container will invalidate this session.

Session Tracking Example

此示例描述了如何使用 HttpSession 对象找出会话的创建时间和上次访问时间。如果尚未存在会话,我们将为请求关联一个新会话。

This example describes how to use the HttpSession object to find out the creation time and the last-accessed time for a session. We would associate a new session with the request if one does not already exist.

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

// Extend HttpServlet class
public class SessionTrack extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Create a session object if it is already not  created.
      HttpSession session = request.getSession(true);

      // Get session creation time.
      Date createTime = new Date(session.getCreationTime());

      // Get last access time of this web page.
      Date lastAccessTime = new Date(session.getLastAccessedTime());

      String title = "Welcome Back to my website";
      Integer visitCount = new Integer(0);
      String visitCountKey = new String("visitCount");
      String userIDKey = new String("userID");
      String userID = new String("ABCD");

      // Check if this is new comer on your web page.
      if (session.isNew()) {
         title = "Welcome to my website";
         session.setAttribute(userIDKey, userID);
      } else {
         visitCount = (Integer)session.getAttribute(visitCountKey);
         visitCount = visitCount + 1;
         userID = (String)session.getAttribute(userIDKey);
      }
      session.setAttribute(visitCountKey,  visitCount);

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      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" +
               "<h2 align = \"center\">Session Infomation</h2>\n" +
               "<table border = \"1\" align = \"center\">\n" +

                  "<tr bgcolor = \"#949494\">\n" +
                     "  <th>Session info</th><th>value</th>
                  </tr>\n" +

                  "<tr>\n" +
                     "  <td>id</td>\n" +
                     "  <td>" + session.getId() + "</td>
                  </tr>\n" +

                  "<tr>\n" +
                     "  <td>Creation Time</td>\n" +
                     "  <td>" + createTime + "  </td>
                  </tr>\n" +

                  "<tr>\n" +
                     "  <td>Time of Last Access</td>\n" +
                     "  <td>" + lastAccessTime + "  </td>
                  </tr>\n" +

                  "<tr>\n" +
                     "  <td>User ID</td>\n" +
                     "  <td>" + userID + "  </td>
                  </tr>\n" +

                  "<tr>\n" +
                     "  <td>Number of visits</td>\n" +
                     "  <td>" + visitCount + "</td>
                  </tr>\n" +
               "</table>\n" +
            "</body>
         </html>"
      );
   }
}

编译上面的 servlet SessionTrack 并创建 web.xml 文件中适当的条目。现在运行 [role="bare"] [role="bare"]http://localhost:8080/SessionTrack ,当您第一次运行时,将显示以下结果 −

Compile the above servlet SessionTrack and create appropriate entry in web.xml file. Now running [role="bare"]http://localhost:8080/SessionTrack would display the following result when you would run for the first time −

Welcome to my website
Session Infomation


Session info
value


id
0AE3EC93FF44E3C525B4351B77ABB2D5


Creation Time
Tue Jun 08 17:26:40 GMT+04:00 2010


Time of Last Access
Tue Jun 08 17:26:40 GMT+04:00 2010


User ID
ABCD


Number of visits
0

现在尝试第二次运行相同的 servlet,它将显示以下结果。

Now try to run the same servlet for second time, it would display following result.

Welcome Back to my website
Session Infomation


info type
value


id
0AE3EC93FF44E3C525B4351B77ABB2D5


Creation Time
Tue Jun 08 17:26:40 GMT+04:00 2010


Time of Last Access
Tue Jun 08 17:26:40 GMT+04:00 2010


User ID
ABCD


Number of visits
1

Deleting Session Data

完成用户的会话数据时,您有几种选择 −

When you are done with a user’s session data, you have several options −

  1. Remove a particular attribute − You can call public void removeAttribute(String name) method to delete the value associated with a particular key.

  2. Delete the whole session − You can call public void invalidate() method to discard an entire session.

  3. Setting Session timeout − You can call public void setMaxInactiveInterval(int interval) method to set the timeout for a session individually.

  4. Log the user out − The servers that support servlets 2.4, you can call logout to log the client out of the Web server and invalidate all sessions belonging to all the users.

  5. web.xml Configuration − If you are using Tomcat, apart from the above mentioned methods, you can configure session time out in web.xml file as follows.

<session-config>
   <session-timeout>15</session-timeout>
</session-config>

超时时间表示为分钟数,并覆盖 Tomcat 中的默认超时时间(30 分钟)。

The timeout is expressed as minutes, and overrides the default timeout which is 30 minutes in Tomcat.

servlet 中的 getMaxInactiveInterval( ) 方法以秒为单位返回该会话的超时时间。因此,如果在 web.xml 中为您的会话配置 15 分钟,则 getMaxInactiveInterval( ) 返回 900。

The getMaxInactiveInterval( ) method in a servlet returns the timeout period for that session in seconds. So if your session is configured in web.xml for 15 minutes, getMaxInactiveInterval( ) returns 900.

Servlets - Database Access

本教程假定您了解 JDBC 应用程序的工作原理。在使用 servlet 访问数据库之前,确保您已经设置好了适当的 JDBC 环境以及数据库。

This tutorial assumes you have understanding on how JDBC application works. Before starting with database access through a servlet, make sure you have proper JDBC environment setup along with a database.

要详细了解如何使用 JDBC 及其环境设置访问数据库,可以参阅我们的 JDBC Tutorial

For more detail on how to access database using JDBC and its environment setup you can go through our JDBC Tutorial.

首先了解基本概念,我们要创建一个简单表格并在该表格中创建一些记录,如下所示 −

To start with basic concept, let us create a simple table and create few records in that table as follows −

Create Table

要创建 TEST 数据库中的 Employees 表格,请使用以下步骤 −

To create the Employees table in TEST database, use the following steps −

Step 1

打开 Command Prompt 并更改到安装目录,如下所示 −

Open a Command Prompt and change to the installation directory as follows −

C:\>
C:\>cd Program Files\MySQL\bin
C:\Program Files\MySQL\bin>

Step 2

按照以下方法登录数据库:

Login to database as follows

C:\Program Files\MySQL\bin>mysql -u root -p
Enter password: ********
mysql>

Step 3

TEST 数据库中按照如下方式创建表 Employee

Create the table Employee in TEST database as follows −

mysql> use TEST;
mysql> create table Employees (
   id int not null,
   age int not null,
   first varchar (255),
   last varchar (255)
);
Query OK, 0 rows affected (0.08 sec)
mysql>

Create Data Records

最后,在 Employee 表中创建一些记录,如下所示 −

Finally you create few records in Employee table as follows −

mysql> INSERT INTO Employees VALUES (100, 18, 'Zara', 'Ali');
Query OK, 1 row affected (0.05 sec)

mysql> INSERT INTO Employees VALUES (101, 25, 'Mahnaz', 'Fatma');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO Employees VALUES (102, 30, 'Zaid', 'Khan');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO Employees VALUES (103, 28, 'Sumit', 'Mittal');
Query OK, 1 row affected (0.00 sec)

mysql>

Accessing a Database

以下示例显示了如何使用 Servlet 访问 TEST 数据库:

Here is an example which shows how to access TEST database using Servlet.

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

public class DatabaseAccess extends HttpServlet{

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // JDBC driver name and database URL
      static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
      static final String DB_URL="jdbc:mysql://localhost/TEST";

      //  Database credentials
      static final String USER = "root";
      static final String PASS = "password";

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      String title = "Database Result";

      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");
      try {
         // Register JDBC driver
         Class.forName("com.mysql.jdbc.Driver");

         // Open a connection
         Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);

         // Execute SQL query
         Statement stmt = conn.createStatement();
         String sql;
         sql = "SELECT id, first, last, age FROM Employees";
         ResultSet rs = stmt.executeQuery(sql);

         // Extract data from result set
         while(rs.next()){
            //Retrieve by column name
            int id  = rs.getInt("id");
            int age = rs.getInt("age");
            String first = rs.getString("first");
            String last = rs.getString("last");

            //Display values
            out.println("ID: " + id + "<br>");
            out.println(", Age: " + age + "<br>");
            out.println(", First: " + first + "<br>");
            out.println(", Last: " + last + "<br>");
         }
         out.println("</body></html>");

         // Clean-up environment
         rs.close();
         stmt.close();
         conn.close();
      } catch(SQLException se) {
         //Handle errors for JDBC
         se.printStackTrace();
      } catch(Exception e) {
         //Handle errors for Class.forName
         e.printStackTrace();
      } finally {
         //finally block used to close resources
         try {
            if(stmt!=null)
               stmt.close();
         } catch(SQLException se2) {
         } // nothing we can do
         try {
            if(conn!=null)
            conn.close();
         } catch(SQLException se) {
            se.printStackTrace();
         } //end finally try
      } //end try
   }
}

现在我们编译上述 servlet 并在 web.xml 中创建以下条目:

Now let us compile above servlet and create following entries in web.xml

....
<servlet>
   <servlet-name>DatabaseAccess</servlet-name>
   <servlet-class>DatabaseAccess</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>DatabaseAccess</servlet-name>
   <url-pattern>/DatabaseAccess</url-pattern>
</servlet-mapping>
....

现在使用 URL [role="bare"] [role="bare"]http://localhost:8080/DatabaseAccess 调用此 servlet,它将显示以下响应:

Now call this servlet using URL [role="bare"]http://localhost:8080/DatabaseAccess which would display following response −

Database Result
ID: 100, Age: 18, First: Zara, Last: Ali
ID: 101, Age: 25, First: Mahnaz, Last: Fatma
ID: 102, Age: 30, First: Zaid, Last: Khan
ID: 103, Age: 28, First: Sumit, Last: Mittal

Servlets - File Uploading

Servlet 可以与 HTML 表单标记一起使用,允许用户将文件上载到服务器。上传的文件可以是文本文件、图像文件或任何文档。

A Servlet can be used with an HTML form tag to allow users to upload files to the server. An uploaded file could be a text file or image file or any document.

Creating a File Upload Form

以下 HTM 代码创建一个上传程序表单。以下是需要注意的重要事项:

The following HTM code below creates an uploader form. Following are the important points to be noted down −

  1. The form method attribute should be set to POST method and GET method can not be used

  2. The form enctype attribute should be set to multipart/form-data.

  3. The form action attribute should be set to a servlet file which would handle file uploading at backend server. Following example is using UploadServlet servlet to upload file.

  4. To upload a single file you should use a single <input …​/> tag with attribute type="file". To allow multiple files uploading, include more than one input tags with different values for the name attribute. The browser associates a Browse button with each of them.

<html>
   <head>
      <title>File Uploading Form</title>
   </head>

   <body>
      <h3>File Upload:</h3>
      Select a file to upload: <br />
      <form action = "UploadServlet" method = "post" enctype = "multipart/form-data">
         <input type = "file" name = "file" size = "50" />
         <br />
         <input type = "submit" value = "Upload File" />
      </form>
   </body>
</html>

这将显示以下结果,该结果允许从本地 PC 中选择一个文件,当用户单击“上传文件”时,表单将与所选文件一起提交:

This will display following result which would allow to select a file from local PC and when user would click at "Upload File", form would be submitted along with the selected fil −

File Upload:
Select a file to upload:




NOTE: This is just dummy form and would not work.

Writing Backend Servlet

以下是 UploadServlet servlet,它将负责接受上传的文件并将其存储在目录 <Tomcat-installation-directory>/webapps/data 中。此目录名称还可以使用外部配置(例如 web.xml 中的 context-param 元素)如下所示添加:

Following is the servlet UploadServlet which would take care of accepting uploaded file and to store it in directory <Tomcat-installation-directory>/webapps/data. This directory name could also be added using an external configuration such as a context-param element in web.xml as follows −

<web-app>
   ....
   <context-param>
      <description>Location to store uploaded file</description>
      <param-name>file-upload</param-name>
      <param-value>
         c:\apache-tomcat-5.5.29\webapps\data\
     </param-value>
   </context-param>
   ....
</web-app>

以下是 UploadServlet 的源代码,它可以一次处理多个文件上传。在继续之前,请确保以下内容:

Following is the source code for UploadServlet which can handle multiple file uploading at a time. Before proceeding you have make sure the followings −

  1. Following example depends on FileUpload, so make sure you have the latest version of commons-fileupload.x.x.jar file in your classpath. You can download it from https://commons.apache.org/fileupload/.

  2. FileUpload depends on Commons IO, so make sure you have the latest version of commons-io-x.x.jar file in your classpath. You can download it from https://commons.apache.org/io/.

  3. While testing following example, you should upload a file which has less size than maxFileSize otherwise file would not be uploaded.

  4. Make sure you have created directories c:\temp and c:\apache-tomcat8.0.28\webapps\data well in advance.

// Import required java libraries
import java.io.*;
import java.util.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.output.*;

public class UploadServlet extends HttpServlet {

   private boolean isMultipart;
   private String filePath;
   private int maxFileSize = 50 * 1024;
   private int maxMemSize = 4 * 1024;
   private File file ;

   public void init( ){
      // Get the file location where it would be stored.
      filePath = getServletContext().getInitParameter("file-upload");
   }

   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, java.io.IOException {

      // Check that we have a file upload request
      isMultipart = ServletFileUpload.isMultipartContent(request);
      response.setContentType("text/html");
      java.io.PrintWriter out = response.getWriter( );

      if( !isMultipart ) {
         out.println("<html>");
         out.println("<head>");
         out.println("<title>Servlet upload</title>");
         out.println("</head>");
         out.println("<body>");
         out.println("<p>No file uploaded</p>");
         out.println("</body>");
         out.println("</html>");
         return;
      }

      DiskFileItemFactory factory = new DiskFileItemFactory();

      // maximum size that will be stored in memory
      factory.setSizeThreshold(maxMemSize);

      // Location to save data that is larger than maxMemSize.
      factory.setRepository(new File("c:\\temp"));

      // Create a new file upload handler
      ServletFileUpload upload = new ServletFileUpload(factory);

      // maximum file size to be uploaded.
      upload.setSizeMax( maxFileSize );

      try {
         // Parse the request to get file items.
         List fileItems = upload.parseRequest(request);

         // Process the uploaded file items
         Iterator i = fileItems.iterator();

         out.println("<html>");
         out.println("<head>");
         out.println("<title>Servlet upload</title>");
         out.println("</head>");
         out.println("<body>");

         while ( i.hasNext () ) {
            FileItem fi = (FileItem)i.next();
            if ( !fi.isFormField () ) {
               // Get the uploaded file parameters
               String fieldName = fi.getFieldName();
               String fileName = fi.getName();
               String contentType = fi.getContentType();
               boolean isInMemory = fi.isInMemory();
               long sizeInBytes = fi.getSize();

               // Write the file
               if( fileName.lastIndexOf("\\") >= 0 ) {
                  file = new File( filePath + fileName.substring( fileName.lastIndexOf("\\"))) ;
               } else {
                  file = new File( filePath + fileName.substring(fileName.lastIndexOf("\\")+1)) ;
               }
               fi.write( file ) ;
               out.println("Uploaded Filename: " + fileName + "<br>");
            }
         }
         out.println("</body>");
         out.println("</html>");
         } catch(Exception ex) {
            System.out.println(ex);
         }
      }

      public void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, java.io.IOException {

         throw new ServletException("GET method used with " +
            getClass( ).getName( )+": POST method required.");
      }
   }
}

Compile and Running Servlet

编译上述 servlet UploadServlet,并在 web.xml 文件中创建必需的条目,如下所示。

Compile above servlet UploadServlet and create required entry in web.xml file as follows.

<servlet>
   <servlet-name>UploadServlet</servlet-name>
   <servlet-class>UploadServlet</servlet-class>
</servlet>

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

现在尝试使用您在上面创建的 HTML 表单上传文件。当您尝试 [role="bare"] [role="bare"]http://localhost:8080/UploadFile.htm 时,它将显示以下结果,这将帮助您上传本地计算机上的任何文件。

Now try to upload files using the HTML form which you created above. When you would try [role="bare"]http://localhost:8080/UploadFile.htm, it would display following result which would help you uploading any file from your local machine.

File Upload:
Select a file to upload:

如果您的 servlet 脚本运行良好,您的文件应上传到 c:\apache-tomcat-8.0.28\webapps\data\ 目录中。

If your servlet script works fine, your file should be uploaded in c:\apache-tomcat8.0.28\webapps\data\ directory.

Servlets - Handling Date

使用 Servlet 最重要的优点之一是您可以在核心 Java 中使用大多数可用方法。本教程将引导您逐步了解 Java 提供的 Date 类,该类在 java.util 包中可用,此类封装当前日期和时间。

One of the most important advantages of using Servlet is that you can use most of the methods available in core Java. This tutorial would take you through Java provided Date class which is available in java.util package, this class encapsulates the current date and time.

Date 类支持两个构造函数。第一个构造函数使用当前日期与时间初始化对象。

The Date class supports two constructors. The first constructor initializes the object with the current date and time.

Date( )

以下构造函数接受一个参数,该参数等于自 1970 年 1 月 1 日午夜以来経過的毫秒数

The following constructor accepts one argument that equals the number of milliseconds that have elapsed since midnight, January 1, 1970

Date(long millisec)

一旦您有可用的 Date 对象,便可以调用以下任何支持方法来处理日期 -

Once you have a Date object available, you can call any of the following support methods to play with dates −

Sr.No.

Methods & Description

1

boolean after(Date date) Returns true if the invoking Date object contains a date that is later than the one specified by date, otherwise, it returns false.

2

boolean before(Date date) Returns true if the invoking Date object contains a date that is earlier than the one specified by date, otherwise, it returns false.

3

Object clone( ) Duplicates the invoking Date object.

4

int compareTo(Date date) Compares the value of the invoking object with that of date. Returns 0 if the values are equal. Returns a negative value if the invoking object is earlier than date. Returns a positive value if the invoking object is later than date.

5

int compareTo(Object obj) Operates identically to compareTo(Date) if obj is of class Date. Otherwise, it throws a ClassCastException.

6

boolean equals(Object date) Returns true if the invoking Date object contains the same time and date as the one specified by date, otherwise, it returns false.

7

long getTime( ) Returns the number of milliseconds that have elapsed since January 1, 1970.

8

int hashCode( ) Returns a hash code for the invoking object.

9

void setTime(long time) Sets the time and date as specified by time, which represents an elapsed time in milliseconds from midnight, January 1, 1970.

10

String toString( ) Converts the invoking Date object into a string and returns the result.

Getting Current Date & Time

在 Java Servlet 中获取当前日期和时间非常简单。您可以使用一个简单的 Date 对象和 toString() 方法来按如下方式打印当前日期和时间 -

This is very easy to get current date and time in Java Servlet. You can use a simple Date object with toString() method to print current date and time as follows −

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

// Extend HttpServlet class
public class CurrentDate 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 = "Display Current Date & Time";
      Date date = new Date();
      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" +
               "<h2 align = \"center\">" + date.toString() + "</h2>\n" +
            "</body>
         </html>"
      );
   }
}

现在让我们编译上述 servlet,并在 web.xml 中创建适当的条目,然后使用 URL [role="bare"] [role="bare"]http://localhost:8080/CurrentDate 调用此 servlet。这将产生以下结果 -

Now let us compile above servlet and create appropriate entries in web.xml and then call this servlet using URL [role="bare"]http://localhost:8080/CurrentDate. This would produce following result −

Display Current Date & Time
Mon Jun 21 21:46:49 GMT+04:00 2010

尝试刷新 URL [role="bare"] [role="bare"]http://localhost:8080/CurrentDate ,每次刷新您都会发现几秒钟的差异。

Try to refresh URL [role="bare"]http://localhost:8080/CurrentDate and you would find difference in seconds every time you would refresh.

Date Comparison

如上所述,您可以在 Servlet 中使用所有可用的 Java 方法。如果您需要比较两个日期,以下是方法:

As I mentioned above you can use all the available Java methods in your Servlet. In case you need to compare two dates, following are the methods −

  1. You can use getTime( ) to obtain the number of milliseconds that have elapsed since midnight, January 1, 1970, for both objects and then compare these two values.

  2. You can use the methods before( ), after( ), and equals( ). Because the 12th of the month comes before the 18th, for example, new Date(99, 2, 12).before(new Date (99, 2, 18)) returns true.

  3. You can use the compareTo( ) method, which is defined by the Comparable interface and implemented by Date.

Date Formatting using SimpleDateFormat

SimpleDateFormat 是一个用于以特定语言敏感的方式设置和解析日期的具体类。使用 SimpleDateFormat,可以选择任何用户定义的模式来设置日期和时间格式。

SimpleDateFormat is a concrete class for formatting and parsing dates in a localesensitive manner. SimpleDateFormat allows you to start by choosing any user-defined patterns for date-time formatting.

让我们修改上面的示例,如下所示:

Let us modify above example as follows −

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

// Extend HttpServlet class
public class CurrentDate 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 = "Display Current Date & Time";
      Date dNow = new Date( );
      SimpleDateFormat ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
      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" +
               "<h2 align = \"center\">" + ft.format(dNow) + "</h2>\n" +
            "</body>
         </html>"
      );
   }
}

再次编译上面的 servlet,然后使用 URL [role="bare"] [role="bare"]http://localhost:8080/CurrentDate 调用此 servlet。这将产生以下结果:

Compile above servlet once again and then call this servlet using URL [role="bare"]http://localhost:8080/CurrentDate. This would produce following result −

Display Current Date & Time
Mon 2010.06.21 at 10:06:44 PM GMT+04:00

Simple DateFormat Format Codes

要指定时间格式,请使用时间模式字符串。在此模式中,保留所有 ASCII 字母作为模式字母,定义如下:

To specify the time format use a time pattern string. In this pattern, all ASCII letters are reserved as pattern letters, which are defined as the following −

Character

Description

Example

G

Era designator

AD

y

Year in four digits

2001

M

Month in year

July or 07

d

Day in month

10

h

Hour in A.M./P.M. (1~12)

12

H

Hour in day (0~23)

22

m

Minute in hour

30

s

Second in minute

55

S

Millisecond

234

E

Day in week

Tuesday

D

Day in year

360

F

Day of week in month

2 (second Wed. in July)

w

Week in year

40

W

Week in month

1

a

A.M./P.M. marker

PM

k

Hour in day (1~24)

24

K

Hour in A.M./P.M. (0~11)

10

z

Time zone

Eastern Standard Time

'

Escape for text

Delimiter

"

Single quote

`

有关用于操作日期的可用常量方法的完整列表,请参阅标准 Java 文档。

For a complete list of constant available methods to manipulate date, you can refer to standard Java documentation.

Servlets - Page Redirection

页面重定向是一种将客户端发送到不同于请求的新位置的技术。当一个文档移到一个新位置或可能因为负载平衡时,通常使用页面重定向。

Page redirection is a technique where the client is sent to a new location other than requested. Page redirection is generally used when a document moves to a new location or may be because of load balancing.

将请求重定向到另一个页面的最简单方法是使用响应对象的 sendRedirect() 方法。以下是此方法的标志:

The simplest way of redirecting a request to another page is using method sendRedirect() of response object. Following is the signature of this method −

public void HttpServletResponse.sendRedirect(String location)
throws IOException

此方法会将响应连同状态代码和新页面位置一起发送回浏览器。您还可以同时使用 setStatus() 和 setHeader() 方法来实现相同的功能:

This method sends back the response to the browser along with the status code and new page location. You can also use setStatus() and setHeader() methods together to achieve the same −

....
String site = "http://www.newpage.com" ;
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site);
....

Example

此示例演示了 servlet 如何执行页面重定向到另一个位置:

This example shows how a servlet performs page redirection to another location −

import java.io.*;
import java.sql.Date;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class PageRedirect extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");

      // New location to be redirected
      String site = new String("http://www.photofuntoos.com");

      response.setStatus(response.SC_MOVED_TEMPORARILY);
      response.setHeader("Location", site);
   }
}

现在我们编译上述 servlet 并在 web.xml 中创建以下条目:

Now let us compile above servlet and create following entries in web.xml

....
<servlet>
   <servlet-name>PageRedirect</servlet-name>
   <servlet-class>PageRedirect</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>PageRedirect</servlet-name>
   <url-pattern>/PageRedirect</url-pattern>
</servlet-mapping>
....

现在,使用 URL [role="bare"] [role="bare"]http://localhost:8080/PageRedirect 调用此 servlet。这将重定向您到 URL [role="bare"] [role="bare"]http://www.photofuntoos.com

Now call this servlet using URL [role="bare"]http://localhost:8080/PageRedirect. This would redirect you to URL [role="bare"]http://www.photofuntoos.com.

Servlets - Hits Counter

Hit Counter for a Web Page

很多情况下,您会希望了解网站特定页面上的点击总数。使用 servlet 计算这些点击数非常简单,因为 servlet 的生命周期由运行其的容器来控制。

Many times you would be interested in knowing total number of hits on a particular page of your website. It is very simple to count these hits using a servlet because the life cycle of a servlet is controlled by the container in which it runs.

以下是实现基于 Servlet 生命周期计数点击数的简单方法:

Following are the steps to be taken to implement a simple page hit counter which is based on Servlet Life Cycle −

  1. Initialize a global variable in init() method.

  2. Increase global variable every time either doGet() or doPost() method is called.

  3. If required, you can use a database table to store the value of global variable in destroy() method. This value can be read inside init() method when servlet would be initialized next time. This step is optional.

  4. If you want to count only unique page hits with-in a session then you can use isNew() method to check if same page already have been hit with-in that session. This step is optional.

  5. You can display value of the global counter to show total number of hits on your web site. This step is also optional.

这里我假设 Web 容器不会重新启动。如果重新启动或 servlet 被销毁,则点击计数器将重置。

Here I’m assuming that the web container will not be restarted. If it is restarted or servlet destroyed, the hit counter will be reset.

Example

本示例演示如何实现简单的页面访问计数器 -

This example shows how to implement a simple page hit counter −

import java.io.*;
import java.sql.Date;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class PageHitCounter extends HttpServlet {

   private int hitCount;

   public void init() {
      // Reset hit counter.
      hitCount = 0;
   }

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");

      // This method executes whenever the servlet is hit
      // increment hitCount
      hitCount++;
      PrintWriter out = response.getWriter();
      String title = "Total Number of Hits";
      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" +
               "<h2 align = \"center\">" + hitCount + "</h2>\n" +
            "</body>
         </html>"
      );
   }

   public void destroy() {
      // This is optional step but if you like you
      // can write hitCount value in your database.
   }
}

现在我们编译上述 servlet 并在 web.xml 中创建以下条目:

Now let us compile above servlet and create following entries in web.xml

<servlet>
   <servlet-name>PageHitCounter</servlet-name>
   <servlet-class>PageHitCounter</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>PageHitCounter</servlet-name>
   <url-pattern>/PageHitCounter</url-pattern>
</servlet-mapping>
....

现在使用 URL [role="bare"] [role="bare"]http://localhost:8080/PageHitCounter 调用此 servlet。每次刷新此页面,计数器都会增加 1,并且会显示以下结果 -

Now call this servlet using URL [role="bare"]http://localhost:8080/PageHitCounter. This would increase counter by one every time this page gets refreshed and it would display following result −

Total Number of Hits
6
Hit Counter for a Website:

许多时候您会希望了解整个网站上的访问总数。这在 Servlet 中也很简单,我们可以使用过滤器来实现此目的。

Many times you would be interested in knowing total number of hits on your whole website. This is also very simple in Servlet and we can achieve this using filters.

以下是实现基于过滤器生命周期的简单网站访问计数器的步骤 -

Following are the steps to be taken to implement a simple website hit counter which is based on Filter Life Cycle −

  1. Initialize a global variable in init() method of a filter.

  2. Increase global variable every time doFilter method is called.

  3. If required, you can use a database table to store the value of global variable in destroy() method of filter. This value can be read inside init() method when filter would be initialized next time. This step is optional.

这里我假设 Web 容器不会重新启动。如果重新启动或 servlet 被销毁,则点击计数器将重置。

Here I’m assuming that the web container will not be restarted. If it is restarted or servlet destroyed, the hit counter will be reset.

Example

本示例演示如何实现简单的网站访问计数器 -

This example shows how to implement a simple website hit counter −

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

public class SiteHitCounter implements Filter {

   private int hitCount;

   public void  init(FilterConfig config) throws ServletException {
      // Reset hit counter.
      hitCount = 0;
   }

   public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws java.io.IOException, ServletException {

      // increase counter by one
      hitCount++;

      // Print the counter.
      System.out.println("Site visits count :"+ hitCount );

      // Pass request back down the filter chain
      chain.doFilter(request,response);
   }

   public void destroy() {
      // This is optional step but if you like you
      // can write hitCount value in your database.
   }
}

现在让我们编译上述 servlet,并在 web.xml 中创建以下项

Now let us compile the above servlet and create the following entries in web.xml

....
<filter>
   <filter-name>SiteHitCounter</filter-name>
   <filter-class>SiteHitCounter</filter-class>
</filter>

<filter-mapping>
   <filter-name>SiteHitCounter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
....

现在调用任何 URL(如 URL [role="bare"] [role="bare"]http://localhost:8080/ )。每次任何页面被访问时,计数器就会增加 1,并且会在日志中显示以下消息 -

Now call any URL like URL [role="bare"]http://localhost:8080/. This would increase counter by one every time any page gets a hit and it would display following message in the log −

Site visits count : 1
Site visits count : 2
Site visits count : 3
Site visits count : 4
Site visits count : 5
..................

Servlets - Auto Page Refresh

考虑一个显示现场比赛比分、股票市场状况或汇率的网页。对于所有这些类型的页面,您都需要使用浏览器的刷新或重新加载按钮定期刷新您的网页。

Consider a webpage which is displaying live game score or stock market status or currency exchange ration. For all such type of pages, you would need to refresh your web page regularly using refresh or reload button with your browser.

Java Servlet 通过为您提供一种机制来简化此项工作,您可以在这种机制中以这样的方式制作网页,使其在给定的时间间隔后自动刷新。

Java Servlet makes this job easy by providing you a mechanism where you can make a webpage in such a way that it would refresh automatically after a given interval.

刷新网页的最简单方法是使用响应对象的 setIntHeader() 方法。以下是该方法的签名 -

The simplest way of refreshing a web page is using method setIntHeader() of response object. Following is the signature of this method −

public void setIntHeader(String header, int headerValue)

此方法将标头 "Refresh" 连同表示时间间隔(以秒为单位)的整数值发送回浏览器。

This method sends back header "Refresh" to the browser along with an integer value which indicates time interval in seconds.

Auto Page Refresh Example

此示例演示 servlet 如何使用 setIntHeader() 方法来设置 Refresh 标头以执行自动页面刷新。

This example shows how a servlet performs auto page refresh using setIntHeader() method to set Refresh header.

// 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 Page Refresh using Servlet";
      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,并在 web.xml 中创建以下项

Now let us compile the above servlet and create the following entries in web.xml

....
 <servlet>
     <servlet-name>Refresh</servlet-name>
     <servlet-class>Refresh</servlet-class>
 </servlet>

 <servlet-mapping>
     <servlet-name>Refresh</servlet-name>
     <url-pattern>/Refresh</url-pattern>
 </servlet-mapping>
....

现在使用 URL [role="bare"] [role="bare"]http://localhost:8080/Refresh 调用此 servlet,它将在每 5 秒后显示当前系统时间,如下所示。只需运行 servlet 并等待查看结果 -

Now call this servlet using URL [role="bare"]http://localhost:8080/Refresh which would display current system time after every 5 seconds as follows. Just run the servlet and wait to see the result −

Auto Page Refresh using Servlet
Current Time is: 9:44:50 PM

Servlets - Sending Email

使用 Servlet 发送电子邮件非常简单,但前提是您应该在计算机上安装 JavaMail APIJava Activation Framework (JAF)

To send an email using your a Servlet is simple enough but to start with you should have JavaMail API and Java Activation Framework (JAF) installed on your machine.

  1. You can download latest version of JavaMail (Version 1.2) from Java’s standard website.

  2. You can download latest version of JAF (Version 1.1.1) from Java’s standard website.

下载并解压缩这些文件,在新建的顶层目录中,你可以找到这两个应用程序的多个 jar 文件。你需要在你的 CLASSPATH 中添加 mail.jaractivation.jar 文件。

Download and unzip these files, in the newly created top level directories you will find a number of jar files for both the applications. You need to add mail.jar and activation.jar files in your CLASSPATH.

Send a Simple Email

以下示例演示从您的计算机发送一封简单的电子邮件。这里假设您的 localhost 已连接到互联网并能够发送电子邮件。同时,确保 CLASSPATH 中存在 Java Email API 包和 JAF 包中的所有 jar 文件。

Here is an example to send a simple email from your machine. Here it is assumed that your localhost is connected to the internet and capable enough to send an email. Same time make sure all the jar files from Java Email API package and JAF package are available in CLASSPATH.

// File Name SendEmail.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class SendEmail extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Recipient's email ID needs to be mentioned.
      String to = "abcd@gmail.com";

      // Sender's email ID needs to be mentioned
      String from = "web@gmail.com";

      // Assuming you are sending email from localhost
      String host = "localhost";

      // Get system properties
      Properties properties = System.getProperties();

      // Setup mail server
      properties.setProperty("mail.smtp.host", host);

      // Get the default Session object.
      Session session = Session.getDefaultInstance(properties);

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      try {
         // Create a default MimeMessage object.
         MimeMessage message = new MimeMessage(session);

         // Set From: header field of the header.
         message.setFrom(new InternetAddress(from));

         // Set To: header field of the header.
         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

         // Set Subject: header field
         message.setSubject("This is the Subject Line!");

         // Now set the actual message
         message.setText("This is actual message");

         // Send message
         Transport.send(message);
         String title = "Send Email";
         String res = "Sent message successfully....";
         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 align = \"center\">" + res + "</p>\n" +
               "</body>
            </html>"
         );
      } catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}

现在让我们编译上述 servlet,并在 web.xml 中创建以下项

Now let us compile the above servlet and create the following entries in web.xml

....
 <servlet>
   <servlet-name>SendEmail</servlet-name>
   <servlet-class>SendEmail</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>SendEmail</servlet-name>
   <url-pattern>/SendEmail</url-pattern>
</servlet-mapping>
....

现在使用 URL [role="bare"] [role="bare"]http://localhost:8080/SendEmail 调用此 servlet,它将向给定的电子邮件 ID abcd@gmail.com 发送一封电子邮件,并会显示以下响应 −

Now call this servlet using URL [role="bare"]http://localhost:8080/SendEmail which would send an email to given email ID abcd@gmail.com and would display following response −

Send Email
Sent message successfully....

如果您要向多个收件人发送电子邮件,则将使用以下方法指定多个电子邮件 ID −

If you want to send an email to multiple recipients then following methods would be used to specify multiple email IDs −

void addRecipients(Message.RecipientType type, Address[] addresses)
throws MessagingException

以下是参数说明 −

Here is the description of the parameters −

  1. type − This would be set to TO, CC or BCC. Here CC represents Carbon Copy and BCC represents Black Carbon Copy. Example Message.RecipientType.TO

  2. addresses − This is the array of email ID. You would need to use InternetAddress() method while specifying email IDs.

Send an HTML Email

以下示例演示从您的计算机发送一封 HTML 电子邮件。这里假设您的 localhost 已连接到互联网并能够发送电子邮件。同时,请确保 CLASSPATH 中存在 Java Email API 包和 JAF 包中的所有 jar 文件。

Here is an example to send an HTML email from your machine. Here it is assumed that your localhost is connected to the internet and capable enough to send an email. At the same time, make sure all the jar files from Java Email API package and JAF package are available in CLASSPATH.

这个示例与之前的示例非常类似,只不过这里我们使用 setContent() 方法设置内容,其第二个参数为“text/html”,用于指定邮件中包含 HTML 内容。

This example is very similar to previous one, except here we are using setContent() method to set content whose second argument is "text/html" to specify that the HTML content is included in the message.

使用这个示例,你可以发送任意长度的 HTML 内容。

Using this example, you can send as big as HTML content you like.

// File Name SendEmail.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class SendEmail extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Recipient's email ID needs to be mentioned.
      String to = "abcd@gmail.com";

      // Sender's email ID needs to be mentioned
      String from = "web@gmail.com";

      // Assuming you are sending email from localhost
      String host = "localhost";

      // Get system properties
      Properties properties = System.getProperties();

      // Setup mail server
      properties.setProperty("mail.smtp.host", host);

      // Get the default Session object.
      Session session = Session.getDefaultInstance(properties);

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      try {

         // Create a default MimeMessage object.
         MimeMessage message = new MimeMessage(session);

         // Set From: header field of the header.
         message.setFrom(new InternetAddress(from));

         // Set To: header field of the header.
         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
         // Set Subject: header field
         message.setSubject("This is the Subject Line!");

         // Send the actual HTML message, as big as you like
         message.setContent("<h1>This is actual message</h1>", "text/html" );

         // Send message
         Transport.send(message);
         String title = "Send Email";
         String res = "Sent message successfully....";
         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 align = \"center\">" + res + "</p>\n" +
               "</body>
            </html>"
         );
      } catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}

编译并运行上述 servlet,以便在给定的电子邮件 ID 上发送 HTML 邮件。

Compile and run the above servlet to send HTML message on a given email ID.

Send Attachment in Email

以下示例演示从您的计算机发送带有附件的电子邮件。这里假设您的 localhost 已连接到互联网并能够发送电子邮件。

Here is an example to send an email with attachment from your machine. Here it is assumed that your localhost is connected to the internet and capable enough to send an email.

// File Name SendEmail.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class SendEmail extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Recipient's email ID needs to be mentioned.
      String to = "abcd@gmail.com";

      // Sender's email ID needs to be mentioned
      String from = "web@gmail.com";

      // Assuming you are sending email from localhost
      String host = "localhost";

      // Get system properties
      Properties properties = System.getProperties();

      // Setup mail server
      properties.setProperty("mail.smtp.host", host);

      // Get the default Session object.
      Session session = Session.getDefaultInstance(properties);

	  // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      try {
         // Create a default MimeMessage object.
         MimeMessage message = new MimeMessage(session);

         // Set From: header field of the header.
         message.setFrom(new InternetAddress(from));

         // Set To: header field of the header.
         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

         // Set Subject: header field
         message.setSubject("This is the Subject Line!");

         // Create the message part
         BodyPart messageBodyPart = new MimeBodyPart();

         // Fill the message
         messageBodyPart.setText("This is message body");

         // Create a multipar message
         Multipart multipart = new MimeMultipart();

         // Set text message part
         multipart.addBodyPart(messageBodyPart);

         // Part two is attachment
         messageBodyPart = new MimeBodyPart();
         String filename = "file.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // Send the complete message parts
         message.setContent(multipart );

         // Send message
         Transport.send(message);
         String title = "Send Email";
         String res = "Sent message successfully....";
         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 align = \"center\">" + res + "</p>\n" +
               "</body>
            </html>"
         );
      } catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}

编译并运行上述 servlet,以便将一个文件作为附件与邮件一起发送到给定的电子邮件 ID。

Compile and run above servlet to send a file as an attachment along with a message on a given email ID.

User Authentication Part

如果需要向电子邮件服务器提供用户 ID 和密码以用于身份验证目的,则您可以按如下方式设置这些属性 −

If it is required to provide user ID and Password to the email server for authentication purpose then you can set these properties as follows −

 props.setProperty("mail.user", "myuser");
 props.setProperty("mail.password", "mypwd");

其余的电子邮件发送机制如下所述。

Rest of the email sending mechanism would remain as explained above.

Servlets - Packaging

涉及 WEB-INF 子目录的 Web 应用程序结构对于所有 Java Web 应用程序都是标准的,并由 servlet API 规范指定。给定顶层目录名称为 myapp。这个目录结构看起来像这样 -

The web application structure involving the WEB-INF subdirectory is standard to all Java web applications and specified by the servlet API specification. Given a top-level directory name of myapp. Here is how this directory structure looks like −

/myapp
   /images
   /WEB-INF
      /classes
      /lib

WEB-INF 子目录包含应用程序的部署描述符,名为 web.xml。所有 HTML 文件都应保存在顶层目录(即 myapp)中。对于管理员用户,您会发现 ROOT 目录作为父目录。

The WEB-INF subdirectory contains the application’s deployment descriptor, named web.xml. All the HTML files should be kept in the top-level directory which is myapp. For admin user, you would find ROOT directory as parent directory.

Creating Servlets in Packages

WEB-INF/classes 目录包含所有 servlet 类和其他类文件,其结构与其包名称相匹配。例如,如果您有 com.myorg.MyServlet 的完全限定类名,那么该 servlet 类必须位于以下目录中 -

The WEB-INF/classes directory contains all the servlet classes and other class files, in a structure that matches their package name. For example, If you have a fully qualified class name of com.myorg.MyServlet, then this servlet class must be located in the following directory −

/myapp/WEB-INF/classes/com/myorg/MyServlet.class

以下示例使用包名为 com.myorg 创建 MyServlet 类

Following is the example to create MyServlet class with a package name com.myorg

// Name your package
package com.myorg;

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

public class MyServlet 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.
   }
}

Compiling Servlets in Packages

编译包中提供的类并没有什么不同。最简单的办法是将您的 Java 文件保存在完全限定的路径中,如上所述,该类将保存在 com.myorg 中。还需要将此目录添加到 CLASSPATH 中。

There is nothing much different to compile a class available in package. The simplest way is to keep your java file in fully qualified path, as mentioned above class would be kept in com.myorg. You would also need to add this directory in CLASSPATH.

假设您的环境已正确设置,请转到 <Tomcat-installationdirectory> /webapps/ROOT/WEB-INF/classes 目录并按如下方式编译 MyServlet.java

Assuming your environment is setup properly, go in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes directory and compile MyServlet.java as follows

$ javac MyServlet.java

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

If the servlet depends on any other libraries, you have to include those JAR files on your CLASSPATH as well. I have included only servlet-api.jar JAR file because I’m not using any other library in Hello World program.

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

This command line uses the built-in javac compiler that comes with the Sun Microsystems Java Software Development Kit (JDK). For this command to work properly, you have to include the location of the Java SDK that you are using in the PATH environment variable.

如果一切顺利,上述编译会在同一目录中生成 MyServlet.class 文件。下一节将说明如何将已编译 servlet 部署到生产中。

If everything goes fine, above compilation would produce MyServlet.class file in the same directory. Next section would explain how a compiled servlet would be deployed in production.

Packaged Servlet Deployment

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

By default, a servlet application is located at the path <Tomcat-installationdirectory>/webapps/ROOT and the class file would reside in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes.

如果您有 com.myorg.MyServlet 的完全限定类名,那么此 servlet 类必须位于 WEB-INF/classes/com/myorg/MyServlet.class 中,并且您需要在位于 <Tomcat 安装目录>/webapps/ROOT /WEB-INF/ 中的 web.xml 文件中创建以下条目:

If you have a fully qualified class name of com.myorg.MyServlet, then this servlet class must be located in WEB-INF/classes/com/myorg/MyServlet.class and you would need to create following entries in web.xml file located in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/

<servlet>
   <servlet-name>MyServlet</servlet-name>
   <servlet-class>com.myorg.MyServlet</servlet-class>
</servlet>

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

上述条目将创建标签中可用的 <web-app>…​</web-app> web.xml 文件内。此表格中可能已经存在各种条目,但不必担心。

Above entries to be created inside <web-app>…​</web-app> tags available in web.xml file. There could be various entries in this table already available, but never mind.

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

You are almost done, now let us start tomcat server using <Tomcat-installationdirectory>\bin\startup.bat (on windows) or <Tomcat-installationdirectory>/bin/startup.sh (on Linux/Solaris etc.) and finally type http://localhost:8080/MyServlet in browser’s address box. If everything goes fine, you would get following result −

Hello World

Servlets - Debugging

测试/调试 servlet 总是一件困难的事情。servlet 往往涉及大量客户端/服务器交互,因此错误可能很频繁,但难以重现。

It is always difficult to testing/debugging a servlets. Servlets tend to involve a large amount of client/server interaction, making errors likely but hard to reproduce.

以下是一些技巧和建议,可以帮助您进行调试。

Here are a few hints and suggestions that may aid you in your debugging.

System.out.println()

System.out.println() 易于用作标记,以测试程序的某个部分是否正在执行。我们还可以打印出变量值。此外 −

System.out.println() is easy to use as a marker to test whether a certain piece of code is being executed or not. We can print out variable values as well. Additionally −

  1. Since the System object is part of the core Java objects, it can be used everywhere without the need to install any extra classes. This includes Servlets, JSP, RMI, EJB’s, ordinary Beans and classes, and standalone applications.

  2. Stopping at breakpoints technique stops the normal execution hence takes more time. Whereas writing to System.out doesn’t interfere much with the normal execution flow of the application, which makes it very valuable when timing is crucial.

以下是如何使用 System.out.println() 的语法 −

Following is the syntax to use System.out.println() −

System.out.println("Debugging message");

通过上述语法生成的所有消息都将记录在 Web 服务器日志文件中。

All the messages generated by above syntax would be logged in web server log file.

Message Logging

使用标准日志方法记录所有调试、警告和错误消息始终是一个好主意。我使用 log4J 记录所有消息。

It is always great idea to use proper logging method to log all the debug, warning and error messages using a standard logging method. I use log4J to log all the messages.

Servlet API 还提供了一种通过使用 log() 方法输出信息更简单的方法,如下所示 −

The Servlet API also provides a simple way of outputting information by using the log() method as follows −

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

public class ContextLog extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, java.io.IOException {

      String par = request.getParameter("par1");

      //Call the two ServletContext.log methods
      ServletContext context = getServletContext( );

      if (par == null || par.equals(""))
         //log version with Throwable parameter
         context.log("No message received:", new IllegalStateException("Missing parameter"));
      else
         context.log("Here is the visitor's message: " + par);

      response.setContentType("text/html");
      java.io.PrintWriter out = response.getWriter( );
      String title = "Context Log";
      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" +
               "<h2 align = \"center\">Messages sent</h2>\n" +
            "</body>
         </html>"
      );
   } //doGet
}

ServletContext 将其文本消息记录到 servlet 容器的日志文件中。在 Tomcat 中,这些日志位于 <Tomcat 安装目录>/logs。

The ServletContext logs its text messages to the servlet container’s log file. With Tomcat these logs are found in <Tomcat-installation-directory>/logs.

日志文件确实提示了新出现的错误或问题的发生频率。因此,在通常不应该发生的异常的 catch 子句中使用 log() 函数效果不错。

The log files do give an indication of new emerging bugs or the frequency of problems. For that reason it’s good to use the log() function in the catch clause of exceptions which should normally not occur.

Using JDB Debugger

您可以使用与用于调试 applet 或应用程序相同的 jdb 命令来调试 serlet。

You can debug servlets with the same jdb commands you use to debug an applet or an application.

要调试 serlet,我们调试 sun.servlet.http.HttpServer,并在 HttpServer 响应来自浏览器 HTTP 请求执行 servlet 时仔细观察行为。这与调试小程序非常相似。不同之处在于,对于小程序,要调试的实际程序是 sun.applet.AppletViewer。

To debug a servlet, we debug sun.servlet.http.HttpServer and carefully watch as HttpServer executes servlets in response to HTTP requests made from browser. This is very similar to how applets are debugged. The difference is that with applets, the actual program being debugged is sun.applet.AppletViewer.

大多数调试器通过自动了解如何调试小程序隐藏此详细信息。直到它们对 servlet 执行相同的操作,您才必须通过执行以下操作帮助您的调试器 −

Most debuggers hide this detail by automatically knowing how to debug applets. Until they do the same for servlets, you have to help your debugger by doing the following −

  1. Set your debugger’s classpath so that it can find sun.servlet.http.Http-Server and associated classes.

  2. Set your debugger’s classpath so that it can also find your servlets and support classes, typically server_root/servlets and server_root/classes.

您通常不希望将 server_root/servlets 放入类路径,因为它会禁用 servlet 重新加载。但是,此包含项对调试很有用。它允许您的调试器在 HttpServer 中的自定义 servlet 加载器加载 servlet 之前在 servlet 中设置断点。

You normally wouldn’t want server_root/servlets in your classpath because it disables servlet reloading. This inclusion, however, is useful for debugging. It allows your debugger to set breakpoints in a servlet before the custom servlet loader in HttpServer loads the servlet.

设置好正确的类路径后,开始调试 sun.servlet.http.HttpServer。您可以在您想要调试的任何 servlet 中设置断点,然后使用网络浏览器向 HttpServer 发出对给定 servlet 的请求([role="bare"] [role="bare"]http://localhost:8080/servlet/ServletToDebug )。您应该看到执行在您的断点处停止。

Once you have set the proper classpath, start debugging sun.servlet.http.HttpServer. You can set breakpoints in whatever servlet you’re interested in debugging, then use a web browser to make a request to the HttpServer for the given servlet ([role="bare"]http://localhost:8080/servlet/ServletToDebug). You should see execution being stopped at your breakpoints.

Using Comments

代码中的注释可以通过多种方式帮助调试过程。注释可以在调试过程中的许多其他方式中使用。

Comments in your code can help the debugging process in various ways. Comments can be used in lots of other ways in the debugging process.

Servlet 使用 Java 注释,并且可以使用单行(// …​)和多行(/* …​ */)注释来临时删除 Java 代码的部分。如果错误消失了,请仔细查看您刚刚注释的代码并找出问题。

The Servlet uses Java comments and single line (// …​) and multiple line (/* …​ */) comments can be used to temporarily remove parts of your Java code. If the bug disappears, take a closer look at the code you just commented and find out the problem.

Client and Server Headers

有时,当 servlet 未按预期运行时,查看原始 HTTP 请求和响应非常有用。如果您熟悉 HTTP 的结构,您可以读取请求和响应,并确切地了解那些标头正在做什么。

Sometimes when a servlet doesn’t behave as expected, it’s useful to look at the raw HTTP request and response. If you’re familiar with the structure of HTTP, you can read the request and response and see exactly what exactly is going with those headers.

Important Debugging Tips

此处列出了一些有关 servlet 调试的其他调试提示 −

Here is a list of some more debugging tips on servlet debugging −

  1. Remember that server_root/classes doesn’t reload and that server_root/servlets probably does.

  2. Ask a browser to show the raw content of the page it is displaying. This can help identify formatting problems. It’s usually an option under the View menu.

  3. Make sure the browser isn’t caching a previous request’s output by forcing a full reload of the page. With Netscape Navigator, use Shift-Reload; with Internet Explorer use Shift-Refresh.

  4. Verify that your servlet’s init() method takes a ServletConfig parameter and calls super.init(config) right away.

Servlets - Internationalization

在我们继续之前,让我解释三个重要术语 −

Before we proceed, let me explain three important terms −

  1. Internationalization (i18n) − This means enabling a web site to provide different versions of content translated into the visitor’s language or nationality

  2. Localization (l10n) − This means adding resources to a web site to adapt to a particular geographical or cultural region.

  3. locale − This is a particular cultural or geographical region. It is usually referred to as a language symbol followed by a country symbol which is separated by an underscore. For example "en_US" represents English locale for US.

在构建全球网站时,有许多事项需要照顾到。本教程不会为您提供这方面的完整详细信息,但会为您提供一个很好的示例,说明如何向互联网社区以不同的语言提供您的网页,方法是区分他们的位置,即语言环境。

There are number of items which should be taken care while building up a global website. This tutorial would not give you complete detail on this but it would give you a good example on how you can offer your web page in different languages to internet community by differentiating their location i.e. locale.

servlet 可以根据请求者的语言环境挑选网站的适当版本,并根据当地语言、文化和要求提供适当的网站版本。以下是返回 Locale 对象的请求对象的方法。

A servlet can pickup appropriate version of the site based on the requester’s locale and provide appropriate site version according to the local language, culture and requirements. Following is the method of request object which returns Locale object.

java.util.Locale request.getLocale()

Detecting Locale

以下是您可以用来检测请求者的位置、语言和语言环境的重要语言环境方法。以下所有方法都显示了请求者的浏览器中设置的国家名称和语言名称。

Following are the important locale methods which you can use to detect requester’s location, language and of course locale. All the below methods display country name and language name set in requester’s browser.

Sr.No.

Method & Description

1

String getCountry() This method returns the country/region code in upper case for this locale in ISO 3166 2-letter format.

2

String getDisplayCountry() This method returns a name for the locale’s country that is appropriate for display to the user.

3

String getLanguage() This method returns the language code in lower case for this locale in ISO 639 format.

4

String getDisplayLanguage() This method returns a name for the locale’s language that is appropriate for display to the user.

5

String getISO3Country() This method returns a three-letter abbreviation for this locale’s country.

6

String getISO3Language() This method returns a three-letter abbreviation for this locale’s language.

Example

此示例显示如何为请求显示语言和关联的国家/地区 −

This example shows how you display a language and associated country for a request −

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Locale;

public class GetLocale extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      //Get the client's Locale
      Locale locale = request.getLocale();
      String language = locale.getLanguage();
      String country = locale.getCountry();

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      String title = "Detecting Locale";
      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\">" + language + "</h1>\n" +
               "<h2 align = \"center\">" + country + "</h2>\n" +
         "</body>
         </html>"
      );
   }
}

Languages Setting

Servlet 可以输出以西欧语言(如英语、西班牙语、德语、法语、意大利语、荷兰语等)编写的页面。此处设置 ContentLanguage 标题以正确显示所有字符非常重要。

A servlet can output a page written in a Western European language such as English, Spanish, German, French, Italian, Dutch etc. Here it is important to set ContentLanguage header to display all the characters properly.

第二点是使用 HTML 实体显示所有特殊字符,例如,“ñ”代表“ñ”,而“¡”代表“¡”,如下所示:

Second point is to display all the special characters using HTML entities, For example, "ñ" represents "ñ", and "¡" represents "¡" as follows:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Locale;

public class DisplaySpanish extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      // Set spanish language code.
      response.setHeader("Content-Language", "es");

      String title = "En Espa&ntilde;ol";
      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>" + "En Espa&ntilde;ol:" + "</h1>\n" +
               "<h1>" + "&iexcl;Hola Mundo!" + "</h1>\n" +
            "</body>
         </html>"
      );
   }
}

Locale Specific Dates

可使用 java.text.DateFormat 类及其静态 getDateTimeInstance() 方法来格式化特定于区域设置的日期和时间。以下示例显示如何格式化特定于给定区域设置的日期 −

You can use the java.text.DateFormat class and its static getDateTimeInstance() method to format date and time specific to locale. Following is the example which shows how to format dates specific to a given locale −

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Locale;
import java.text.DateFormat;
import java.util.Date;

public class DateLocale extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      //Get the client's Locale
      Locale locale = request.getLocale( );
      String date = DateFormat.getDateTimeInstance(DateFormat.FULL,
         DateFormat.SHORT, locale).format(new Date( ));

      String title = "Locale Specific Dates";
      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\">" + date + "</h1>\n" +
            "</body>
         </html>"
      );
   }
}

Locale Specific Currency

可使用 java.txt.NumberFormat 类及其静态 getCurrencyInstance() 方法来格式化数字,如 long 或 double 类型,以区域设置特定的货币。以下示例显示如何格式化特定于给定区域设置的货币 −

You can use the java.txt.NumberFormat class and its static getCurrencyInstance() method to format a number, such as a long or double type, in a locale specific currency. Following is the example which shows how to format currency specific to a given locale −

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Locale;
import java.text.NumberFormat;
import java.util.Date;

public class CurrencyLocale extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      //Get the client's Locale
      Locale locale = request.getLocale( );
      NumberFormat nft = NumberFormat.getCurrencyInstance(locale);
      String formattedCurr = nft.format(1000000);

      String title = "Locale Specific Currency";
      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\">" + formattedCurr + "</h1>\n" +
            "</body>
         </html>"
      );
   }
}

Locale Specific Percentage

可使用 java.txt.NumberFormat 类及其静态 getPercentInstance() 方法来获取区域设置特定的百分比。以下示例显示如何格式化特定于给定区域设置的百分比 −

You can use the java.txt.NumberFormat class and its static getPercentInstance() method to get locale specific percentage. Following is the example which shows how to format percentage specific to a given locale −

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Locale;
import java.text.NumberFormat;
import java.util.Date;

public class PercentageLocale extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      //Get the client's Locale
      Locale locale = request.getLocale( );
      NumberFormat nft = NumberFormat.getPercentInstance(locale);
      String formattedPerc = nft.format(0.51);

      String title = "Locale Specific Percentage";
      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\">" + formattedPerc + "</h1>\n" +
            "</body>
         </html>"
      );
   }
}

Servlets - Annotations

到目前为止,您已了解 Servlet 如何使用部署描述符(web.xml 文件)将您的应用程序部署到 Web 服务器中。Servlet API 3.0 引入了名为 javax.servlet.annotation 的新包。它提供可用于注释 Servlet 类的注释类型。如果您使用注释,则不需要部署描述符 (web.xml)。但您应该使用 tomcat7 或更高版本的 tomcat。

So far, you have learnt how Servlet uses the deployment descriptor (web.xml file) for deploying your application into a web server. Servlet API 3.0 has introduced a new package called javax.servlet.annotation. It provides annotation types which can be used for annotating a servlet class. If you use annotation, then the deployment descriptor (web.xml) is not required. But you should use tomcat7 or any later version of tomcat.

注释可替换 Web 部署描述符文件 (web.xml) 中等效的 XML 配置,如 Servlet 声明和 Servlet 映射。Servlet 容器将在部署时处理带注释的类。

Annotations can replace equivalent XML configuration in the web deployment descriptor file (web.xml) such as servlet declaration and servlet mapping. Servlet containers will process the annotated classes at deployment time.

Servlet 3.0 中引入的注释类型有:

The annotation types introduced in Servlet 3.0 are −

Sr.No.

Annotation & Description

1

@WebServlet To declare a servlet.

2

@WebInitParam To specify an initialization parameter.

3

@WebFilter To declare a servlet filter.

4

@WebListener To declare a WebListener

5

*@HandlesTypes * To declare the class types that a ServletContainerInitializer can handle.

6

@HttpConstraint This annotation is used within the ServletSecurity annotation to represent the security constraints to be applied to all HTTP protocol methods for which a corresponding HttpMethodConstraint element does NOT occur within the ServletSecurity annotation.

7

*@HttpMethodConstraint * This annotation is used within the ServletSecurity annotation to represent security constraints on specific HTTP protocol messages.

8

*@MultipartConfig * Annotation that may be specified on a Servlet class, indicating that instances of the Servlet expect requests that conform to the multipart/form-data MIME type.

9

@ServletSecurity This annotation is used on a Servlet implementation class to specify security constraints to be enforced by a Servlet container on HTTP protocol messages.

此处我们已详细讨论了一些注解。

Here we have discussed some of the Annotations in detail.

@WebServlet

@WebServlet用于使用容器声明Servlet的配置。下表包含用于WebServlet注解的属性列表。

The @WebServlet is used to declare the configuration of a Servlet with a container. The following table contains the list of attributes used for WebServlet annotation.

Sr.No.

Attribute & Description

1

String name Name of the Servlet

2

String[] value Array of URL patterns

3

String[] urlPatterns Array of URL patterns to which this Filter applies

4

Int loadOnStartup The integer value gives you the startup ordering hint

5

WebInitParam[] initParams Array of initialization parameters for this Servlet

6

Boolean asyncSupported Asynchronous operation supported by this Servlet

7

String smallIcon Small icon for this Servlet, if present

8

String largeIcon Large icon for this Servlet, if present

9

String description Description of this Servlet, if present

10

String displayName Display name of this Servlet, if present

注解的 valueurlPattern 属性中至少必须声明一个URL模式,但不能同时声明两个。

At least one URL pattern MUST be declared in either the value or urlPattern attribute of the annotation, but not both.

建议在URL模式是唯一要设置的属性时使用 value 属性,否则应使用 urlPattern 属性。

The value attribute is recommended for use when the URL pattern is the only attribute being set, otherwise the urlPattern attribute should be used.

Example

以下示例介绍如何使用@WebServlet注解。它是一个简单的servlet,用于显示文本 Hello Servlet

The following example describes how to use @WebServlet annotation. It is a simple servlet that displays the text Hello Servlet.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(value = "/Simple")
public class Simple extends HttpServlet {

   private static final long serialVersionUID = 1L;

   protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.print("<html><body>");
      out.print("<h3>Hello Servlet</h3>");
      out.print("</body></html>");
   }
}

以通常的方式编译 Simple.java ,并将你的类文件放入<Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes。

Compile Simple.java in the usual way and put your class file in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes.

现在只需运行 [role="bare"] [role="bare"]http://localhost:8080/Simple 即可尝试调用任何 servlet。您将在网页上看到以下输出。

Now try to call any servlet by just running [role="bare"]http://localhost:8080/Simple. You will see the following output on the web page.

Hello servlet

@WebInitParam

@WebInitParam 注解用于指定 Servlet 或 Filter 的初始化参数。它在 WebFilter 或 WebSevlet 注解中使用。下表包含用于 WebInitParam 注解的属性列表。

The @WebInitParam annotation is used for specifying an initialization parameter for a Servlet or a Filter. It is used within a WebFilter or WebSevlet annotations. The following table contains the list of attributes used for WebInitParam annotation.

Sr.No.

Attribute & Description

1

String name Name of the initialization parameter

2

String value Value of the initialization parameter

3

String description Description of the initialization parameter

Example

以下示例介绍如何将 @WeInitParam 注解与 @WebServlet 注解搭配使用。这是一个简单的 servlet,它显示文本 Hello Servlet 和字符串值 Hello World! ,它们取自 init 参数。

The following example describes how to use @WeInitParam annotation along with @WebServlet annotation. It is a simple servlet that displays the text Hello Servlet and the string value Hello World! which are taken from the init parameters.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(value = "/Simple", initParams = {
   @WebInitParam(name = "foo", value = "Hello "),
   @WebInitParam(name = "bar", value = " World!")
})
public class Simple extends HttpServlet {

   private static final long serialVersionUID = 1L;

   protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.print("<html><body>");
      out.print("<h3>Hello Servlet</h3>");
      out.println(getInitParameter("foo"));
      out.println(getInitParameter("bar"));
      out.print("</body></html>");
   }
}

以通常的方式编译 Simple.java ,然后将你的类文件放在 <Tomcat-installationdirectory>;/webapps/ROOT/WEB-INF/classes 中。

Compile Simple.java in the usual way and put your class file in <Tomcat-installationdirectory>;/webapps/ROOT/WEB-INF/classes.

现在只需运行 [role="bare"] [role="bare"]http://localhost:8080/Simple 即可尝试调用任何 servlet。您将在网页上看到以下输出。

Now try to call any servlet by just running [role="bare"]http://localhost:8080/Simple. You will see the following output on the web page.

Hello Servlet

Hello World!

@Webfilter

这是用于声明 servlet 过滤器的注释。它在部署时由容器处理,并向指定的 URL 模式、servlet 和分派器类型应用相应的过滤器。

This is the annotation used to declare a servlet filter. It is processed by the container at deployment time, and the corresponding filter applied to the specified URL patterns, servlets, and dispatcher types.

@WebFilter 注解在 Web 应用程序中定义了一个过滤器。此注释指定在类上,并包含有关声明的过滤器的元数据。带注释的过滤器必须至少指定一个 URL 模式。下表列出了用于 WebFilter 注解的属性。

The @WebFilter annotation defines a filter in a web application. This annotation is specified on a class and contains metadata about the filter being declared. The annotated filter must specify at least one URL pattern. The following table lists the attributes used for WebFilter annotation.

Sr.No.

Attribute & Description

1

String filterName Name of the filter

2

* String[] urlPatterns * Provides array of values or urlPatterns to which the filter applies

3

DispatcherType[] dispatcherTypes Specifies the types of dispatcher (Request/Response) to which the filter applies

4

String[] servletNames Provides an array of servlet names

5

String displayName Name of the filter

6

String description Description of the filter

7

WebInitParam[] initParams Array of initialization parameters for this filter

8

Boolean asyncSupported Asynchronous operation supported by this filter

9

String smallIcon Small icon for this filter, if present

10

String largeIcon Large icon for this filter, if present

Example

以下示例描述了如何使用 @WebFilter 注解。它是一个简单的 LogFilter,显示控制台上的 Init-param test-param 值和当前时间戳。这意味着过滤器在请求和响应之间发挥接口层的作用。这里我们为 urlPattern 使用了“/*”。这意味着此过滤器适用于所有 servlet。

The following example describes how to use @WebFilter annotation. It is a simple LogFilter that displays the value of Init-param test-param and the current time timestamp on the console. That means, the filter works like an interface layer between the request and the response. Here we use "/*" for urlPattern. It means, this filter is applicable for all the servlets.

import java.io.IOException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.*;
import java.util.*;

// Implements Filter class

@WebFilter(urlPatterns = {"/*"}, initParams = {
   @WebInitParam(name = "test-param", value = "Initialization Paramter")})
public class LogFilter implements Filter {

   public void init(FilterConfig config) throws ServletException {
      // Get init parameter
      String testParam = config.getInitParameter("test-param");

      //Print the init parameter
      System.out.println("Test Param: " + testParam);
   }

   public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

      // Log the current timestamp.
      System.out.println("Time " + new Date().toString());

      // Pass request back down the filter chain
      chain.doFilter(request,response);
   }

   public void destroy( ) {
      /* Called before the Filter instance is removed
      from service by the web container*/
   }
}

以通常的方式编译 Simple.java ,并将你的类文件放入<Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes。

Compile Simple.java in the usual way and put your class file in <Tomcat-installationdirectory>/webapps/ROOT/WEB-INF/classes.

现在只需运行 [role="bare"] [role="bare"]http://localhost:8080/Simple 即可尝试调用任何 servlet。您将在网页上看到以下输出。

Now try to call any servlet by just running [role="bare"]http://localhost:8080/Simple. You will see the following output on the web page.

Hello Servlet

Hello World!

现在,打开 servlet 控制台。在那里,您将看到 init 参数 testparamcurrent timestamp 的值以及 servlet 通知消息。

Now, open the servlet console. There, you will find the value of the init parameter testparam and the current timestamp along with servlet notification messages.