天天看點

servlet相關(流程、原理、生命周期、HttpServlet)

一、什麼是servlet ?

Servlet本質上就是一個Java語言定義的接口,廣義的Servlet就是指實作了這個Servlet接口的類。一般指的就是後者。

Servlet執行個體的主要功能就是根據用戶端的請求,找到并調用服務端相關java代碼,完成對請求的處理和運算。

Servlet執行個體遵循了伺服器能夠識别的規則,伺服器會根據請求調用對應的servlet進行請求處理。

(1)Servlet執行個體,由Servlet容器建立,通常這個容器就是tomcat。

(2)Servlet是一個接口:位于javax.servlet包中。

二、Servlet實作步驟

具體實作一個Servlet的步驟如下:

  1. 建立普通的java類,并實作Servlet接口
  2. 重寫service方法,添加業務邏輯代碼
  3. 在webRoot下的WEB-INF檔案夾下的web.xml中配置Servlet及其映射
// 普通Java類實作Servlet接口
public class MyServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    // 添加業務邏輯代碼
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("MyServlet 的 service()方法");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}      
servlet相關(流程、原理、生命周期、HttpServlet)

<servlet-name>是指servlet的名稱,<servlet>标簽和<servlet-mapping>标簽中的<servlet-name>必須一緻。<servlet-class>是目前servlet的全限定類名,<url-pattern>是映射servlet的url。

servlet相關(流程、原理、生命周期、HttpServlet)
servlet相關(流程、原理、生命周期、HttpServlet)

三、Servlet生命周期

Servlet生命周期是指servlet執行個體的建立、初始化、服務執行、銷毀的整個過程。

這些流程都是web伺服器負責調用執行,程式員無法控制整個流程,但是程式員可以擷取到這些Servlet生命周期的時間點,在這些時間點上可以做些業務相關的操作。

了解Servlet的生命周期還要看下Servlet的源碼,源碼中對其生命周期中的主要節點都有相應的方法:

servlet相關(流程、原理、生命周期、HttpServlet)

整個方法調用的流程圖如下:

servlet相關(流程、原理、生命周期、HttpServlet)

當一個用戶端請求過來的時候,tomcat伺服器首先解析這個url,首先找到對應的應用app,然後根據/xxx去web.xml中根據配置資訊去找對應的servlet,找到對應的servlet後,若還沒有建立servlet執行個體就會建立一個該servlet執行個體,然後執行init()方法,service()方法,然後響應用戶端;若該servlet執行個體已存在,就隻會執行service()方法。當應用解除安裝的時候,會執行destory()方法銷毀這個servlet執行個體。

我們來示範一下:

public class MyServlet implements Servlet {

    public MyServlet(){
        System.out.println("create servlet !");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("initialize Servlet !");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("MyServlet's service() method");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy servlet!");
    }
}      

浏覽器輸入位址:

servlet相關(流程、原理、生命周期、HttpServlet)

檢視日志:

create servlet !
initialize Servlet !
MyServlet's service() method      

可以看出執行順序符合上面流程圖定義的順序,無參構造--》初始化--》service方法,但是沒有直接執行destroy銷毀方法,一個servlet執行個體隻會在服務停止時調用一次該方法。無參構造和初始化也隻會執行一次,若現在再次刷頁面,隻會執行service方法:

create servlet !
initialize Servlet !
MyServlet's service() method
MyServlet's service() method
MyServlet's service() method      

總結一下servlet的特征:

  1. servlet是單例多線程的,單例是指servlet的執行個體隻有一個,多線程是指每次用戶端的請求,web伺服器都會從線程池中配置設定一個工作線程去執行servlet的service()方法,線程安全。
  2. 預設情況下,servlet不會在服務啟動時執行個體化,即一個servlet執行個體的無參構造和初始化也隻會執行一次,且不會在服務啟動時執行,而是在第一次請求時執行,是以接到請求時會先檢查servlet執行個體是否已經存在
  3. 每次請求隻會執行一個service方法
  4. 一個servlet執行個體隻會在服務停止時調用一次該方法

四、HttpServlet

現在我們的請求都是基于HTTP協定的,是以應該專門為HTTP請求寫一個Servlet做為通用父類。

HttpServlet的工作流程如下:

  • 1.Web客戶向Servlet容器發出Http請求
  • 2.Servlet容器解析Web客戶的Http請求
  • 3.Servlet容器建立一個HttpRequest對象,在這個對象中封裝Http請求資訊
  • 4.Servlet容器建立一個HttpResponse對象
  • 5.Servlet容器調用HttpServlet的service方法,把HttpRequest和HttpResponse對象作為service方法的參數傳給HttpServlet對象,service()方法會判斷來自客服端的請求方式,根據不同請求方式調用不同方法,如果是get請求,則調用doGet()方法,如果是post請求,則調用doPost()方法
  • 6.HttpServlet調用HttpRequest的有關方法,擷取HTTP請求資訊
  • 7.HttpServlet調用HttpResponse的有關方法,生成響應資料
  • 8.Servlet容器把HttpServlet的響應結果傳給Web客戶

補充一:

JSP和Servlet有哪些相同點和不同點,他們之間的聯系是什麼?

JSP (JavaServer Pages)是Servlet技術的擴充,本質上是Servlet的簡易方式,更強調應用的外表表達。JSP編譯後是"類servlet"。Servlet和JSP最主要的不同點在于,Servlet的應用邏輯是在Java檔案中,并且完全從表示層中的HTML裡分離開來。而JSP的情況是Java和HTML可以組合成一個擴充名為.jsp的檔案。JSP側重于視圖,Servlet主要用于控制邏輯。

補充二:

  • genericservlet類提供了servlet接口的基本實作;
  • HttpServlet是GenericServlet的子類,又是在GenericServlet的基礎上做了增強;

補充三:

請求轉發與重定向差別

servlet API中forward() 與redirect()的差別? 

前者僅是容器中控制權的轉向,在用戶端浏覽器位址欄中不會顯示出轉向後的位址;後者則是完全的跳轉,浏覽器将會得到跳轉的位址,并重新發送請求連結。這樣,從浏覽器的位址欄中可以看到跳轉後的連結位址。是以,前者更加高效,在前者可以滿足需要時,盡量使用 forward()方法,并且,這樣也有助于隐藏實際的連結。在有些情況下,比如,需要跳轉到一個其它伺服器上的資源,則必須使用 sendRedirect()方法。從資料共享來說:forward 共享 request 中的資料,redirect 不能。forward - 一般用于使用者登陸的時候,根據角色轉發到相應的子產品, redirect - 一般用于使用者登出登陸時傳回首頁面和跳轉到其它的網址等;

補充四:Servlet與線程安全

  • 1.不要在Servlet中建立成員!建立局部變量即可!
  • 2.可以建立無狀态成員!無狀态表示不可變
  • 3.可以建立有狀态的成員,但狀态必須為隻讀的!