Servlet

Table of Contents

1. Java Servlets 简介

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

Java Servlets often serve the same purpose as programs implemented using the Common Gateway Interface (CGI).

Servlets could in principle communicate over any client-server protocol, but they are most often used with the HTTP protocol. Thus "servlet" is often used as shorthand for "HTTP servlet".

参考:
Java™ Servlet Programming: https://docstore.mik.ua/orelly/java-ent/servlet/index.htm
The Java EE 6 Tutorial, Chapter 15 Java Servlet Technology: http://docs.oracle.com/javaee/6/tutorial/doc/bnafd.html

1.1. Servlet Tasks

Servlets perform the following major tasks:

  • 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.
  • 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.
  • 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.
  • 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.
  • 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 - Overview: http://www.tutorialspoint.com/servlets/servlets_overview.htm

1.2. Servlet container (web container)

To deploy and run a servlet, a web container must be used. A web container (also known as a servlet container) is essentially the component of a web server that interacts with the servlets. The web container is responsible for managing the lifecycle of servlets, mapping a URL to a particular servlet and ensuring that the URL requester has the correct access rights.

1.3. Servlet version history

Table 1: Servlet API history
Servlet API version Released Platform Important Changes
Servlet 4.0 Sep 2017 Java EE 8 HTTP/2
Servlet 3.1 May 2013 Java EE 7 Non-blocking I/O, HTTP protocol upgrade mechanism (WebSocket)
       
Servlet 3.0 December 2009 Java EE 6, Java SE 6 Pluggability, Ease of development, Async Servlet, Security, File Uploading
Servlet 2.5 September 2005 Java EE 5, Java SE 5 Requires Java SE 5, supports annotation
Servlet 2.4 November 2003 J2EE 1.4, J2SE 1.3 web.xml uses XML Schema
Servlet 2.3 August 2001 J2EE 1.3, J2SE 1.2 Addition of Filter
Servlet 2.2 August 1999 J2EE 1.2, J2SE 1.2 Becomes part of J2EE, introduced independent web applications in .war files
Servlet 2.1 November 1998 Unspecified First official specification, added RequestDispatcher, ServletContext
Servlet 2.0   JDK 1.1 Part of Java Servlet Development Kit 2.0
Servlet 1.0 June 1997    

参考:https://en.wikipedia.org/wiki/Java_servlet#History

Servert 3.0 新功能,可参考:
http://stackoverflow.com/questions/1638865/what-are-the-differences-between-servlet-2-5-and-3
http://javabeat.net/new-features-in-servlets-3-0/

2. Servlets Lifecycle

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:

  • The servlet is initialized by calling the init() method.
  • The servlet calls service() method to process a client's request.
  • The servlet is terminated by calling the destroy() method.
  • Finally, servlet is garbage collected by the garbage collector of the JVM.

Now let us discuss the life cycle methods in details.

参考:
http://www.tutorialspoint.com/servlets/servlets-life-cycle.htm
http://docs.oracle.com/javaee/6/tutorial/doc/bnafi.html

2.1. The service() method

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.

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

The service () method is called by the container and service method invokes doGe, 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.

2.2. Architecture Digram

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

  • First the HTTP requests coming to the server are delegated to the servlet container.
  • The servlet container loads the servlet before invoking the service() method.
  • 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.jpg

Figure 1: Servlet life-cycle

3. Servlets Example: Hello World

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.

下面演示一个简单的 servlet 实例(Hello World):

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

// Extend HttpServlet class
public class HelloWorld extends HttpServlet {

  private String message;

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

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

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

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

编译上面的 servlet 程序:

$ export CLASSPATH=/path/to/tomcat/lib/servlet-api.jar:${CLASSPATH}
$ javac HelloWorld.java
$ ls
HelloWorld.class  HelloWorld.java

说明:编译程序前,servlet-api.jar 应该配置到环境变量 CLASSPATH 中,否则会提示类似下面的错误:
package javax.servlet does not exist
package javax.servlet.http does not exist

可用下面步骤来部署上面编译好的 servlet 程序:
第 1 步,复制 HelloWorld.class 到<Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes
第 2 步,在配置文件<Tomcat-installation-directory>/webapps/ROOT/WEB-INF/web.xml 中的<web-app>...</web-app>之间增加下面内容:

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

第 3 步,运行脚本<Tomcat-installation-directory>/bin/startup.sh 启动 tomcat。
第 4 步,测试,用浏览器访问 http://localhost:8080/HelloWorld ,可看到下面内容:

servlet_helloworld.jpg

Figure 2: Servlet example: Hello World

参考:http://www.tutorialspoint.com/servlets/servlets-first-example.htm

4. Servlet Filters

A filter is an object that can transform the header and content (or both) of a request or response. Filters differ from web components in that filters usually do not themselves create a response. Instead, a filter provides functionality that can be "attached" to any kind of web resource. Consequently, a filter should not have any dependencies on a web resource for which it is acting as a filter; this way, it can be composed with more than one type of web resource.

The main tasks that a filter can perform are as follows:

