JavaEE--JavaWeb三大組件Servlet、Filter、Listener


  Servlet、Filter、Listener是JavaEE Web服務規定的服務器動態組件,由開發者編寫由Web容器創建,並保證單例以及線程安全性,其中加載順序為Linstener -> Fliter -> Servlet,與它們在web.xml中配置的順序沒有關系,<xx-mapping>的配置順序會影響到url在某一類組件的過濾順序。

一、Servlet 

  Servlet是用來處理客戶端請求的動態資源,也就是當我們在瀏覽器中鍵入一個地址回車跳轉后,請求就會被發送到對應的Servlet上進行處理。它是一個POJO類,在web容器的管理下實現對web請求的處理與分發。 

1.Servlet的任務

接收請求數據:我們都知道客戶端請求會被封裝成HttpServletRequest對象,里面包含了請求頭、參數等各種信息。

②處理請求:通常我們會在service、doPost或者doGet方法進行接收參數,並且調用業務層(service)的方法來處理請求。

③完成響應:處理完請求后,我們一般會轉發(forward)或者重定向(redirect)到某個頁面,轉發是HttpServletRequest中的方法,重定向是HttpServletResponse中的方法,兩者是有很大區別的。

2.Servlet的特性

  Servlet可以在第一次接收請求(訪問該Servlet的映射名)時被創建,也可以在服務器啟動時就被創建,這需要在web.xml的<servlet>標簽中添加一條配置信息 <load-on-startup>5</load-on-startup>,當值為0或者大於0時,表示容器在應用啟動時就加載這個servlet,當是一個負數時或者沒有指定時,則指示容器在該servlet被請求時才加載。

  對於Servlet來說它既是一個java類也是CGI(通用網關接口),面向瀏覽器時它屬於CGI,專長於處理瀏覽器請求數據,完全由服務器掌控,在服務器內部只允許一個對外的Servlet實例,並且服務器會通過手段來保證面向外界的Servlet是單例的!但不保證線程安全!Servlet面向JVM內部類似於普通java類,可以被多次實例化!服務器不保證此類情況的Servlet單實例。

3.Servlet的生命周期方法

  • void init(ServletConfig)

  servlet的初始化方法,只在創建servlet實例時候調用一次,Servlet是單例的,整個服務器就只創建一個同類型Servlet

  • void service(ServletRequest,ServletResponse)

  servlet的處理請求方法,在servle被請求時,會被馬上調用,每處理一次請求,就會被調用一次。ServletRequest類為請求類,ServletResponse類為響應類

  • void destory()

  servlet銷毀之前執行的方法,只執行一次,用於釋放servlet占有的資源,通常Servlet是沒什么可要釋放的,所以該方法一般都是空的

4.Servlet的其他重要方法

  • ServletConfig getServletConfig()

  獲取servlet的配置信息的方法,所謂的配置信息就是WEB-INF目錄下的web.xml中的servlet標簽里面的信息

  • String getServletInfo()

  獲取servlet的信息方法

