原文同步發表至我的博客【夜月歸途】html
原文連接:http://www.guitu18.com/se/java/2018-07-22/19.htmljava
查看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方法在容器啓動時會被容器調用,且只會被調用一次;
調用的時機是跟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方法用於獲取ServletConfig;測試
service方法用於具體處理一個請求;每次訪問,都會執行一次,server方法內部會根據請求方式的不一樣,調用不一樣的doXXX方法;ui
getServletInfo方法能夠獲取一些Servlet相關的信息,如做者、版權等;這個方法須要本身實現,默認返回空字符串;url
destroy方法主要用於Servlet銷燬時釋放資源,同init同樣只會被調用一次;
新建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()執行中..."); } }
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種:
爲了是匹配時不產歧義,這三種匹配方式是有優先級的:
徹底路徑匹配 > 目錄匹配 > 擴展名匹配
啓動項目:
由於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才被初始化;
Servlet對象銷燬 如今關閉Tomcat服務,Servlet對象會被銷燬;
Servlet_2:destroy()執行銷燬... Servlet_3:destroy()執行銷燬... Servlet_1:destroy()執行銷燬...
能夠看出銷燬的順序和加載的順序相同,優先被加載的也會最早被銷燬;