  • Query the request and act accordingly.
  • Block the request-and-response pair from passing any further.
  • Modify the request headers and data. You do this by providing a customized version of the request.
  • Modify the response headers and data. You do this by providing a customized version of the response.
  • Interact with external resources.

Applications of filters include authentication, logging, image conversion, data compression, encryption, tokenizing streams, XML transformations, and so on.

Note that filters are not servlets. They do not implement and override HttpServlet methods such as doGet() or doPost(). Rather, a filter implements the methods of the javax.servlet.Filter interface. The methods are: init(), destroy(), doFilter().

Servlet Filter 工作原理如下:

servlet_filter.gif

Figure 3: Servlet Invocation with and without Filters

参考:
http://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html
http://docs.oracle.com/cd/B14504_01/dl/web/B10321_01/filters.htm

4.1. web.xml 中配置 filter

和配置 sevlet 类似,我们可以在 web.xml 的<web-app>...</web-app>之间配置 filter。如:

<filter>
   <filter-name>AuthenticationFilter</filter-name>
   <filter-class>com.xxx.servlet.filters.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>AuthenticationFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

上面例子中,所有请求都会先经过 AuthenticationFilter 的处理。

filter 简单实例可参考:http://www.tutorialspoint.com/servlets/servlets-writing-filters.htm

5. Event Listeners

The servlet specification includes the capability to track key events in your Web applications through event listeners. This functionality allows more efficient resource management and automated processing based on event status.

参考:http://docs.oracle.com/cd/B14099_19/web.1012/b14017/filters.htm#i1000654

5.1. Event Listeners 实例

下面例子摘自:https://www.mkyong.com/servlet/what-is-listener-servletcontextlistener-example/

首先,创建一个类。

package com.mkyong.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyAppServletContextListener implements ServletContextListener{

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
    System.out.println("ServletContextListener destroyed");
    }

    //Run this before web application is started
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
    }
}

然后,在 web.xml 中进行相关配置,例如:

<web-app ...>
  <listener>
    <listener-class>
       com.mkyong.listener.MyAppServletContextListener
    </listener-class>
  </listener>
</web-app>

启动 tomcat 后,会有类似下面的输出:

Dec 2, 2009 10:11:46 AM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.20

ServletContextListener started   <-------------- Your code here, before we application --->

Dec 2, 2009 10:11:46 AM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
//...
INFO: Server startup in 273 ms

6. Tips

6.1. Servlet 不是线程安全的

Servlet 是运行在 Servlet 容器中的,常用的 Tomcat、JBoss、WebLogic 都是 Servlet 容器,其生命周期是由容器来管理。Servlet 的生命周期通过 java.servlet.Servlet 接口中的 init(), service(), 和 destroy() 方法表示。Servlet 的生命周期有四个阶段:加载并实例化、初始化、请求处理、销毁。

当客户端第一次请求 Servlet 的时候,Tomcat 会根据 web.xml 配置文件实例化 Servlet。当又有一个客户端访问该 Servlet 的时候,不会再实例化该 Servlet,也就是多个线程在使用这个实例。

Serlvet 采用多线程来处理多个请求同时访问,Tomcat 容器维护了一个线程池来服务请求。线程池实际上是等待执行代码的一组线程叫做工作组线程(Worker Thread),Tomcat 容器使用一个调度线程(Dispatcher Thead)来管理工作组线程。

当容器收到一个 Servlet 请求,调度线程从线程池中选出一个工作组线程,将请求传递给该线程,然后由该线程来执行 Servlet 的 service() 方法。当这个线程正在执行的时候,容器收到另一个请求,调度线程将从线程池中选出另外一个工作组线程来服务这个新的请求,容器并不关心这个请求是否访问的是同一个 Servlet 还是另一个 Servlet。 当容器同时收到对同一个 Servlet的多个请求的时候,那这个Servlet的 service() 方法将在多线程中并发地执行。 所以,Servlet不是线程安全的。

Author: cig01

Created: <2015-11-15 Sun>

Last updated: <2018-10-31 Wed>

Creator: Emacs 27.1 (Org mode 9.4)