5.Servlet的配置

 1 <servlet>  2   <servlet-name>LoginServlet</servlet-name>  3   <servlet-class>com.briup.estore.web.servlet.LoginServlet</servlet-class>  4   <!--配置Serlvet的初始化參數。且節點必須在load-on-startup節點的前面-->  5   <init-param>  6     <param-name>password</param-name>  7     <param-value>6379</param-value>  8   </init-param>  9   <load-on-startup>0</load-on-startup> 10   <!--上面的參數最小值應該為0,值越小表示服務器啟動時加載、初始化Servlet的順序,如果不聲明的話則該Servlet等到客戶端第一次請求它時再創建實例並初始化--> 11 </servlet> 12 13 <servlet-mapping> 14   <servlet-name>LoginServlet</servlet-name> 15   <url-pattern>/login</url-pattern> 16   <!--url-pattern的寫法: 17  1.使用“/”:表示url不能匹配其他資源時匹配該動態組件,即前面只能允許是‘/’,后面可以加任意的字符, 這種形式不會覆蓋任何其它的servlet。它僅僅替換了servlet容器中內建的默認servlet。 18  ‘/’在url能匹配到精確的其他組件時會失效,如hello/hello.jsp,此時只會響應該jsp並不會隨后訪問該組件 19 20     2.使用“*”:表示通配任何字符,它前面只允許是‘/’,后面只允許‘.’加任意字符,但是它不允許前后都有字符,這種形式將會覆蓋所有其它的servlet。不管你發出了什么樣的請求,最終都會在這個servlet中結束。 21  ‘/*’表示匹配所有url,此時會將其他精確的url覆蓋掉,此時只會響應該組件 22   --> 23 </servlet-mapping>   

二、Fliter

  Filter與Servlet在很多的方面極其相似,但是也有不同,例如Filter和Servlet一樣都又三個生命周期方法,同時他們在web.xml中的配置文件也是差不多的、 但是Servlet主要負責處理請求,而Filter主要負責攔截請求,和放行。Filter實際上是一個接口,定義了一套規則,等待具體的類來實現該接口,而具體的攔截操作還需要web容器來實現。

1.Filter四種攔截方式

①REQUEST:直接訪問目標資源時執行過濾器。包括:在地址欄中直接訪問、表單提交、超鏈接、重定向,只要在地址欄中可以看到目標資源的路徑,就是REQUEST;

②FORWARD:轉發訪問執行過濾器。包括RequestDispatcher#forward()方法、<jsp:forward>標簽都是轉發訪問;

③INCLUDE:包含訪問執行過濾器。包括RequestDispatcher#include()方法、<jsp:include>標簽都是包含訪問;

④ERROR:當目標資源在web.xml中配置為<error-page>中時,並且真的出現了異常,轉發到目標資源時,會執行過濾器。

2.url-mapping的寫法

  匹配規則有三種:

  • 精確匹配 —— 如/foo.htm,只會匹配foo.htm這個URL
  • 路徑匹配 —— 如/foo/*,會匹配以foo為前綴的URL
  • 后綴匹配 —— 如*.htm,會匹配所有以.htm為后綴的URL
  • <url-pattern>的其他寫法,如/foo/ ,/.htm ,/foo 都是不對的。

3.執行filter的順序

   如果有多個過濾器都匹配該請求,順序決定於web.xml filter-mapping的順序,在前面的先執行,后面的后執行

三、Listener

  Listener就是監聽器,我們在JavaSE開發或者Android開發時,經常會給按鈕加監聽器,當點擊這個按鈕就會觸發監聽事件,調用onClick方法,本質是方法回調。在JavaWeb的Listener也是這么個原理,但是它監聽的內容不同,它可以監聽Application、Session、Request對象,當這些對象發生變化就會調用對應的監聽方法。Listener與Filter一樣同樣是一個接口,定義了監聽的規則,等待實現類實現該接口,而具體的監聽事務完全由web容器實現。

1.ServletContext(監聽Application)

①生命周期監聽:ServletContextListener,它有兩個方法,一個在出生時調用,一個在死亡時調用;

  • void contextInitialized(ServletContextEvent sce):創建Servletcontext時
  • void contextDestroyed(ServletContextEvent sce):銷毀Servletcontext時

②屬性監聽:ServletContextAttributeListener,它有三個方法,一個在添加屬性時調用,一個在替換屬性時調用,最后一個是在移除屬性時調用。

  • void attributeAdded(ServletContextAttributeEvent event):添加屬性時;
  • void attributeReplaced(ServletContextAttributeEvent event):替換屬性時;
  • void attributeRemoved(ServletContextAttributeEvent event):移除屬性時;

2.HttpSession(監聽Session)

①生命周期監聽:HttpSessionListener,它有兩個方法,一個在出生時調用,一個在死亡時調用;

  • void sessionCreated(HttpSessionEvent se):創建session時
  • void sessionDestroyed(HttpSessionEvent se):銷毀session時

②屬性監聽:HttpSessioniAttributeListener,它有三個方法,一個在添加屬性時調用,一個在替換屬性時調用,最后一個是在移除屬性時調用。

  • void attributeAdded(HttpSessionBindingEvent event):添加屬性時;
  • void attributeReplaced(HttpSessionBindingEvent event):替換屬性時
  • void attributeRemoved(HttpSessionBindingEvent event):移除屬性時

3.ServletRequest(監聽Request)

①生命周期監聽:ServletRequestListener,它有兩個方法,一個在出生時調用,一個在死亡時調用;

  • void requestInitialized(ServletRequestEvent sre):創建request時
  • void requestDestroyed(ServletRequestEvent sre):銷毀request時

②屬性監聽:ServletRequestAttributeListener,它有三個方法,一個在添加屬性時調用,一個在替換屬性時調用,最后一個是在移除屬性時調用。

  • void attributeAdded(ServletRequestAttributeEvent srae):添加屬性時
  • void attributeReplaced(ServletRequestAttributeEvent srae):替換屬性時
  • void attributeRemoved(ServletRequestAttributeEvent srae):移除屬性時

4.感知Session監聽

①HttpSessionBindingListener監聽

  • 在需要監聽的實體類實現HttpSessionBindingListener接口
  • 重寫valueBound()方法,這方法是在當該實體類被放到Session中時,觸發該方法
  • 重寫valueUnbound()方法,這方法是在當該實體類從Session中被移除時,觸發該方法

②HttpSessionActivationListener監聽

  • 在需要監聽的實體類實現HttpSessionActivationListener接口
  • 重寫sessionWillPassivate()方法,這方法是在當該實體類被序列化時,觸發該方法
  • 重寫sessionDidActivate()方法,這方法是在當該實體類被反序列化時,觸發該方法

5.application與web三大組件加載以及初始化的關系

  在一個web應用程序中假定實現了所有的配置,服務器啟動時首先要加載的是web.xml文件,從中確定整個web應用的基本配置。整個web.xml加載過程以及服務器對象創建過程如下:

  1. 啟動一個WEB項目的時候,容器(如:Tomcat)會去讀它的配置文件web.xml.讀兩個節點: <listener></listener> 和 <context-param></context-param>(具體先讀哪個,尚不可知)。
  2. 緊接着,容器創建一個ServletContext(application),這個WEB項目所有部分都將共享這個上下文,它標識一個web應用,首先在堆中分配空間,但尚未初始化。
  3. 容器將<context-param></context-param>轉化為鍵值對,並交給ServletContext。
  4. 容器創建<listener></listener>中的類實例,並綁定需要監聽的事件,對於application、session的創建來說,監聽的是他們的init方法,類似於類的構造器方法,它為整個對象進行屬性初始化。
  5. 容器創建過濾器實例開啟對url進行過濾。
  6. 容器創建Servlet實例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM