Servlet
Servlet 沒(méi)有 main 方法,不能夠獨(dú)立的運(yùn)行,它的運(yùn)行需要容器的支持,Tomcat 是最常用的 JSP/Servlet 容器。
Servlet 運(yùn)行在 Servlet 容器中,并由容器管理從創(chuàng)建到銷(xiāo)毀的整個(gè)過(guò)程。
Servlet 的生命周期
(1) 加載和實(shí)例化
Servlet 容器裝載和實(shí)例化一個(gè) Servlet。創(chuàng)建出該 Servlet 類(lèi)的一個(gè)實(shí)例。
(2) 初始化
在 Servlet 實(shí)例化完成之后,容器負(fù)責(zé)調(diào)用該 Servlet 實(shí)例的 init() 方法,在處理用戶請(qǐng)求之前,來(lái)做一些額外的初始化工作。
(3) 處理請(qǐng)求
當(dāng) Servlet 容器接收到一個(gè) Servlet 請(qǐng)求時(shí),便運(yùn)行與之對(duì)應(yīng)的 Servlet 實(shí)例的 service() 方法,service() 方法再派遣運(yùn)行與請(qǐng)求相對(duì)應(yīng)的
doXX(doGet,doPost) 方法來(lái)處理用戶請(qǐng)求。
(4) 銷(xiāo)毀
當(dāng) Servlet 容器決定將一個(gè) Servlet 從服務(wù)器中移除時(shí) ( 如 Servlet 文件被更新 ),便調(diào)用該 Servlet 實(shí)例的 destroy() 方法,在銷(xiāo)毀該 Servlet 實(shí)例之前,
來(lái)做一些其他的工作。
其中,(1)(2)(4) 在 Servlet 的整個(gè)生命周期中只會(huì)被執(zhí)行一次。
Servlet 的工作原理

結(jié)合右邊給出的流程圖:
當(dāng)客戶端瀏覽器向服務(wù)器請(qǐng)求一個(gè) Servlet 時(shí),服務(wù)器收到該請(qǐng)求后,首先到容器中檢索與請(qǐng)求
匹配的 Servlet 實(shí)例是否已經(jīng)存在。若不存在,則 Servlet 容器負(fù)責(zé)加載并實(shí)例化出該類(lèi) Servlet
的一個(gè)實(shí)例對(duì)象,接著容器框架負(fù)責(zé)調(diào)用該實(shí)例的 init() 方法來(lái)對(duì)實(shí)例做一些初始化工作,然后
Servlet 容器運(yùn)行該實(shí)例的 service() 方法。
若 Servlet 實(shí)例已經(jīng)存在,則容器框架直接調(diào)用該實(shí)例的 service() 方法。
service() 方法在運(yùn)行時(shí),自動(dòng)派遣運(yùn)行與用戶請(qǐng)求相對(duì)應(yīng)的 doXX() 方法來(lái)響應(yīng)用戶發(fā)起的請(qǐng)求。
通常,每個(gè) Servlet 類(lèi)在容器中只存在一個(gè)實(shí)例,每當(dāng)請(qǐng)求到來(lái)時(shí),則分配一條線程來(lái)處理該請(qǐng)求。
JSP 工作原理

結(jié)合右邊給出的流程圖:
當(dāng)客戶端瀏覽器向服務(wù)器請(qǐng)求一個(gè) JSP 頁(yè)面時(shí),服務(wù)器收到該請(qǐng)求后,首先檢查所請(qǐng)求的這個(gè)
JSP 文件內(nèi)容 ( 代碼 ) 是否已經(jīng)被更新,或者是否是 JSP 文件創(chuàng)建后的第一次被訪問(wèn),如果是,
那么,這個(gè) JSP 文件就會(huì)在服務(wù)器端的 JSP 引擎作用下轉(zhuǎn)化為一個(gè) Servlet 類(lèi)的 Java 源代碼
文件。緊接著,這個(gè) Servlet 類(lèi)會(huì)在 Java 編譯器的作用下被編譯成一個(gè)字節(jié)碼文件,并裝載
到 jvm 解釋執(zhí)行。剩下的就等同于 Servlet 的處理過(guò)程了。
如果被請(qǐng)求的 JSP 文件內(nèi)容 ( 代碼 ) 沒(méi)有被修改,那么它的處理過(guò)程也等同于一個(gè) Servlet 的
處理過(guò)程。即直接由服務(wù)器檢索出與之對(duì)應(yīng)的 Servlet 實(shí)例來(lái)處理。
需要注意的是,JSP 文件不是在服務(wù)器啟動(dòng)的時(shí)候轉(zhuǎn)換成 Servlet 類(lèi)的。而是在被客戶端訪問(wèn)
的時(shí)候才可能發(fā)生轉(zhuǎn)換的 ( 如 JSP 文件內(nèi)容沒(méi)有被更新等,就不再發(fā)生 Servlet 轉(zhuǎn)換 )。
就 Tomcat 而言,打開(kāi)目錄 %Tomcat%/work/%您的工程文件目錄%,然后會(huì)看到里面有 3
個(gè)子目錄:org/apache/jsp,若沒(méi)有這 3 個(gè)目錄,說(shuō)明項(xiàng)目的 JSP 文件還沒(méi)有被訪問(wèn)過(guò),
打開(kāi)進(jìn)到 jsp 目錄下,會(huì)看到一些 *_jsp.java 和 *_jsp.class 文件,這就是 JSP 文件被轉(zhuǎn)換成
Servlet 類(lèi)的源文件和字節(jié)碼文件了。
有興趣的話,可以使用瀏覽器訪問(wèn)服務(wù)器中的 JSP,然后觀察 JSP 轉(zhuǎn)換 Servlet 以及編譯的時(shí)機(jī)。
Servlet 與 JSP
JSP 本質(zhì)是一個(gè) Servlet,它的運(yùn)行也需要容器的支持。
在 JSP 和 Servlet 文件中都可以編寫(xiě) Java 和 HTML 代碼,不同的是,
Servlet 雖然也可以動(dòng)態(tài)的生成頁(yè)面內(nèi)容,但更加偏向于邏輯的控制。
JSP 最終被轉(zhuǎn)換成 Servlet 在 jvm 中解釋執(zhí)行,在 JSP 中雖然也可以編寫(xiě) Java 代碼,但它更加偏向于頁(yè)面視圖的展現(xiàn)。
在 MVC 架構(gòu)模式中,就 JSP 和 Servlet 而言,C 通常由 Servlet 充當(dāng),V 通常由 JSP 來(lái)充當(dāng)。