1. 程式人生 > >實驗說明Servlet的生命週期

實驗說明Servlet的生命週期

Servlet的生命週期

Servlet是執行在伺服器端的程式,它的執行狀態由Servlet容器(簡稱容器)來維護。

通常,在容器收到客戶對Servlet的請求時,容器會判斷這個Servlet是否為第一次被訪問,如果是第一次被訪問,則會建立一個Servlet例項同時呼叫該例項的init()方法,進行初始化。

每個Servlet只會被建立一個例項,同時也只會被初始化一次。然後將這個例項一直儲存在記憶體中,對所有的請求進行處理。預設的服務功能是呼叫與HTTP請求方法相應的do功能。同時,HttpServlet.service()方法會檢查請求方法是否呼叫了適當的處理方法。

最後,當伺服器關閉時,容器將會呼叫Servlet的destroy()方法清除Servlet例項。

我們下面用實驗看一下這個過程:

實驗驗證

首先,我們寫一個很簡單的JSP程式,我們通過JSP頁面來呼叫Servlet方法。我們在Tomcat安裝目錄下的webapps資料夾下新建一個ServletLife資料夾,進入該資料夾,寫一個index.jsp檔案,程式碼如下:

index.jsp

<%@ page contentType="text/html;charset=GBK" language="java" %>
<html>
  <head>
    <title>Show servlet life cycle</title
>
</head> <body> <center> <form action="ShowLifeCycle" name=form"> <input type="submit" value="SUBMIT"></form> </center> </body> </html>

這是一段很簡單的JSP程式,只為說明問題,整個程式只有一個提交表單的”submit”。

  • 程式碼第8行指定表單提交給ShowLifeCycle
  • 程式碼第9行建立一個“提交”

然後我們在我們建立的/ServletLife目錄下新建一個WEB-INF資料夾,進入WEB-INF資料夾,再建立一個classes資料夾。

接下來,建立Servlet.java,程式碼如下:

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

public class Servlet extends HttpServlet {
    private ServletConfig config;
    private static int counter = 0;

    public Servlet() {
        super();
        System.out.println("=== " + ++counter + " instances ===");
    }

    //初始化servlet
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.config = config;
        System.out.println("=== invoke init() ===" + new Date().toString());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("=== invoke doPost ===" + new Date().toString());
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("=== invoke doGet() ===" + new Date().toString());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.service(req, resp);
        System.out.println("=== invoke service ===");
    }

    @Override
    public void destroy() {
        System.out.println("=== invoke destroy() ===" + new Date().toString());
    }
}
  • 11行,定義一個類變數,用來記錄一共建立了幾個例項。
  • 13~16行,顯式地寫出建構函式,是為了打印出一共建立了多少個例項。
  • 18~24行,初始化函式。每次呼叫顯示”=== invoke init() ===”以及當前時間。
  • 26~28行,在doPost()方法中列印”=== invoke doPost ===”以及當前時間。
  • 30~32行,在doGet()方法中列印”=== invoke doGet ===”以及當前時間。
  • 34~38行,這裡我們重寫service()方法,只是為了在呼叫此方法的時候打印出””’ invoke service ===”以及當前時間。
  • 40~43行,在呼叫destroy()方法時,列印”=== invoke destroy() ===”以及當前時間。

將該java檔案編譯後的Servlet.class放到/WEB-INF/classes資料夾下。

然後在/WEB-INF資料夾下建立一個配置檔案web.xml:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <servlet>
            <servlet-name>LifeCycle</servlet-name>
            <servlet-class>Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LifeCycle</servlet-name>
        <url-pattern>/ShowLifeCycle</url-pattern>
    </servlet-mapping>
</web-app>

這個檔案主要來配置Servlet的。

接下來執行Tomcat,我們在Tomcat安裝目錄下的logs資料夾中找到剛剛生成(看修改日期的時間)的tomcat7-stdout.2016-03-15文字文件檔案,裡面會有一行剛剛列印的文字:

2016-03-15 20:04:53 Commons Daemon procrun stdout initialized

此時伺服器正常啟動。

然後我們在瀏覽器位址列輸入

localhost/8080/http://localhost:8080/ServletLife/index.jsp

只有一個submit按鈕:

submit

點選該按鈕,此時Servlet被請求,關閉重新開啟剛才的tomcat7-stdout.2016-03-15,此時內容如下:

2016-03-15 20:04:53 Commons Daemon procrun stdout initialized
=== 1 instances ===
=== invoke init() ===Tue Mar 15 20:10:20 CST 2016
=== invoke doGet() ===Tue Mar 15 20:10:20 CST 2016
=== invoke service ===
  • 第2行,當第一次收到該Servlet請求時,會呼叫該Servlet的例項方法,並建立1個例項。”=== 1 instances ===”;
  • 第3行,建立該例項後,呼叫Servlet的init()方法進行初始化操作;
  • 第4行,通過doGet()方法處理請求響應;
  • 第5行,在service()方法最後一行打印出”=== invoke service ===”,實際上,doGet()方法是由service()方法呼叫的。

接下來我們重新建立一個Servlet請求,開啟瀏覽器,重複以上過程,找到localhost/8080/ServletLife/index.jsp頁面,點選submit,然後重新開啟剛才的文字文件,內容如下:

2016-03-15 20:04:53 Commons Daemon procrun stdout initialized
=== 1 instances ===
=== invoke init() ===Tue Mar 15 20:10:20 CST 2016
=== invoke doGet() ===Tue Mar 15 20:10:20 CST 2016
=== invoke service ===
=== invoke doGet() ===Tue Mar 15 20:18:50 CST 2016
=== invoke service ===

新增加了6、7兩行。再次請求Servlet,並沒有新建一個Servlet例項,也沒有init過程,直接使用上次建立的例項來處理請求響應,doGet()方法被呼叫。

然後我們關閉Tomcat伺服器。重新開啟以上文字文件,內容如下:

2016-03-15 20:04:53 Commons Daemon procrun stdout initialized
=== 1 instances ===
=== invoke init() ===Tue Mar 15 20:10:20 CST 2016
=== invoke doGet() ===Tue Mar 15 20:10:20 CST 2016
=== invoke service ===
=== invoke doGet() ===Tue Mar 15 20:18:50 CST 2016
=== invoke service ===
=== invoke destroy() ===Tue Mar 15 20:22:43 CST 2016

destroy()方法被呼叫,清除Servlet例項。