1. 程式人生 > >web.xml中filter的用法

web.xml中filter的用法

Servlet API的2.3版本中最重要的一個新功能就是能夠為servlet和JSP頁面定義過濾器。過濾器提供了某些早期伺服器所支援的非標準“servlet連結”的一種功能強大且標準的替代品。
   過濾器是一個程式,它先於與之相關的servlet或JSP頁面執行在伺服器上。過濾器可附加到一個或多個servlet或JSP頁面上,並且可以檢查進入這些資源的請求資訊。在這之後,過濾器可以作如下的選擇:

  1. 以常規的方式呼叫資源(即,呼叫servlet或JSP頁面)。
  2. 利用修改過的請求資訊呼叫資源。
  3. 呼叫資源,但在傳送響應到客戶機前對其進行修改。
  4. 阻止該資源呼叫,代之以轉到其他的資源,返回一個特定的狀態程式碼或生成替換輸出。
  •    過濾器只在與servlet規範2.3版相容的伺服器上有作用。如果你的Web應用需要支援舊版伺服器,就不能使用過濾器。
    1. 建立基本過濾器
    建立一個過濾器涉及下列五個步驟:
    1)建立一個實現Filter介面的類。這個類需要三個方法,分別是:doFilter、init和destroy。doFilter方法包含主要的過濾程式碼(見第2步),init方法建立設定操作,而destroy方法進行清楚。
    2)在doFilter方法中放入過濾行為。doFilter方法的第一個引數為ServletRequest物件。此物件給過濾器提供了對進入的資訊(包括表單資料、cookie和HTTP請求頭)的完全訪問。第二個引數為ServletResponse,通常在簡單的過濾器中忽略此引數。最後一個引數為FilterChain,如下一步所述,此引數用來呼叫servlet或JSP頁。
    3)呼叫FilterChain物件的doFilter方法。Filter介面的doFilter方法取一個FilterChain物件作為它的一個引數。在呼叫此物件的doFilter方法時,啟用下一個相關的過濾器。如果沒有另一個過濾器與servlet或JSP頁面關聯,則servlet或JSP頁面被啟用。
    4)對相應的servlet和JSP頁面註冊過濾器。在部署描述符檔案(web.xml)中使用filter和filter-mapping元素。
    5)禁用啟用器servlet。防止使用者利用預設servlet URL繞過過濾器設定。
    1.1 建立一個實現Filter介面的類
    所有過濾器都必須實現javax.servlet.Filter。這個介面包含三個方法,分別為doFilter、init和destroy。
    1、public void doFilter(ServletRequset request, 
    ServletResponse response,
    FilterChain chain)
    thows ServletException, IOException
    每當呼叫一個過濾器(即,每次請求與此過濾器相關的servlet或JSP頁面)時,就執行其doFilter方法。正是這個方法包含了大部分過濾邏輯。
    第一個引數為與傳入請求有關的ServletRequest。對於簡單的過濾器,大多數過濾邏輯是基於這個物件的。如果處理HTTP請求,並且需要訪問諸如getHeader或getCookies等在ServletRequest中無法得到的方法,就要把此物件構造成HttpServletRequest。
    第二個引數為ServletResponse。除了在兩個情形下要使用它以外,通常忽略這個引數。首先,如果希望完全阻塞對相關servlet或JSP頁面的訪問。可呼叫response.getWriter並直接傳送一個響應到客戶機。第7節給出詳細內容,第8節給出一個例子。其次,如果希望修改相關的servlet或JSP頁面的輸出,可把響應包含在一個收集所有傳送到它的輸出的物件中。然後,在呼叫serlvet或JSP頁面後,過濾器可檢查輸出,如果合適就修改它,之後傳送到客戶機。詳情請參閱第9節。
    DoFilter的最後一個引數為FilterChain物件。對此物件呼叫doFilter以啟用與servlet或JSP頁面相關的下一個過濾器。如果沒有另一個相關的過濾器,則對doFilter的呼叫啟用servlet或JSP本身。
    2、public void init(FilterConfig config)
    thows ServletException
    init方法只在此過濾器第一次初始化時執行,不是每次呼叫過濾器都執行它。對於簡單的過濾器,可提供此方法的一個空體,但有兩個原因需要使用init。首先,FilterConfig物件提供對servlet環境及web.xml檔案中指派的過濾器名的訪問。因此,普遍的辦法是利用init將FilterConfig物件存放在一個欄位中,以便doFilter方法能夠訪問servlet環境或過濾器名。這種處理在第3節描述。其次,FilterConfig物件具有一個getInitParameter方法,它能夠訪問部署描述符檔案(web.xml)中分配的過濾器初始化引數。初始化引數的使用在第5節中描述。
    3、public void destroy( )
    此方法在利用一個給定的過濾器物件永久地終止伺服器(如關閉伺服器)時呼叫。大多數過濾器簡單地為此方法提供一個空體,不過,可利用它來完成諸如關閉過濾器使用的檔案或資料庫連線池等清除任務。
    1.2 將過濾行為放入doFilter方法
    doFilter方法為大多數過濾器地關鍵部分。每當呼叫一個過濾器時,都要執行doFilter。對於大多數過濾器來說,doFilter執行的步驟是基於傳入的資訊的。因此,可能要利用作為doFilter的第一個引數提供的ServletRequest。這個物件常常構造為HttpServletRequest型別,以提供對該類的更特殊方法的訪問。
    1.3 呼叫FilterChain物件的doFilter方法
    Filter介面的doFilter方法以一個FilterChain物件作為它的第三個引數。在呼叫該物件的doFilter方法時,啟用下一個相關的過濾器。這個過程一般持續到鏈中最後一個過濾器為止。在最後一個過濾器呼叫其FilterChain物件的doFilter方法時,啟用servlet或頁面自身。
    但是,鏈中的任意過濾器都可以通過不呼叫其FilterChain的doFilter方法中斷這個過程。在這樣的情況下,不再呼叫JSP頁面的serlvet,並且中斷此呼叫過程的過濾器負責將輸出提供給客戶機。詳情請參閱第7節。
    1.4 對適當的servlet和JSP頁面註冊過濾器
    部署描述符檔案的2.3版本引入了兩個用於過濾器的元素,分別是:filter和filter-mapping。filter元素向系統註冊一個過濾物件,filter-mapping元素指定該過濾物件所應用的URL。
    1.filter元素
    filter元素位於部署描述符檔案(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六個可能的子元素:
    icon 這是一個可選的元素,它宣告IDE能夠使用的一個圖象檔案。
    filter-name 這是一個必需的元素,它給過濾器分配一個選定的名字。
    display-name 這是一個可選的元素,它給出IDE使用的短名稱。
    description 這也是一個可選的元素,它給出IDE的資訊,提供文字文件。
    filter-class 這是一個必需的元素,它指定過濾器實現類的完全限定名。
    init-param 這是一個可選的元素,它定義可利用FilterConfig的getInitParameter方法讀取的初始化引數。單個過濾器元素可包含多個init-param元素。

filter-mapping元素
filter-mapping元素位於web.xml檔案中filter元素之後serlvet元素之前。它包含如下三個可能的子元素::
l filter-name 這個必需的元素必須與用filter元素宣告時給予過濾器的名稱相匹配。
l url-pattern 此元素宣告一個以斜槓(/)開始的模式,它指定過濾器應用的URL。所有filter-mapping元素中必須提供url-pattern或servlet-name。但不能對單個filter-mapping元素提供多個url-pattern元素項。如果希望過濾器適用於多個模式,可重複整個filter-mapping元素。
l servlet-name 此元素給出一個名稱,此名稱必須與利用servlet元素給予servlet或JSP頁面的名稱相匹配。不能給單個filter-mapping元素提供多個servlet-name元素項。如果希望過濾器適合於多個servlet名,可重複這個filter-mapping元素。

基於以上的原理,在專案中遇到這樣一個問題,使用者只有登陸之後才能瀏覽resource目錄下的資源,而這些resource的地址都是靜態地址,這時候就用到了過濾器,

public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain chain) throws IOException, ServletException {
   HttpServletRequest request = (HttpServletRequest) req;
   HttpServletResponse response = (HttpServletResponse) res;
   HttpSession session=request.getSession();
   ServletContext application=session.getServletContext();
   
      if(session.getAttribute("userSession")==null)
      {
       response.sendRedirect("error/priv_error.jsp");
       return;
      }
      else
      {
       chain.doFilter(request, response);
      }

 }

