SpringMVC 過濾器Filter使用解析


SpringMVC框架是一個成熟的優秀java web開發框架,學習研究框架設計有助於我們更好的理解和掌握spring MVC,設計和寫出更符合的結構和代碼。

本節主要是研讀SpringMVC框架中的過濾器設置,以編碼處理過濾器為例來學習框架內是怎樣設置過濾器的。

 

 

如上所示的spring-web.jar包結構所示, Spring的web包中中提供有很多過濾器,這些過濾器位於org.springframework.web.filter並且理所當然地實現了javax.servlet.Filter,

不過實現的方式有以下幾類

        (1) 直接實現Filter,這一類過濾器只有CompositeFilter;

        (2) 繼承抽象類GenericFilterBean,該類實現了javax.servlet.Filter,這一類的過濾器只有一個,即DelegatingFilterProxy;

        (3) 繼承抽象類OncePerRequestFilter,該類為GenericFilterBean的直接子類,這一類過濾器包括CharacterEncodingFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter和ShallowEtagHeaderFilter;

        (4) 繼承抽象類AbstractRequestLoggingFilter,該類為OncePerRequestFilter的直接子類,這一類過濾器包括CommonsRequestLoggingFilter、Log4jNestedDiagnosticContextFilter和ServletContextRequestLoggingFilter。

過濾器放在容器結構的什么位置?

過濾器放在web資源之前,可以在請求抵達它所應用的web資源(可以是一個Servlet、一個Jsp頁面,甚至是一個HTML頁面)之前截獲進入的請求,並且在它返回到客戶之前截獲輸出請求。Filter:用來攔截請求,處於客戶端與被請求資源之間,目的是重用代碼。Filter鏈,在web.xml中哪個先配置,哪個就先調用。在filter中也可以配置一些初始化參數。

Java中的Filter 並不是一個標准的Servlet ,它不能處理用戶請求,也不能對客戶端生成響應。 主要用於對HttpServletRequest 進行預處理,也可以對HttpServletResponse 進行后處理,是個典型的處理鏈。 

Filter 有如下幾個種類:

l  用戶授權的Filter: Filter 負責檢查用戶請求,根據請求過濾用戶非法請求。 

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

l  負責解碼的Filter: 包括對非標准編碼的請求解碼。 

l  能改變XML 內容的XSLTFilter 等。 

 

Filter 有如下幾個用處

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

l  根據需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數據。 

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

l  根據需要檢查HttpServletResponse ,可以修改HttpServletResponse 頭和數據。

 

創建一個Filter 只需兩個步驟
(1)創建Filter 處理類: 

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

 

創建Filter 必須實現javax.servlet.Filter 接口,在該接口中定義了三個方法。 
• void init(FilterConfig config): 用於完成Filter 的初始化。 
• void destroy(): 用於Filter 銷毀前,完成某些資源的回收。 
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 實現過濾功能,該方法就是對每個請求及響應增加的額外處理。 

過濾器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驅動。

參照編碼過濾器示例來查看怎么實現的

  1. 首先配置在web.xml文件里的規則如下
<!-- 編碼處理過濾器 -->

   <filter>

      <filter-name>encodingFilter</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>encodingFilter</filter-name>

       <url-pattern>*.do</url-pattern>

    </filter-mapping>

 

 

其中,filter-class 為過濾器Filter類,init-prama為注入的set參數

Filter-mapping中的url-pattern為過濾的url類型

 

類的繼承關系

CharacterEncodingFilter r類繼承了 OncePerRequestFilter

public class CharacterEncodingFilter extends OncePerRequestFilter

 

OncePerRequestFilter 類又繼承了GenericFilterBean

public abstract class OncePerRequestFilter extends GenericFilterBean

 

public abstract class GenericFilterBean implements

       Filter, BeanNameAware, EnvironmentAware, ServletContextAware, InitializingBean, DisposableBean

 

 

設置編碼的核心代碼為

@Override

   protected void doFilterInternal(

         HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

         throws ServletException, IOException {

 

      if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {

         request.setCharacterEncoding(this.encoding);

         if (this.forceEncoding) {

            response.setCharacterEncoding(this.encoding);

         }

      }

      filterChain.doFilter(request, response);

   }

 

 

 

其中filterChain為過濾器鏈,表示執行完這個過濾器之后接着執行下一個過濾器

區別

         我們在使用過濾器時,通常沒必要知道GenericFilterBean、OncePerRequestFilter和AbstractRequestLoggingFilter,但不防礙我們了解這幾個類,就上文所述,AbstractRequestLoggingFilter繼承自OncePerRequestFilter,OncePerRequestFilter繼承自GenericFilterBean,所以我們知道,genericFilterBean是任何類型的過濾器的一個比較方便的超類,這個類主要實現的就是從web.xml文件中取得init-param中設定的值,然后對Filter進行初始化(當然,其子類可以覆蓋init方法)。

         OncePerRequestFilter繼承自GenericFilterBean,那么它自然知道怎么去獲取配置文件中的屬性及其值,所以其重點不在於取值,而在於確保在接收到一個request后,每個filter只執行一次,它的子類只需要關注Filter的具體實現即doFilterInternal。

        AbstractRequestLoggingFilter是對OncePerRequestFilter的擴展,它除了遺傳了其父類及祖先類的所有功能外,還在doFilterInternal中決定了在過濾之前和之后執行的事件,它的子類關注的是beforeRequest和afterRequest。

       總體來說,這三個類分別執行了Filter的某部分功能,當然,具體如何執行由它們的子類規定,若你需要實現自己的過濾器,也可以根據上文所述繼承你所需要的類。

 


免責聲明!

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



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