Servlet生命周期實現(xiàn)方式
實例和初始化時機
就緒/調用/服務階段
銷毀時機
案例實操
Servlet 的生命周期
??Servlet 沒有 main() 方法,不能獨立運行,它的運行完全由 Servlet 引擎來控制和調度。所謂生命周期,指的是 servlet 容器何時創(chuàng)建 servlet 實例、何時調用其方法進行請求的處理、并何時銷毀其實例的整個過程。(此處討論默認的生命周期)
實例和初始化時機
當請求到達容器時,容器查找該 servlet 對象是否存在,如果不存在,則會創(chuàng)建實例并進行初始化。
就緒/調用/服務階段
有請求到達容器,容器調用 servlet 對象的 service() 方法,處理請求的方法在整個生命周期中可以被多次調用;
HttpServlet 的 service() 方法,會依據(jù)請求方式來調用 doGet() 或者 doPost() 方法。但是,這兩個 do 方法默認情況下,會拋出異常,需要子類去 override。
銷毀時機
當容器關閉時(應用程序停止時),會將程序中的 Servlet 實例進行銷毀。
上述的生命周期可以通過 Servlet 中的生命周期方法來觀察。在 Servlet 中有三個生命周期方法,不由用戶手動調用,而是在特定的時機由容器自動調用,觀察這三個生命周期方法即可觀察到 Servlet 的生命周期。
init 方法,在 Servlet 實例創(chuàng)建之后執(zhí)行(證明該 Servlet 有實例創(chuàng)建了)
publicvoidinit(ServletConfigconfig)throwsServletException{
System.out.println("有實例創(chuàng)建了");
?? }
service 方法,每次有請求到達某個 Servlet 方法時執(zhí)行,用來處理請求(證明該 Servlet 進行服務了)
? ? protectedvoidservice(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
? ? ? ? System.out.println("服務調用了");
? ? }
destroy 方法,Servlet 實例銷毀時執(zhí)行(證明該 Servlet 的實例被銷毀了)
? ? publicvoiddestroy() {
? ? ? ? System.out.println("有實例被銷毀了");
? ? }
Servlet 的生命周期,簡單的概括就分為四步:servlet 類加載→實例化→服務→銷毀。下面我們描述一下 Tomcat 與 Servlet 是如何工作的,看看下面的時序圖:

1、Web Client 向 Servlet 容器(Tomcat)發(fā)出 Http 請求
2、Servlet 容器接收 Web Client 的請求
3、Servlet 容器創(chuàng)建一個 HttpRequest 對象,將 Web Client 請求的信息封裝到這個對象中
4、Servlet 容器創(chuàng)建一個 HttpResponse 對象
5、Servlet 容器調用 HttpServlet 對象的 service 方法,把 HttpRequest 對象與 HttpResponse 對象作為參數(shù),傳給 HttpServlet 對象
6、HttpServlet 調用 HttpRequest 對象的有關方法,獲取 Http 請求信息
7、HttpServlet 調用 HttpResponse 對象的有關方法,生成響應數(shù)據(jù)
8、Servlet 容器把 HttpServlet 的響應結果傳給 Web Client
擴展
Servlet 的配置
Servlet 除了配置基本的訪問信息,還可以配置初始化參數(shù),自啟動等,并且一個 Servlet 可以配置多個訪問路徑,還可以使用通配符“*”。
基本配置
<servlet>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet對應的資源路徑 -->
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 給瀏覽器看的,對外訪問路徑 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
初始化參數(shù)
<servlet>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet對應的資源路徑 -->
<!-- 初始化參數(shù) -->
? ? <init-param>
? ? ? ? <param-name>param1</param-name>
? ? ? ? <param-value>1</param-value>
? ? </init-param>
? ? <init-param>
? ? ? ? <param-name>param2</param-name>
? ? ? ? <param-value>2</param-value>
? ? </init-param>
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 給瀏覽器看的,對外訪問路徑 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
自啟動
<servlet>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet對應的資源路徑 -->
<!-- 初始化參數(shù) -->
? ? <init-param>
? ? ? ? <param-name>param1</param-name>
? ? ? ? <param-value>1</param-value>
? ? </init-param>
? ? <init-param>
? ? ? ? <param-name>param2</param-name>
? ? ? ? <param-value>2</param-value>
? ? </init-param>
? ? <!-- 自啟動 -->
? ? <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 給服務器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 給瀏覽器看的,對外訪問路徑 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
servlet-name:Servlet 對象的名稱
servlet-class:創(chuàng)建 Servlet 對象所要調用的類
param-name:參數(shù)名稱
param-value:參數(shù)值
load-on-startup:Servlet 容器啟動時加載 Servlet 對象的順序
servlet-mapping/servlet-name:要與 servlet 中的 servlet-name 配置的內(nèi)容對應
url-pattern:客戶訪問的 Servlet 的相對 URL 路徑
說明:url-pattern 可以配多個(一個 servlet 可以通過多個 url-pattern 訪問)當多個 servlet 配置成了同一個 url-pattern,報錯 java.lang.reflect.InvocationTargetExceptionion;通配符“*”只能放在最前面或最后面,不能放中間且不能單獨存在(以/分割的,不能和單詞組成整體)。越精確越優(yōu)先。常規(guī)配置即可。