官术网_书友最值得收藏!

3.2 Servlet基礎(chǔ)

3.2.1 Servlet定義

Servlet是服務(wù)器端的Java應(yīng)用程序,它用來(lái)擴(kuò)展服務(wù)器的功能,可以生成動(dòng)態(tài)的Web頁(yè)面。Servlet與傳統(tǒng)Java應(yīng)用程序最大的不同在于:它不是從命令行啟動(dòng)的,而是由包含Java虛擬機(jī)的Web服務(wù)器進(jìn)行加載。

Applet是運(yùn)行于客戶(hù)端瀏覽器的Java應(yīng)用程序,Servlet與Applet相比較,有以下特點(diǎn)。

1.相似之處

(1)它們不是獨(dú)立的應(yīng)用程序,沒(méi)有main方法。

(2)它們不是由用戶(hù)調(diào)用,而是由另外一個(gè)應(yīng)用程序(容器)調(diào)用。

(3)它們都有一個(gè)生命周期,包含init和destroy方法。

2.不同之處

(1)Applet運(yùn)行在客戶(hù)端,具有豐富的圖形界面。

(2)Servlet運(yùn)行在服務(wù)器端,沒(méi)有圖形界面。

造成這種差別的原因在于它們所肩負(fù)的使命不同。Applet目的是為了實(shí)現(xiàn)瀏覽器與客戶(hù)的強(qiáng)大交互,因此需要豐富多樣的圖形交互界面;Servlet用于擴(kuò)展服務(wù)器端的功能,實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,它不直接同客戶(hù)交互,因此不需要圖形界面。

Servlet最大的用途是通過(guò)動(dòng)態(tài)響應(yīng)客戶(hù)端請(qǐng)求來(lái)擴(kuò)展服務(wù)器功能。

3.2.2 Servlet工作流程

Servlet運(yùn)行在Web服務(wù)器上的Web容器里。Web容器負(fù)責(zé)管理Servlet。它裝入并初始化Servlet,管理Servlet的多個(gè)實(shí)例,并充當(dāng)請(qǐng)求調(diào)度器,將客戶(hù)端的請(qǐng)求傳遞到Servlet,并將Servlet的響應(yīng)返回給客戶(hù)端。Web容器在Servlet的使用期限結(jié)束時(shí)終結(jié)該Servlet。服務(wù)器關(guān)閉時(shí),Web容器會(huì)從內(nèi)存中卸載和除去Servlet。

Servlet的基本工作流程如下:

(1)客戶(hù)端將請(qǐng)求發(fā)送到服務(wù)器。

(2)服務(wù)器上的Web容器實(shí)例化(裝入)Servlet,并為Servlet進(jìn)程創(chuàng)建線程。請(qǐng)注意,Servlet是在出現(xiàn)第一個(gè)請(qǐng)求時(shí)裝入的,在服務(wù)器關(guān)閉之前不會(huì)卸載它。

注意:Servlet也可以配置為Web應(yīng)用程序啟動(dòng)時(shí)自動(dòng)裝載。關(guān)于如何配置Servlet將在3.6節(jié)詳細(xì)講解。

(3)Web容器將請(qǐng)求信息發(fā)送到Servlet。

(4)Servlet創(chuàng)建一個(gè)響應(yīng),并將其返回到Web容器。Servlet使用客戶(hù)端請(qǐng)求中的信息以及服務(wù)器可以訪問(wèn)的其他信息資源(如資源文件和數(shù)據(jù)庫(kù)等)來(lái)動(dòng)態(tài)構(gòu)造響應(yīng)。

(5)Web容器將響應(yīng)返回客戶(hù)端。

(6)服務(wù)器關(guān)閉或Servlet空閑時(shí)間超過(guò)一定限度時(shí),調(diào)用destroy方法退出。

從上面Servlet的工作基本流程可以看出,客戶(hù)端與Servlet間沒(méi)有直接的交互。無(wú)論是客戶(hù)端對(duì)Servlet的請(qǐng)求還是Servlet對(duì)客戶(hù)端的響應(yīng),都是通過(guò)Web容器來(lái)實(shí)現(xiàn)的,這就大大提高了Servlet組件的可移植性。

下面對(duì)Servlet的工作基本流程進(jìn)行詳細(xì)說(shuō)明。

1.Servlet裝入和初始化

第一次請(qǐng)求Servlet時(shí),服務(wù)器將動(dòng)態(tài)裝入并實(shí)例化Servlet。開(kāi)發(fā)人員可以通過(guò)Web配置文件將Servlet配置成在Web服務(wù)器初始化時(shí)直接裝入和實(shí)例化。Servlet調(diào)用init方法執(zhí)行初始化。init方法只在Servlet創(chuàng)建時(shí)被調(diào)用,所以,它常被用來(lái)作為一次性初始化的工作,如裝入初始化參數(shù)或獲取數(shù)據(jù)庫(kù)連接。

init方法有兩個(gè)版本:一個(gè)沒(méi)有參數(shù),一個(gè)以ServletConfig對(duì)象作為參數(shù)。

2.調(diào)用Servlet