web.xml中如下配置:

<filter>
      <filter-name>PrivFilter</filter-name>
      <filter-class>com.myPriv.filter.PrivFilter</filter-class>
   </filter>

<filter-mapping>
    <filter-name>PrivFilter</filter-name>
    <url-pattern>/resource/*</url-pattern>
</filter-mapping>

在過濾器程式中判斷到resource目錄下的請求的使用者session是否為空,如果空的話就跳轉出去;

=================filter下一些url-pattern,dispatche的用法==============

在研究liferay框架中看到Web.xml中加入了過濾器的標籤,可以根據頁面提交的URL地址進行過濾,發現有幾個新標籤沒用過,下面就介紹以下幾個過濾器的標籤用法:

<!-- 定義Filter --><filter>

<!-- Filter的名字 --><filter-name>log</filter-name>

<!-- Filter的實現類 --><filter-class>lee.LogFilter</filter-class> 

</filter>

<!-- 定義Filter攔截的URL地址 --><filter-mapping>

<!-- Filter的名字 --><filter-name>log</filter-name>

<!-- Filter負責攔截的URL 全部以/的請求,如果<url-pattern>/*.action </>,將會以攔截*.action的請求--><url-pattern>/*</url-pattern>

</filter-mapping>

在Servlet2.4中filter-mapping中加入了新的標籤<dispatcher> ,裡面有4個值即REQUEST, FORWARD,INCLUDE和ERROR,預設不寫這個標籤的時候是REQUEST,該標籤是根據客戶端傳過來的地址進行過濾,FORWARD方法傳過來的request方法可以攔截,<ERROR-PAGE>錯誤頁面傳過來的攔截,INCLUDE包含過來的過濾,一般REQUEST傳過來的攔截.該標籤可以加入多個.

下面例子是引用網上的:

例1:

Xml程式碼

  1. <filter-mapping>
  2. <filter-name>Logging Filter</filter-name>
  3. <url-pattern>/products/*</url-pattern>
  4. </filter-mapping>

這種情況下,過濾器將會作用於直接從客戶端發過來的以/products/…開始的請求。因為這裡沒有制定任何的< dispatcher >元素,預設值是REQUEST。
例2:

Xml程式碼

  1. <filter-mapping>
  2. <filter-name>Logging Filter</filter-name>
  3. <servlet-name>ProductServlet</servlet-name>
  4. <dispatcher>INCLUDE</dispatcher>
  5. </filter-mapping>

這種情況下,如果請求是通過request dispatcher的include方法傳遞過來的對ProductServlet的請求,則要經過這個過濾器的過濾。其它的諸如從客戶端直接過來的對ProductServlet的請求等都不需要經過這個過濾器。
指定filter的匹配方式有兩種方法:直接指定url-pattern和指定servlet,後者相當於把指定的servlet對應的url-pattern作為filter的匹配模式
filter的路徑匹配和servlet是一樣的,都遵循servlet規範中《SRV.11.2 Specification of Mappings》一節的說明
例3:

Xml程式碼

  1. <filter-mapping>
  2. <filter-name>Logging Filter</filter-name>
  3. <url-pattern>/products/*</url-pattern>
  4. <dispatcher>FORWARD</dispatcher>
  5. <dispatcher>REQUEST</dispatcher>
  6. </filter-mapping>

在這種情況下,如果請求是以/products/…開頭的,並且是通過request dispatcher的forward方法傳遞過來或者直接從客戶端傳遞過來的,則必須經過這個過濾器。