JAVA學習篇--javaweb之Filter詳解

來源:互聯網
上載者:User


在DRP項目中,多次提到了Filter,它解決了字元集的統一設定以及統一控制簡單WebCache,從中我們可以體會到,它給我們帶來的好處不僅僅是減少代碼量這麼簡單,它的出現避免了我們每個頁面重複的編寫相同的代碼,減少了我們的工作量,而且給維護帶來了極大的便利,那麼它是如何?統一管理的呢?既然它能統一管理某些重複的操作,那麼它和AOP有什麼關係呢?

 

Filter簡介

 

ServletAPI中提供了一個Filter介面,開發web應用時,如果編寫的Java類實現了這個介面,則把這個java類稱之為過濾器Filter。

通過Filter技術,開發人員可以實現使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截。簡單說,就是可以實現web容器對某資源的訪問前截獲進行相關的處理,還可以在某資源向web容器返迴響應前進行截獲進行處理。

 

是filter調用關係的UML圖:


             


一個filter必須實現javax.servlet.Filter。

三個方法

1. voidsetFilterConfig(FilterConfig config) //設定filter 的設定物件;

2. FilterConfiggetFilterConfig() //返回filter的設定物件;

3. voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain) //執行filter的工作

 

Filter實現攔截的原理

 

Filter介面中有一個doFilter方法,當開發人員編寫好Filter類實現doFilter方法,並配置對哪個web資源進行攔截後,WEB伺服器每次在調用web資源的service方法之前(伺服器內部對資源的訪問機制決定的),都會先調用一下filter的doFilter方法。

 

應用舉例:

 

大量設定請求編碼


public class EncodingFilter implements Filter {        private String encoding = null;        public void destroy() {          encoding = null;      }        public void doFilter(ServletRequest request, ServletResponse response,              FilterChain chain) throws IOException, ServletException {          String encoding = getEncoding();          if (encoding == null){              encoding = "gb2312";          }          request.setCharacterEncoding(encoding);// 在請求裡設定上指定的編碼          chain.doFilter(request, response);  //通過控制對chain.doFilter的方法的調用,來決定是否需要訪問目標資源    }        public void init(FilterConfig filterConfig) throws ServletException {          this.encoding = filterConfig.getInitParameter("encoding");      }        private String getEncoding() {          return this.encoding;      }    }  

xml配置代碼


<filter>      <filter-name>EncodingFilter</filter-name>      <filter-class>com.logcd.filter.EncodingFilter</filter-class>      <init-param>         <param-name>encoding</param-name>         <param-value>gb2312</param-value>      </init-param>  </filter>    <filter-mapping>     <filter-name>EncodingFilter</filter-name>     <url-pattern>/*</url-pattern>  </filter-mapping>  

如上的程式碼完成的功能為,無論進入那個頁面,都要先執行EncodingFilter類的dofilter方法設定字元集

 

其中,doFilter()方法類似於Servlet介面的service()方法。當用戶端請求目標資源的時候,容器就會調用與這個目標資源相關聯的過濾器的doFilter()方法。

參數 request, response 為web 容器或 Filter 鏈的上一個 Filter 傳遞過來的請求和相應對象;參數 chain 代表當前 Filter 鏈的對象。

 

對於FilterChain介面,代表當前Filter鏈的對象。由容器實現,容器將其執行個體作為參數傳入過濾器對象的doFilter()方法中。

過濾器對象使用FilterChain對象調用過濾器鏈中的下一個過濾器,或者目標Servlet 程式去處理,也可以直接向用戶端返迴響應資訊,或者利用RequestDispatcher的forward()和include()方法,以及HttpServletResponse的sendRedirect()方法將請求轉向到其他資源。

這個方法的請求和響應參數的類型是 ServletRequest和ServletResponse,也就是說,過濾器的使用並不依賴於具體的協議。

 

Filter生命週期

 

和Servlet一樣,Filter的建立和銷毀也是由WEB伺服器負責。


與Servlet區別的是


1>在應用啟動的時候就進行裝載Filter類而servlet是在請求時才建立(但filter與Servlet的load-on-startup配置效果相同)。

2>容器建立好Filter對象執行個體後,調用init()方法。接著被Web容器儲存進應用級的集合容器中去了等待著,使用者訪問資源。

3>當使用者訪問的資源正好被Filter的url-pattern攔截時,容器會取出Filter類調用doFilter方法,下次或多次訪問被攔截的資源時,Web容器會直接取出指定Filter對象執行個體調用doFilter方法(Filter對象常駐留Web容器了)。

4>當應用服務被停止或重新裝載了,則會執行Filter的destroy方法,Filter對象銷毀。

 

Filter工作原理(執行流程)

     

    當用戶端發出Web資源的請求時,Web伺服器根據應用程式設定檔設定的過濾規則進行檢查,若客戶請求滿足過濾規則,則對客戶請求/響應進行攔截,對要求標頭和請求資料進行檢查或改動,並依次通過過濾器鏈,最後把請求/響應交給請求的Web資源處理。

    請求資訊在過濾器鏈中可以被修改,也可以根據條件讓請求不發往資源處理器,並直接向客戶機發回一個響應。當資源處理器完成了對資源的處理後,響應資訊將逐級逆向返回。同樣在這個過程中,使用者可以修改響應資訊,從而完成一定的任務。

    過濾鏈的好處是,執行過程中任何時候都可以打斷,只要不執行chain.doFilter()就不會再執行後面的過濾器和請求的內容。


                


針對多個過濾器來說,例如,EncodingFilter負責設定編碼,SecurityFilter負責控制許可權,伺服器會按照web.xml中過濾器定義的先後循序組裝成一條鏈,然後一次執行其中的doFilter()方法,在實際使用時,就要特別注意過濾鏈的執行順序問題,像EncodingFilter就一定要放在所有Filter之前,這樣才能確保在使用請求中的資料前設定正確的編碼。

 

總結:

 

對於filter的應用相信大家已經明白了,它主要的作用就是使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截,做一些處理,然後再調用目標程式,這樣做的好處是可以對一些公用的操作進行抽象,就拿設定字元集來說,如果不使用這種方式,我們每個頁面都要寫設定字元集的語句。不但麻煩而且維護困難,但是如果使用filter的話,只需要添加一個類,在xml中配置一下,如果不想使用了,將設定檔中的內容去除即可。

 

其實這就是一種AOP(Aspect OrientedProgramming),面向切面編程。它的主要的意圖是:將日誌記錄,效能統計,安全控制,交易處理,異常處理等代碼從商務邏輯代碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導商務邏輯的方法中,進而改變這些行為的時候不影響商務邏輯的代碼。

對於設定字元集來說,它並非是商務邏輯的內容,對於這些內容的處理我們就可以提取出來,使用filter進行整體設定,這種方式相當於對類中的內容做進一步的抽象,使我們的系統更加靈活,更加能應對變化!

 

解疑:

 

由於上篇部落格介紹的動態代理,就是一種符合AOP的一種體現,現在我們又說Filter也符合AOP,那麼大家一定會有一個疑問,動態代理和Filter處理問題的區別在哪裡呢?First既然都符合AOP思想,那麼一定都可以進行統一處理(其實核心就是做進一步抽象)。那麼區別呢?

 

從表現形式上來說,兩者確實很相似,同樣可以在你寫的jsp、servlet代碼的前後加入其它的動作,但是兩者是有本質區別的。

1、 filter基於回呼函數,我們需要實現的filter介面中doFilter方法就是回呼函數,而動態代理則基於java本身的反射機制,如果對這種形式不瞭解,可以去看看動態代理實現過程,這是aop的基礎。這是兩者最本質的區別。

2、 filter是依賴於servlet容器的,即只能在servlet容器中執行,很顯然沒有servlet容器就無法來回調doFilter方法。而動態代理與servlet容器無關。






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.