每個(gè)Servlet都對(duì)應(yīng)一個(gè)URL地址。Servlet可以作為顯式URL引用調(diào)用,或者嵌入在HTML中并從Web應(yīng)用程序調(diào)用。

Servlet和其他資源文件(如JSP文件、靜態(tài)HTML文本等)打包作為一個(gè)Web應(yīng)用存放在Web服務(wù)器上。對(duì)于每個(gè)Web應(yīng)用,都可以存在一個(gè)配置文件web.xml。關(guān)于Servlet的名稱(chēng)、對(duì)應(yīng)的Java類(lèi)文件、URL地址映射等信息都存放在配置文件web.xml中。當(dāng)Web服務(wù)器接收到對(duì)URL地址的請(qǐng)求信息時(shí),會(huì)根據(jù)配置文件中URL地址與Servlet之間的映射關(guān)系將請(qǐng)求轉(zhuǎn)發(fā)到指定的Servlet來(lái)處理。

說(shuō)明:自Java EE 6版本以來(lái),Java EE規(guī)范推薦使用注解來(lái)配置Web組件,而不是使用配置文件web.xml。注解是內(nèi)嵌在Java代碼中的一種特殊標(biāo)記,關(guān)于注解的使用本書(shū)后面的示例中會(huì)反復(fù)講到。因此,在Java EE 6版本以上的Web應(yīng)用中,也允許沒(méi)有配置文件web.xml存在。

3.處理請(qǐng)求

當(dāng)Web容器接收到對(duì)Servlet的請(qǐng)求,Web容器會(huì)產(chǎn)生一個(gè)新的線程來(lái)調(diào)用Servlet的service方法。service方法檢查HTTP請(qǐng)求類(lèi)型(GET、POST、PUT、DELETE等),然后相應(yīng)地調(diào)用Servlet組件的doGet、doPost、doPut、doDelete等方法。如果Servlet處理各種請(qǐng)求的方式相同,也可以嘗試覆蓋service方法。GET請(qǐng)求類(lèi)型與POST請(qǐng)求類(lèi)型的區(qū)別在于:如果以GET方式發(fā)送請(qǐng)求,所帶參數(shù)附加在請(qǐng)求URL后直接傳給服務(wù)器,并可從服務(wù)器端的QUERY_STRING這個(gè)環(huán)境變量中讀取;如果以POST方式發(fā)送請(qǐng)求,則參數(shù)會(huì)被打包在數(shù)據(jù)包中傳送給服務(wù)器。

4.多個(gè)請(qǐng)求的處理

Servlet由Web容器裝入,一個(gè)Servlet同一時(shí)刻只有一個(gè)實(shí)例,并且它在Servlet的使用期間將一直保留。當(dāng)同時(shí)有多個(gè)請(qǐng)求發(fā)送到同一個(gè)Servlet時(shí),服務(wù)器將會(huì)為每個(gè)請(qǐng)求創(chuàng)建一個(gè)新的線程來(lái)處理客戶(hù)端的請(qǐng)求。

如圖3-2所示,有兩個(gè)客戶(hù)端瀏覽器同時(shí)請(qǐng)求同一個(gè)Servlet服務(wù),服務(wù)器會(huì)根據(jù)Servlet實(shí)例對(duì)象為每個(gè)請(qǐng)求創(chuàng)建一個(gè)處理線程。每個(gè)線程都可以訪問(wèn)Servlet裝入時(shí)的初始化變量。每個(gè)線程處理它自己的請(qǐng)求。Web容器將不同的響應(yīng)返回各自的客戶(hù)端。

圖3-2 Servlet對(duì)多個(gè)請(qǐng)求的處理

上述說(shuō)明意味著Servlet的doGet方法和doPost方法必須注意共享數(shù)據(jù)和領(lǐng)域的同步訪問(wèn)問(wèn)題,因?yàn)槎鄠€(gè)線程可能會(huì)同時(shí)嘗試訪問(wèn)同一塊數(shù)據(jù)或代碼。如果想避免多線程的并發(fā)訪問(wèn),可以設(shè)置Servlet實(shí)現(xiàn)SingleThreadModel接口,如下所示:

    public class YourServlet extends HttpServlet  implements SingleThreadModel {
      ...
    }

注意:使用SingleThreadModel接口雖然避免了多請(qǐng)求條件下的線程同步問(wèn)題,但是單線程模式將對(duì)應(yīng)用的性能造成重大影響,因此在使用時(shí)要特別慎重。

5.退出

如果Web應(yīng)用程序關(guān)閉或者Servlet已經(jīng)空閑了很長(zhǎng)時(shí)間,Web容器會(huì)將Servlet實(shí)例從內(nèi)存移除。移除之前Web容器會(huì)調(diào)用Servlet的destroy方法。Servlet可以使用這個(gè)方法關(guān)閉數(shù)據(jù)庫(kù)連接、中斷后臺(tái)線程、向磁盤(pán)寫(xiě)入Cookie列表及執(zhí)行其他清理動(dòng)作。

注意:當(dāng)Web容器出現(xiàn)意外而被關(guān)閉,則不能夠保證destroy方法被調(diào)用。

