隨筆-57  評論-117  文章-1  trackbacks-0

          Servlet 是一種比JSP 更早的動態(tài)網(wǎng)頁編程技術(shù)。在沒有JSP 之前, Servlet 也是同時充當(dāng)視圖層、業(yè)務(wù)邏輯層及持久層角色。

          Servlet 的開發(fā)效率非常低,特別是當(dāng)使用Servlet 生成表現(xiàn)層頁面時,頁面中所有的HTML 標(biāo)簽,都需采用Servlet 的輸出流來輸出,因此極其煩瑣。由于Servlet 是個標(biāo)準(zhǔn)的Java 類,因此必須由程序員開發(fā),其修改難度大,美工人員根本無法參與Servlet 頁面的開發(fā)。這一系列的問題,都阻礙了Servlet 作為表現(xiàn)層的使用。

          自MVC 規(guī)范出現(xiàn)后, Servlet 的責(zé)任開始明確下來,僅僅作為控制器使用,不再需要生成頁面標(biāo)簽,也不再作為視圖層角色使用。

           

          Servlet ,通常稱為服務(wù)器端小程序,是運行在服務(wù)器端的程序,用于處理及響應(yīng)客戶端請求。

          Servlet 是個特殊的Java 類,這個Java 類必須繼承HttpServlet 。每個Servlet 可以響應(yīng)戶端的請求。Servlet 提供不同的方法用于響應(yīng)客戶端請求。

          doGet: 用于響應(yīng)客戶端的get 請求。

          doPost: 用于響應(yīng)客戶端的post 請求。

          doPut: 用于響應(yīng)客戶端的put 請求。

          doDelete: 用于響應(yīng)客戶端的delete 請求。

          事實上,客戶端的請求通常只有g(shù)et 和post 兩種; Servlet 為了響應(yīng)這兩種請求,必須重寫doGet 和doPost 兩個方法。如果Servlet 為了響應(yīng)四個方法,則需要同時重寫上面的四個方法。

           

          大部分時候, Servlet 對于所有請求的響應(yīng)都是完全一樣的。此時,可以采用重寫一個方法來代替上面的幾個方法, Servlet 只需重寫service 方法即可響應(yīng)客戶端的所有請求。另外, HttpServlet 還包含兩個方法。

          init(ServletConfig config): 創(chuàng)建Servlet 實例時,調(diào)用的初始化方法。

          destroy: 銷毀Servlet 實例時,自動調(diào)用的資源回收方法。

          通常無須重寫init和destroy兩個方法,除非需要在初始化Servlet 時,完成某些資源初始化的方法,才考慮重寫init 方法。如果需要在銷毀Servlet 之前,先完成某些資源的回收,比如關(guān)閉數(shù)據(jù)庫連接等,才需要重寫destroy 方法。

          注意:如果重寫了init(ServletConfig config)方法,則應(yīng)在重寫該方法的第一行調(diào)用super.init(config) 。該方法將調(diào)用HttpServlet 的init 方法。

           

          Servlet 和JSP 的區(qū)別在于:

          Servlet 中沒有內(nèi)置對象,原來JSP 中的內(nèi)置對象都必須通過HttpServletRequest對象,或由HttpServletResponse 對象生成:

          對于靜態(tài)的HTML 標(biāo)簽, Servlet 都必須使用頁面輸出流逐行輸出。

          這也正是筆者在前面介紹的: JSP 是Servlet 的一種簡化,使用JSP 只需要完成程序員需要輸出到客戶端的內(nèi)容,至于JSP 中的Java 腳本如何鑲嵌到一個類中,由JSP 容器完成。而Servlet 則是個完整的Java 類,這個類的service 方法用于生成對客戶端的響應(yīng)。

           

          Servlet 的配置

          編輯好的Servlet 源文件并不能響應(yīng)用戶請求,還必須將其編譯成class 文件。將編譯后的HelloServlet. class 文件放在WEB-INF/classes 路徑下,如果Servlet 有包,則還應(yīng)該將class 文件放在對應(yīng)的包路徑下。

          為了讓Servlet 能響應(yīng)用戶請求,還必須將Servlet 配置在Web 應(yīng)用中。配置Servlet時,需要修改web.xrnl 文件。

          配置Servlet 需要配置兩個部分。<servlet>/<servlet-mapping>

           

          Servlet的生命周期

          Servlet 在容器中運行,其實例的創(chuàng)建及銷毀等都不是由程序員決定的,而是由容器進行控制。

          Servlet 的創(chuàng)建有兩個選擇。

          客戶端請求對應(yīng)的Servlet 時,創(chuàng)建Servlet 實例:大部分的Servlet 都是這種Servlet。 Web 應(yīng)用啟動時,立即創(chuàng)建Servlet 實例:即load-on-startup Servlet。

          每個Servlet 的運行都遵循如下生命周期。

          (1)創(chuàng)建Servlet 實例。

          (2) Web 容器調(diào)用Servlet 的init 方法,對Servlet 進行初始化。

          (3) Servlet 初始化后,將一直存在于容器中,用于響應(yīng)客戶端請求。如果客戶端有g(shù)et 請求,容器調(diào)用Servlet 的doGet 方法處理并響應(yīng)請求。對于不同的請求,有不同的處理方法,或者統(tǒng)一使用service 方法處理來響應(yīng)用戶請求。

          (4) Web 容器角色銷毀Servlet 時,調(diào)用Servlet 的destroy 方法,通常在關(guān)閉Web容器之時銷毀Servlet。

           

          使用Servlet創(chuàng)作為控制器

          正如前面見到,使用Servlet 作為表現(xiàn)層的工作量太大,所有的HTML 標(biāo)簽都需要使用頁面輸出流生成。因此,使用Servlet 作為表現(xiàn)層有如下三個劣勢。

          開發(fā)效率低,所有的HTML 標(biāo)簽都需使用頁面輸出流完成。

          不利于團隊協(xié)作開發(fā),美工人員無法參與Servlet 界面的開發(fā)。

          程序可維護性差,即使修改一個按鈕的標(biāo)題,都必須重新編輯Java 代碼,并重新編譯。

           

          整個結(jié)構(gòu)非常清晰,下面是MVC 中各個角色的對應(yīng)組件。

          M: Model,即模型,對應(yīng)JavaBean 。

          V: View ,即視圖,對應(yīng)JSP 頁面。

          C: Controller,即控制器,對應(yīng)Servlet。

           

          load-on-startup Servlet

          Servlet 的實例化有兩個時機:用戶請求之時,或應(yīng)用啟動之時。應(yīng)用啟動時就啟動的Servlet 通常是用于某些后臺服務(wù)的Servlet ,或者攔截很多請求的Servlet; 這種Servlet 通常作為應(yīng)用的基礎(chǔ)Servlet 使用,提供重要的后臺服務(wù)。如果需要Web 應(yīng)用啟動時,可使用load-on-startup 元素完成Servlet 的初始化。load-on-startup 元素只接收一個整型值,這個整型值越小, Servlet 就越優(yōu)先初始化。

          訪問Servlet 的配置參數(shù)

          配置Servlet 時,還可以增加附加的配置參數(shù)。通過使用配置參數(shù),可以實現(xiàn)更好地解耦,避免將所有的參數(shù)以硬編碼方式寫在程序中。

          訪問Servlet 配置參數(shù)要通過ServletConfig 類的實例完成, ServletConfig提供如下方法。

          java.lang.String getInitParameter(java.lang.String name): 用于獲取初始化參數(shù)。

          注意: JSP 的內(nèi)直對象config 就是此處的ServletConfig

          自定義標(biāo)簽類

          使用標(biāo)簽類,可以使用簡單的標(biāo)簽來封裝復(fù)雜的功能,從而使團隊更好地協(xié)作開發(fā)(能讓美工人員更好地參與JSP 頁面的開發(fā))。

          自定義標(biāo)簽類都必須繼承一個父類: java.Servlet.jsp.tagext.TagSupport 。除此之外,自定義標(biāo)簽類還有如下要求。

          ·如果標(biāo)簽類包含屬性,每個屬性都有對應(yīng)的getter 和setter 方法。

          ·重寫doStartTag或doEndTag方法,這兩個方法生成頁面內(nèi)容。

          ·如果需要在銷毀標(biāo)簽之前完成資源回收,則重寫re1ease方法。

          TLD 文件

          TLD 是Tag Library Definition 的縮寫,即標(biāo)簽庫定義,文件的后綴是tld ,每個TLD文件對應(yīng)一個標(biāo)簽庫,一個標(biāo)簽庫中可包含多個標(biāo)簽。TLD 文件也稱為標(biāo)簽庫定義文件。標(biāo)簽庫定義文件的根元素是taglib,它可以有多個tag 子元素,每個tag 子元素都對應(yīng)一個標(biāo)簽。

          編輯了標(biāo)簽庫定義文件還不夠, Web 容器還無法加載標(biāo)簽庫定義文件。還必須在web.xml 文件中增加標(biāo)簽庫的定義。在web.xml 文件中定義標(biāo)簽庫時使用taglib 元素,該元素包含兩個子元素: taglib-uri和taglib-location,前者確定標(biāo)簽庫的URI; 后者確定標(biāo)簽庫定義文件的位置。

          使用標(biāo)簽庫

          使用標(biāo)簽庫分成以下兩步。

          (1) 導(dǎo)入標(biāo)簽庫:使用taglib 編譯指令導(dǎo)入標(biāo)簽。

          (2) 使用標(biāo)簽:在JSP 頁面中使用自定義標(biāo)簽。

          taglib 的語法格式如下:

          〈%@ taglib uri="tagliburi" prefix="tagPrefix" %〉

          其中uri 屬性確定標(biāo)簽庫定義文件的URI,這個URI 就是在web.xml 文件中為標(biāo)簽

          庫定義的URI。而prefix 屬性確定的是標(biāo)簽前綴,即在JSP 頁面中使用標(biāo)簽時,該標(biāo)簽

          庫負責(zé)處理的標(biāo)簽前綴。

          使用標(biāo)簽的語法格式如下:

          <tagPrefix : tagName tagAttribute=ntagValue n ...>

          <tagBody/>

          </tagPrefix>

          如果該標(biāo)簽沒有標(biāo)簽體,則可以使用如下語法格式:

          <tagPrefix : tagName tagAttribute=ntagValue n …/>

          帶標(biāo)簽體的標(biāo)簽

          帶標(biāo)簽體的標(biāo)簽,就是允許在標(biāo)簽內(nèi)嵌套標(biāo)簽,通常可用于完成一些邏輯運算例如判斷和循環(huán)等。

          帶標(biāo)簽體的標(biāo)簽需要繼承BodyTagSupport,該類包含一個bodyContent 屬性,該屬性代表標(biāo)簽體。

          BodyTagSupport 還包含兩個方法。

          doAfterBody: 每次處理完標(biāo)簽體后調(diào)用該方法。

          void doInitBody: 開始調(diào)用標(biāo)簽體時調(diào)用該方法。

          如果有必要,可以重寫這兩個方法。

          在處理標(biāo)簽類的各個方法中,不同的返回值對應(yīng)不同的含義,常用的返回值有如下幾個。

          SKIP_BODY: 不處理標(biāo)簽體,直接調(diào)用doEndTag方法。

          SKIP_PAGE: 忽略標(biāo)簽后面的JSP 頁面。

          EVAL_PAGE: 處理標(biāo)簽結(jié)束,直接處理頁面內(nèi)容。

          EVAL_BODY_BUFFERED: 處理標(biāo)簽體。

          EVAL_BODY_INCLUDE: 處理標(biāo)簽體,但忽略setBodyContent和doInitBody方法。

          EVAL_BODY_AGAIN: 對標(biāo)簽體循環(huán)處理。

           

          Filter

          Filter 并不是一個標(biāo)準(zhǔn)的Servlet ,它不能處理用戶請求,也不能對客戶端生成響應(yīng)。主要用于對HttpServletRequest 進行預(yù)處理,也可以對HttpServletResponse 進行后處理,是個典型的處理鏈。

          Filter 有如下幾個用處。

          ·在HttpServletRequest 到達Servlet 之前,攔截客戶的HttpServletRequest 。

          ·根據(jù)需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數(shù)據(jù)。

          ·在HttpServletResponse 到達客戶端之前,攔截HttpServletResponse 。

          ·根據(jù)需要檢查HttpServletResponse ,也可以修改HttpServletResponse 頭和數(shù)據(jù)。

          Filter 有如下幾個種類。

          ·用戶授權(quán)的Filter: Filter 負責(zé)檢查用戶請求,根據(jù)請求過濾用戶非法請求。

          ·日志Filter: 詳細記錄某些特殊的用戶請求。

          ·負責(zé)解碼的Filter: 包括對非標(biāo)準(zhǔn)編碼的請求解碼。

          .能改變XML 內(nèi)容的XSLTFilter 等。

          一個Filter 可負責(zé)攔截多個請求或響應(yīng):一個請求或響應(yīng)也可被多個請求攔截。

          創(chuàng)建一個Filter 只需兩個步驟:

          (1)創(chuàng)建Filter 處理類:

          (2) 在web.xml 文件中配置Filter。

          創(chuàng)建Filter 類

          創(chuàng)建Filter 必須實現(xiàn)javax.servle t. Filter 接口,在該接口中定義了三個方法。

          void init(FilterConfig config): 用于完成Filter 的初始化。

          void destroy: 用于Filter 銷毀前,完成某些資源的回收。

          void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 實現(xiàn)過濾功能,該方法就是對每個請求及響應(yīng)增加的額外處理。

          執(zhí)行chain.doFilter(request,reponse)方法,當(dāng)Filter 對請求過濾后,依然將請求發(fā)送到目的地址。如果檢查權(quán)限,可以在Filter 中根據(jù)用戶請求的HttpSession,判斷用戶權(quán)限是否足夠。

          如果權(quán)限不夠,則調(diào)用重定向即可,無須調(diào)用chain.doFilter(request,reponse)方法。

          配置Filter

          Filter 的配置和Servlet 的配置非常相似,都需要配置兩個部分:

          ·配置Filter 名。

          ·配置Filter 攔截URL 模式。

          區(qū)別在于, Servlet 通常只配置一個URL ,而Filter 可以同時攔截多個請求的URL。

          因此,可以配置多個Filter 攔截模式。

           

          Listener

          Listener 的作用非常類似于load-on-startup Servlet。用于在Web 應(yīng)用啟動時,啟動某些后臺程序,這些后臺程序負責(zé)為系統(tǒng)運行提供支持。

          Listener 與load-on-startup Servlet 的區(qū)別在于: Listener 的啟動時機比load-on-startup Servlet 早,只是Listener 是Servlet 2.3 規(guī)范之后才出現(xiàn)的。

          使用Listener 只需要兩個步驟:

          (1) 創(chuàng)建Listener 實現(xiàn)類。

          (2) 在web.xml 文件中配置Listener。

          創(chuàng)建Listener 類

          創(chuàng)建Li stener 類必須實現(xiàn)ServletContex tListener 接口,該接口包含兩個方法。

          eontextInitialized(ServletContextEvent see): 啟動Web 應(yīng)用時,系統(tǒng)調(diào)用該Filter的方法。

          eontextDestroyed(ServletContextEvent see): 關(guān)閉Web 應(yīng)用時候,系統(tǒng)調(diào)用Filter

          的方法。

          配置Listener

          正如load-an-startup Servlet 一樣, Listener 用于啟動Web 應(yīng)用的后臺服務(wù)程序,但不負責(zé)處理及響應(yīng)用戶請求,因此無須配置URL。

          若將Listener 配置在Web 容器中(如果Web 容器支持Listener),則Listener 將隨Web 應(yīng)用的啟動而啟動。

          配置Listener 時使用<listener/>元素,下面是配置Listener 的片段:

          <!-- 配置Listener-->

          <listener>

          <!- 指定Listener 的實現(xiàn)類→

          <listener-class>lee.ScheduleListener</listener-class>

          </listener>

          在上面的配置中,既無須配置Listener 的名字,也無須配置Listener 的URL 只需配置它的實現(xiàn)類即可。此時容器將自動檢測部署在容器中的Listener,并在應(yīng)用啟動時,自動加載所有的Listener。



          作者:hoojo
          出處:
          blog:http://blog.csdn.net/IBM_hoojo
                   http://hoojo.cnblogs.com
          本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。


          版權(quán)所有,轉(zhuǎn)載請注明出處 本文出自:
          分享道版權(quán)所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處,謝謝
          posted on 2012-01-29 15:50 hoojo 閱讀(2208) 評論(5)  編輯  收藏 所屬分類: JavaEEJsp/Servlet

          評論:
          # re: Servlet 手記[未登錄] 2012-01-30 10:56 | tbw
          不錯 一直關(guān)注   回復(fù)  更多評論
            
          # re: Servlet 手記 2012-02-01 15:19 | 日出星辰
          差距!使用Java快2年了,servlet&jsp是每個java開發(fā)人員必須會的,但樓主能把這么簡單的東西總結(jié)的這么詳細、明白,自嘆不如!
          越簡單的東西越重要啊!向樓主學(xué)習(xí)!  回復(fù)  更多評論
            
          # re: Servlet 手記 2012-02-01 16:22 | hoojo
          @日出星辰
          也是看書、加上之前開發(fā)總結(jié)的一下基礎(chǔ)性的東西,謝謝支持~  回復(fù)  更多評論
            
          # re: Servlet 手記 2012-02-03 23:39 | allenny
          Servlce和JSP的區(qū)別總結(jié)的一塌糊涂  回復(fù)  更多評論
            
          # re: Servlet 手記 2012-02-11 13:35 | hoojo
          @allenny
          怎么講~也只是籠統(tǒng)的概括下  回復(fù)  更多評論
            
          主站蜘蛛池模板: 康保县| 高青县| 德阳市| 松阳县| 葫芦岛市| 万全县| 正阳县| 武定县| 太仓市| 襄城县| 华宁县| 都安| 盖州市| 济南市| 抚远县| 新宁县| 信丰县| 临西县| 通化市| 专栏| 西乌珠穆沁旗| 黄大仙区| 遵化市| 台中县| 芦山县| 双城市| 黄平县| 尤溪县| 淳化县| 巨野县| 吉木萨尔县| 贵港市| 和硕县| 百色市| 方山县| 疏勒县| 乐清市| 博湖县| 龙海市| 资兴市| 襄樊市|