JAVA WEB 三器之過濾器(Filter)


過濾器(Filter)

1. 簡介 

  過濾器可以動態地攔截請求和響應,以變換或使用包含在請求或響應中的信息,它是 Servlet 技術中最實用的技術,屬於系統級別,主要是利用函數的回調實現。對 Jsp, Servlet  靜態圖片文件或靜態 html 文件等進行攔截。主要應用的場景有:如實現 URL 級別的權限訪問控制、過濾敏感詞匯、壓縮響應信息、設置字符編碼等一些高級功能。

  它主要用於對用戶請求進行預處理,也可以對HttpServletResponse 進行后處理。使用Filter 的完整流程:Filter 對用戶請求進行預處理,接着將請求交給Servlet 進行處理並生成響應,最后Filter 再對服務器響應進行后處理。

  Filter功能:

  • 在HttpServletRequest 到達 Servlet 之前,攔截客戶的 HttpServletRequest 。 根據需要檢查 HttpServletRequest ,也可以修改HttpServletRequest 頭和數據。
  • 在HttpServletResponse 到達客戶端之前,攔截HttpServletResponse 。 根據需要檢查 HttpServletResponse ,也可以修改HttpServletResponse頭和數據。

2. 方法

序號 方法
1

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)

該方法完成實際的過濾操作,當客戶端請求方法與過濾器設置匹配的 URL 時,Servlet 容器將先調用過濾器的 doFilter 方法。

FilterChain 用戶訪問后續過濾器。

2

public void init(FilterConfig filterConfig)

web 應用程序啟動時,web 服務器將創建 Filter 的實例對象,並調用其 init 方法,讀取 web.xml 配置,完成對象的初始化功能,

從而為后續的用戶請求作好攔截的准備工作(filter 對象只會創建一次,init 方法也只會執行一次)。開發人員通過 init 方法的參數,

可獲得代表當前 filter 配置信息的 FilterConfig 對象。

3

public void destroy()

Servlet 容器在銷毀過濾器實例前調用該方法,在該方法中釋放 Servlet 過濾器占用的資源。

3. 應用順序

  web.xml 中的 filter-mapping 元素的順序決定了 Web 容器應用過濾器到 Servlet 的順序。

4. web.xml 文件配置信息

  • <filter> 指定一個過濾器。
    • <filter-name> 用於為過濾器指定一個名字,該元素的內容不能為空。
    • <filter-class> 元素用於指定過濾器的完整的限定類名。
    • <init-param> 元素用於為過濾器指定初始化參數,它的子元素 <param-name> 指定參數的名字,<param-value> 指定參數的值。
    • 在過濾器中,可以使用 FilterConfig 接口對象來訪問初始化參數。
  • <filter-mapping> 元素用於設置一個 Filter 所負責攔截的資源。一個 Filter 攔截的資源可通過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑
    • <filter-name> 子元素用於設置filter的注冊名稱。該值必須是在 <filter> 元素中聲明過的過濾器的名字
    • <url-pattern> 設置 filter 所攔截的請求路徑(過濾器關聯的 URL 樣式)
  • <servlet-name> 指定過濾器所攔截的 Servlet 名稱。
  • <dispatcher> 指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是 REQUESTINCLUDEFORWARD 和 ERROR 之一,默認 REQUEST。用戶可以設置多個 <dispatcher> 子元素用來指定 Filter 對資源的多種調用方式進行攔截。
  • <dispatcher> 子元素可以設置的值及其意義
    • REQUEST:當用戶直接訪問頁面時,Web 容器將會調用過濾器。如果目標資源是通過 RequestDispatcher 的 include() 或 forward() 方法訪問時,那么該過濾器就不會被調用。
    • INCLUDE:如果目標資源是通過 RequestDispatcher 的 include() 方法訪問時,那么該過濾器將被調用。除此之外,該過濾器不會被調用。
    • FORWARD:如果目標資源是通過 RequestDispatcher 的 forward() 方法訪問時,那么該過濾器將被調用,除此之外,該過濾器不會被調用。
    • ERROR:如果目標資源是通過聲明式異常處理機制調用時,那么該過濾器將被調用。除此之外,過濾器不會被調用。

5. 應用實例