通過(guò)上面Servlet工作流程的基本描述,對(duì)于Web容器的職責(zé),可以歸納為以下兩點(diǎn):一是管理Servlet組件的生命周期,包括Servlet組件的初始化、銷(xiāo)毀等;二是作為客戶(hù)端與Servlet之間的中介,負(fù)責(zé)封裝客戶(hù)端對(duì)Servlet的請(qǐng)求,并將請(qǐng)求映射到對(duì)應(yīng)的Servlet,以及將Servlet產(chǎn)生的響應(yīng)返回給客戶(hù)端。

3.2.3 Servlet編程接口

Java EE標(biāo)準(zhǔn)定義了Java Servlet API,用于規(guī)范Web容器和Servlet組件之間的標(biāo)準(zhǔn)接口。Java Servlet API是一組接口和類(lèi),主要由兩個(gè)包組成:javax.servlet包含了支持協(xié)議無(wú)關(guān)的Servlet的類(lèi)和接口;javax.servlet.http包括了對(duì)HTTP協(xié)議的特別支持的類(lèi)和接口。如果希望詳細(xì)了解Java Servlet API,可訪問(wèn)http://www.oracle.com/technetwork/java/index-jsp-135475.html下載Java Servlet API的詳細(xì)文檔。

所有的Servlet都必須實(shí)現(xiàn)通用Servlet接口或HttpServlet接口。通用Servlet接口類(lèi)javax.servlet.GenericServlet定義了管理Servlet及它與客戶(hù)端通信的方法;HttpServlet接口類(lèi)javax.servlet.http.HttpServlet是繼承了通用Servlet接口類(lèi)的一個(gè)抽象子類(lèi)。要編寫(xiě)在Web上使用的HTTP協(xié)議下的Servlet,通常采用繼承HttpServlet接口的形式。下面以HttpServlet接口為中心,介紹與Servlet編程密切相關(guān)的幾個(gè)接口,如圖3-3所示。

圖3-3 Servlet編程相關(guān)接口示意圖

·HttpServletRequest代表發(fā)送到HttpServlet的請(qǐng)求。這個(gè)接口封裝了從客戶(hù)端到服務(wù)器的通信。它可以包含關(guān)于客戶(hù)端環(huán)境的信息和任何要從客戶(hù)端發(fā)送到Servlet的數(shù)據(jù)。

·HttpServletResponse代表從HttpServlet返回客戶(hù)端的響應(yīng)。它通常是根據(jù)請(qǐng)求和Servlet訪問(wèn)的其他來(lái)源中的數(shù)據(jù)動(dòng)態(tài)創(chuàng)建生成的響應(yīng),如HTML頁(yè)面。

·ServletConfig代表Servlet的配置信息。Servlet在發(fā)布到服務(wù)器上的時(shí)候,在Web應(yīng)用配置文件中對(duì)應(yīng)一段配置信息。Servlet根據(jù)配置信息進(jìn)行初始化。配置信息的好處在于在Servlet發(fā)布時(shí)可以通過(guò)配置信息靈活地調(diào)整Servlet而不需要重新改動(dòng)、編譯代碼。

·ServletContext代表Servlet的運(yùn)行環(huán)境信息。Servlet是運(yùn)行在服務(wù)器上的程序。為了與服務(wù)器及服務(wù)器上運(yùn)行的其他程序進(jìn)行交互,有必要獲得服務(wù)器的環(huán)境信息。

·ServletException代表Servlet運(yùn)行過(guò)程中拋出的意外對(duì)象。

·HttpSession用來(lái)在無(wú)狀態(tài)的HTTP協(xié)議下跨越多個(gè)請(qǐng)求頁(yè)面來(lái)維持狀態(tài)和識(shí)別用戶(hù)。維護(hù)HttpSession的方法有Cookie或URL重寫(xiě)。

·RequestDispatcher:請(qǐng)求轉(zhuǎn)發(fā)器,可以將客戶(hù)端請(qǐng)求從一個(gè)Servlet轉(zhuǎn)發(fā)到其他的服務(wù)器資源,如其他Servlet、靜態(tài)HTML頁(yè)面等。

Java EE服務(wù)器必須聲明支持的Java Servlet API的版本級(jí)別。隨著Java EE技術(shù)的不斷進(jìn)步,Java Servlet API的版本也在不斷更新,在Java EE 8標(biāo)準(zhǔn)規(guī)范中包含的Java Servlet API的版本為4.0。

主站蜘蛛池模板: 三穗县| 闽清县| 康乐县| 厦门市| 株洲市| 郁南县| 桂阳县| 神农架林区| 永昌县| 永仁县| 西吉县| 思茅市| 外汇| 太谷县| 东乌| 资阳市| 湛江市| 东明县| 旌德县| 乌鲁木齐市| 德昌县| 嘉荫县| 南木林县| 宾川县| 西乌珠穆沁旗| 邢台县| 宾阳县| 乡宁县| 桂阳县| 大理市| 英吉沙县| 闸北区| 吉水县| 甘洛县| 麦盖提县| 长春市| 砀山县| 临泉县| 嘉祥县| 江津市| 江达县|