JaveWeb學習之Servlet(一):Servlet生命週期和加載機制

原文同步發表至我的博客【夜月歸途】html

原文連接:http://www.guitu18.com/se/java/2018-07-22/19.htmljava

Servlet生命週期和加載機制

查看Servlet3.1源碼,其接口定義以下:web

package javax.servlet;  
public interface Servlet {
    public void init(ServletConfig config) 
        throws ServletException; 
    public ServletConfig getServletConfig();
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException;
    public String getServletInfo();
    public void destroy();
}

init(ServletConfig config);

init方法在容器啓動時會被容器調用,且只會被調用一次;
調用的時機是跟Servlet的配置項'load-on-startup'有關係的;spring

<servlet>
    <servlet-name>springmvcdemo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<load-on-startup>1</load-on-startup>:配置的值若是不小於0,那麼標識容器在啓動時就會加載這個Servlet,配置的值越小,加載的優先級越高;若是沒有配置或者配置的值小於0時,容器會在該Servlet第一次被調用時纔會被加載;不論哪一種配置,init方法只會被調用一次;mvc

init方法的參數,是容器傳進去的;咱們在web.xml中配置的contextConfigLocation參數,就保存在ServletConfig中;app

這項參數咱們不配置的話,它有默認值:WEB-INF/${ServletName}-servlet.xml,變量${ServletName}是xml中配置的'servlet-name';ide

getServletConfig();

getServletConfig方法用於獲取ServletConfig;測試

service(ServletRequest req, ServletResponse res);

service方法用於具體處理一個請求;每次訪問,都會執行一次,server方法內部會根據請求方式的不一樣,調用不一樣的doXXX方法;ui

getServletInfo();

getServletInfo方法能夠獲取一些Servlet相關的信息,如做者、版權等;這個方法須要本身實現,默認返回空字符串;url

destroy();

destroy方法主要用於Servlet銷燬時釋放資源,同init同樣只會被調用一次;

Servlet生命週期測試demo

  1. 新建web工程,建立三個都實現Servlet接口的ServletDemo對象;
    這裏建立的分別是Servlet1,Servlet2,Servlet3,代碼都是同樣的只貼上Servlet1的代碼;

    package com.guitu18.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class Servlet_1 implements Servlet {
    
        @Override
        public void destroy() {
            System.out.println("Servlet_1:destroy()執行銷燬...");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void init(ServletConfig arg0) throws ServletException {
            System.out.println("Servlet_1:init()執行初始化...");
        }
    
        @Override
        public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
            System.out.println("Servlet_1:service()執行中...");
        }
    
    }
  2. web.xml配置以下:

    <servlet>
        <servlet-name>servlet_1</servlet-name>
        <servlet-class>com.guitu18.servlet.Servlet_1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_1</servlet-name>
        <url-pattern>/servlet_1</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet_2</servlet-name>
        <servlet-class>com.guitu18.servlet.Servlet_2</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_2</servlet-name>
        <url-pattern>*.guitu18</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet_3</servlet-name>
        <servlet-class>com.guitu18.servlet.Servlet_3</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_3</servlet-name>
        <url-pattern>/abc/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>servlet_2</servlet-name>
        <url-pattern>/servlet_4</url-pattern>
    </servlet-mapping>

    我在xml中分別配置了這三個Servlet,配置了4個servlet-mapping,其中'/servlet2.guitu'和'/servlet4'都是指向servle_2的;
    這裏就涉及到Servlet中<url-pattern>的配置方式了,一共有3種:

    1. 徹底路徑匹配
      以'/'開始;好比:/servlet_1
    2. 目錄匹配
      以'/'開始,以'/'結束;好比:/abc/
    3. 擴展名匹配
      不能以'/'開始,要以''開始;好比:.guitu18

    爲了是匹配時不產歧義,這三種匹配方式是有優先級的:
    徹底路徑匹配 > 目錄匹配 > 擴展名匹配

  3. 啓動項目:
    由於Servlet2和Servlet3都配置了<load-on-startup>項,且配置的值不小於0,因此在項目啓動時,Servlet2和Servlet3就會被初始化,控制檯輸出:

    Servlet_3:init()執行初始化...  
    Servlet_2:init()執行初始化...

    這裏看出,Servlet3比Servlet2有限初始化,由於Servlet_3配置的<load-on-startup>的值比Servlet2小,因此優先被加載;Servlet1由於沒有配置<load-on-startup>因此只有其第一次被訪問時纔會被加載初始化;

    訪問Servlet1的地址:http://localhost:8080/servletdemo/servlet1

    Servlet_1:init()執行初始化...
    Servlet_1:service()執行中...

    此時Servlet_1才被初始化;

  4. Servlet對象銷燬 如今關閉Tomcat服務,Servlet對象會被銷燬;

    Servlet_2:destroy()執行銷燬...
    Servlet_3:destroy()執行銷燬...
    Servlet_1:destroy()執行銷燬...

    能夠看出銷燬的順序和加載的順序相同,優先被加載的也會最早被銷燬;

相關文章
相關標籤/搜索