1. 程式人生 > >servlet——filter

servlet——filter

文章目錄

1 概述

Filter是Servlet規範的三大元件之一。顧名思義,就是過濾。可以在請求到達目標資源之前先對請求進行攔截過濾,即對請求進行一些處理;也可以在響應到達客戶端之前先對響應進行攔截過濾,即對響應進行一些處理。採用的責任鏈設計模式

2 生命週期

    Filter的生命週期與Servlet的生命週期類似,其主要生命週期階段有四個:Filter物件的建立、Filter物件的初始化、Filter執行doFilter()方法以及最終Filter物件被銷燬。
    Filter的整個生命週期過程的執行,均由Web伺服器負責管理。即Filter從建立到銷燬的整個過程中方法的呼叫,都是由Web伺服器負責呼叫執行的,程式設計師無法控制其執行流程。

3 Demo

1註冊filter

<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>fiter.MyFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/</url-pattern>
  </filter-mapping
>

2 實現Filter介面

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 做某些操作 request.setCharacterEncoding("utf-8"); // 責任鏈的引用 chain.doFilter(request,response); } @Override public void destroy() { } }

4 FilterChain

FilterChain介面類物件是被用於Tomcat等容器提供給開發者從檢視到資源過濾請求的呼叫鏈的物件。過濾器使用過濾器鏈來呼叫鏈中的下一個過濾器,如果正在呼叫的過濾器是鏈中的最後一個,則會直接呼叫鏈末尾端的資源。

5 Filter詳解

5.1 特點

  • Filter是單例多執行緒的。
  • Filter是在應用被載入時建立並初始化的,這是與Servlet不同的地方。Servlet是在該Servlet被第一次訪問時建立的。Filter與Servlet的共同點是,其無參構造器與init()方法只會執行一次。
  • 使用者每提交一次該Filter可以過濾的請求,伺服器就會執行一次doFilter()方法,即doFilter()方法可以被多次執行。
  • 當應用被停止時執行destroy()方法,Filter被銷燬,即destroy()方法只會執行一次。
  • 由於Filter是單例多執行緒的,所以為了保證其執行緒安全性,一般情況下是不為Filter類定義可修改的成員變數。因為每個執行緒均可修改這個成員變數,會出現執行緒安全問題。

5.2 dispatcher

  • 在中還有一個子標籤,用於設定過濾器的請求型別。其有四種取值,REQUEST、FORWARD、INCLUDE、ERROR。
  • FORWARD:若請求是由一個Servlet通過RequestDsipatcher的forward()方法所轉發的,那麼這個請求將被值為FORWARD的Filter所攔截。即當前Filter只會攔截由RequestDispatcher的forward()方法所轉發的請求。其他請求均不攔截。
  • INCLUDE:當前Fillter只會攔截由RequestDsipatcher的include()方法所轉發的請求。其他請求均不攔截。
  • REQUEST:表示當前過濾其只會攔截普通請求,但是對forward和include的跳轉不進行攔截。(預設值)
  • ERROR:表示當跳轉到指定的錯誤處理頁面時,這個跳轉請求會被當前過濾器攔截。

5.3 Filter執行原理

  • 當某資源的請求到達Web容器時,會先對請求進行解析,使用解析出來的URI作為比較物件,從Map(Map的key為的值,value為Filter例項物件的引用)中查詢是否存在相匹配的key。若存在,那麼讀取其value,即Filter物件的引用,將該引用存入到陣列中。然後繼續向後查詢,直到將該Map查詢完畢。這樣在陣列中就存在按照查詢順序排好序的Filter引用。
  • 陣列初始化完畢後,開始按照陣列元素順序進行執行。所以陣列中的Filter全部執行完畢之後,再跳轉到請求的目標資源。(陣列中存放著與請求相匹配的所有Filter)

5.4 說明

  • 若Filter為全路徑匹配方式,那麼url-pattern只能寫為/*,而不能夠寫為/。(寫為/,無論是靜態資源,還是動態資源都不起作用)
  • 標籤中可以不使用,但需要指定,即當前過濾器攔截的是對指定Servlet的請求。

6 應用

解決中文亂碼問題,過濾敏感詞、安全許可權檢查等

<filter>
   	<filter-name>CharacterEncodingFilter</filter-name>
   	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   	<init-param>
   		<param-name>encoding</param-name>
   		<param-value>UTF-8</param-value>
   	</init-param>
   	<init-param>
   		<param-name>forceEncoding</param-name>
   		<param-value>true</param-value>
   	</init-param>
</filter>
<filter-mapping>
   <filter-name>CharacterEncodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>