17.6Filter過濾器

一、Filter簡介

Filter也稱之為過濾器,它是Servlet技術(shù)中最激動人心的技術(shù),WEB開發(fā)人員通過Filter技術(shù),對web服務(wù)器管理的所有web資源:例如Jsp, Servlet, 靜態(tài)圖片文件或靜態(tài) html 文件等進行攔截,從而實現(xiàn)一些特殊的功能。例如實現(xiàn)URL級別的權(quán)限訪問控制、過濾敏感詞匯、壓縮響應信息等一些高級功能。

Servlet API中提供了一個Filter接口,開發(fā)web應用時,如果編寫的Java類實現(xiàn)了這個接口,則把這個java類稱之為過濾器Filter。通過 Filter技術(shù),開發(fā)人員可以實現(xiàn)用戶在訪問某個目標資源之前,對訪問的請求和響應進行攔截,如下所示:

Filter請求處理

在攔截器出來之前,F(xiàn)ilter是web開發(fā)的基礎(chǔ)核心,可以負責權(quán)限控制、日志記錄、字符集處理等等

二、Filter是如何實現(xiàn)攔截的?

Filter接口中有一個doFilter方法,當我們編寫好Filter,并配置對哪個web資源進行攔截后,WEB服務(wù)器每次在調(diào)用web 資源的service方法之前,都會先調(diào)用一下filter的doFilter方法,因此,在該方法內(nèi)編寫代碼可達到如下目的:

調(diào)用目標資源之前,讓一段代碼執(zhí)行。
1、是否調(diào)用目標資源(即是否讓用戶訪問web資源)。
2、調(diào)用目標資源之后,讓一段代碼執(zhí)行。
web服務(wù)器在調(diào)用doFilter方法時,會傳遞一個filterChain對象進來,filterChain對象是filter接口中最重 要的一個對象,它也提供了一個doFilter方法,開發(fā)人員可以根據(jù)需求決定是否調(diào)用此方法,調(diào)用該方法,則web服務(wù)器就會調(diào)用web資源的service方法,即web資源就會被訪問,否則web資源不會被訪問。

三、Filter開發(fā)入門

3.1、Filter開發(fā)步驟

Filter開發(fā)分為二個步驟:
1、編寫java類實現(xiàn)Filter接口,并實現(xiàn)其doFilter方法。
2、在 web.xml 文件中使用<filter>和<filter-mapping>元素對編寫的filter類進行注冊,并設(shè)置它所能攔截的資源。

下面以字符集處理的過濾器進行舉例。
在java開發(fā)中,經(jīng)常會遇到中文亂碼的問題,原因就是頁面提交的中文是ISO88590-1格式的,到后臺如果不進行轉(zhuǎn)碼,就會出現(xiàn)中文亂碼。但是不能每個請求都要手動轉(zhuǎn)碼吧,所以采用filter就可以輕松解決這個問題了。

public class CharacterEncodingFilter implements Filter {
    private FilterConfig filterConfig = null;
    //設(shè)置默認的字符編碼
    private String defaultCharset = "UTF-8";

    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String charset = filterConfig.getInitParameter("charset");
        if (charset == null) {
            charset = defaultCharset;
        }
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset=" + charset);
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        //得到過濾器的初始化配置信息
        this.filterConfig = filterConfig;
    }

    public void destroy() {

    }
}

原理就是在每個請求時,設(shè)置request和response的字符集都是UTF-8

3.2、Filter鏈

在一個web應用中,可以開發(fā)編寫多個Filter,這些Filter組合起來稱之為一個Filter鏈。

web服務(wù)器根據(jù) Filter在web.xml文件中的注冊順序,決定先調(diào)用哪個Filter,當?shù)谝粋€Filter的doFilter方法被調(diào)用時,web服務(wù)器會創(chuàng)建 一個代表Filter鏈的FilterChain對象傳遞給該方法。在doFilter方法中,開發(fā)人員如果調(diào)用了FilterChain對象的 doFilter方法,則web服務(wù)器會檢查FilterChain對象中是否還有filter,如果有,則調(diào)用第2個filter,如果沒有,則調(diào)用目 標資源。

四、Filter的生命周期

4.1、Filter的創(chuàng)建

Filter的創(chuàng)建和銷毀由WEB服務(wù)器負責。 web 應用程序啟動時,web 服務(wù)器將創(chuàng)建Filter 的實例對象,并調(diào)用其init方法,完成對象的初始化功能,從而為后續(xù)的用戶請求作好攔截的準備工作,filter對象只會創(chuàng)建一次,init方法也只會執(zhí)行一次。通過init方法的參數(shù),可獲得代表當前filter配置信息的FilterConfig對象。

4.2、Filter的銷毀

Web容器調(diào)用destroy方法銷毀Filter。destroy方法在Filter的生命周期中僅執(zhí)行一次。在destroy方法中,可以釋放過濾器使用的資源。

4.3、FilterConfig接口

用戶在配置filter時,可以使用<init-param>為filter配置一些初始化參數(shù),當web容器實例化Filter 對象,調(diào)用其init方法時,會把封裝了filter初始化參數(shù)的filterConfig對象傳遞進來。因此開發(fā)人員在編寫filter時,通過 filterConfig對象的方法,就可獲得:

  • 1、String getFilterName():得到filter的名稱。
  • 2、String getInitParameter(String name): 返回在部署描述中指定名稱的初始化參數(shù)的值。如果不存在返回null.
  • 3、Enumeration getInitParameterNames():返回過濾器的所有初始化參數(shù)的名字的枚舉集合。
  • 4、public ServletContext getServletContext():返回Servlet上下文對象的引用。

五、Filter的部署

Filter的部署分為兩個步驟:

  • 1、注冊Filter
  • 2、映射Filter

5.1、注冊Filter

開發(fā)好Filter之后,需要在web.xml文件中進行注冊,這樣才能夠被web服務(wù)器調(diào)用

在web.xml文件中注冊Filter范例:

 <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.critc.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>charset</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

5.2、映射Filter

在web.xml文件中注冊了Filter之后,還要在web.xml文件中映射Filter

<!--映射過濾器-->
   <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 1、<filter-mapping>元素用于設(shè)置一個 Filter 所負責攔截的資源。一個Filter攔截的資源可通過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑
  • 2、<filter-name>子元素用于設(shè)置filter的注冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字
  • 3、<url-pattern>設(shè)置 filter 所攔截的請求路徑(過濾器關(guān)聯(lián)的URL樣式)

現(xiàn)在有了SpringMVC的攔截器和Struts的攔截器,F(xiàn)ilter用的越來越少,不過原理還是要掌握的,便于讀懂歷史項目。

源碼下載

本例子詳細源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容