(1)簡單結構

 1 public class AuthorityFilter implements Filter {
 2     
 3     /**
 4      * 銷毀
 5      */
 6     @Override
 7     public void destroy() {
 8         
 9     }
10 
11     @Override
12     public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
13             throws IOException, ServletException {
14         HttpServletRequest request = (HttpServletRequest) req;
15         HttpServletResponse response = (HttpServletResponse) resp;
16         HttpSession session = request.getSession();
17         
18         boolean flag = false;
19         if(xxx) {
20              flag = false;
21         } else {
22             flag = true;
23         }
24         if (flag) {
25             chain.doFilter(req, resp);
26             return;
27         } else {
28             // 這是返回403錯誤
29             response.sendError(HttpServletResponse.SC_FORBIDDEN, "");
30             return;
31         }
32     }
33 
34     /**
35      * 初始化
36      */
37     @Override
38     public void init(FilterConfig filterConfig) throws ServletException {
39         
40     }
41 
42 }            

web.xml 配置

1 <filter>
2     <filter-name>authorityFilter</filter-name>
3     <filter-class>com.jd.nw.filter.AuthorityFilter</filter-class>
4   </filter>
5   <filter-mapping>
6     <filter-name>authorityFilter</filter-name>
7     <url-pattern>*</url-pattern>
8   </filter-mapping>

(2)中文亂碼過濾器

項目使用spring框架時。當前台JSP頁面和Java代碼中使用了不同的字符集進行編碼的時候就會出現表單提交的數據或者上傳/下載中文名稱文件出現亂碼的問題,那就可以使用這個過濾器。

<filter>
    <filter-name>encoding</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><!--true:無論request是否指定了字符集,都是用encoding;false:如果request已指定一個字符集,則不使用encoding-->
        <param-value>false</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

(3) Spring + Hibernate 的 OpenSessionInViewFilter 控制 session 的開關

  當 hibernate + spring 配合使用的時候,如果設置了 lazy = true(延遲加載),那么在讀取數據的時候,當讀取了父數據后,hibernate 會自動關閉 session,這樣,當要使用與之關聯數據、子數據的時候,系統會拋出 lazyinit 的錯誤,這時就需要使用 spring 提供的OpenSessionInViewFilter 過濾器。

  OpenSessionInViewFilter 主要是保持 Session 狀態直到 request 將全部頁面發送到客戶端,直到請求結束后才關閉 session,這樣就可以解決延遲加載帶來的問題。

  注意:OpenSessionInViewFilter 配置要寫在 struts2 的配置前面。因為 tomcat 容器在加載過濾器的時候是按照順序加載的,如果配置文件先寫的是 struts2 的過濾器配置,然后才是 OpenSessionInViewFilter 過濾器配置,所以加載的順序導致,action 在獲得數據的時候 session 並沒有被 spring 管理。

 1 <filter>
 2     <filter-name>OpenSessionInViewFilter</filter-name>
 3     <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
 4     <init-param>
 5         <param-name>sessionFactoryBeanName</param-name><!-- 可缺省。默認是從spring容器中找id為sessionFactory的bean,如果id不為sessionFactory,則需要配置如下,此處SessionFactory為spring容器中的bean。 -->
 6         <param-value>sessionFactory</param-value>
 7     </init-param>
 8     <init-param>
 9         <param-name>singleSession</param-name><!-- singleSession默認為true,若設為false則等於沒用OpenSessionInView -->
10         <param-value>true</param-value>
11     </init-param>
12 </filter>
13 <filter-mapping>
14     <filter-name>OpenSessionInViewFilter</filter-name>
15     <url-pattern>*.do</url-pattern>
16 </filter-mapping>

6. 總結

  過濾器顧名思義是用來過濾的,Java 的過濾器能夠為我們提供系統級別的過濾,也就是說,能過濾所有的 web 請求,這一點,是攔截器無法做到的。在 Java Web 中,你傳入的 request,response 提前過濾掉一些信息,或者提前設置一些參數,然后再傳入 servlet 或者 action 進行業務邏輯,比如過濾掉非法 url,或者在傳入servlet或者struts的action前統一設置字符集,或者去除掉一些非法字符。filter  流程是線性的,url 傳來之后,檢查之后,可保持原來的流程繼續向下執行,被下一個 filter, servlet 接收。

 

參考資料:

https://www.cnblogs.com/CloverSH/p/4531492.html


免責聲明!

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



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