JavaWeb--Filter

一、基本概念

之前我們用一篇博文介紹了Servlet相關(guān)的知識,有了那篇博文的知識積淀,今天我們學(xué)習(xí)Filter將會非常輕松,因為Filter有很多地方和Servlet類似,下面在講Filter的時候,就閑話不絮了。

Filter稱之為過濾器,是用來做一些攔截的任務(wù)。比如客戶端請求服務(wù)器的某個資源時(可以是Servlet、JSP、HTML等等),我們可以攔截。當(dāng)服務(wù)器返回資源給客戶端的時候,我們也可以攔截。這樣我們就可以在調(diào)用資源之前和之后分別加入一些業(yè)務(wù)邏輯。

Filter的位置

當(dāng)我們對某個資源加上多個過濾器的時候,就形成了過濾鏈。請求(request)會依次通過鏈上的過濾器,響應(yīng)(response)會依次以相反的順序通過過濾器。

過濾鏈

二、樣例分析

和使用servlet一樣,要使用filter只需要兩步:1.編寫自己的filter,實現(xiàn)javax.servlet.Filter。2.在web.xml中注冊該filter。

TestFilter.java

public class TestFilter implements Filter {
    public TestFilter() {}
    
    public void init(FilterConfig fConfig) throws ServletException {}

    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("before doFilter");
        chain.doFilter(request, response);
        System.out.println("after doFilter");
    }
}

web.xml

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.nantang.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/test</url-pattern>
</filter-mapping>

假定我們在本機部署應(yīng)用,應(yīng)用上下文路徑是/demo,那么在瀏覽器里面輸入http://localhost:8080/demo/test。則在控制臺會輸出:"before doFilter"和"after doFilter"。這是我們的請求和響應(yīng)受到了攔截,在調(diào)用具體的Servlet或其他資源前后執(zhí)行了我們編寫的邏輯(例子中就是往控制臺打印信息)。

這里需要注意的是,filter可以對url進行過濾,也可以針對具體的servlet進行過濾,只需要制定servlet的名稱,如:

<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <servlet-name>TestServlet</servlet-name>
</filter-mapping>

三、源碼分析

我們自己編寫的filter都需要實現(xiàn)javax.servlet.Filter接口,下面我們看一下Filter接口的繼承層級,并逐一分析。

Filter源碼

1 FilterConfig

當(dāng)容器去初始化一個filter的時候,就會根據(jù)web.xml文件的配置和當(dāng)前的運行環(huán)境去構(gòu)造一個FilterCongif實例并傳給filter。所以一個filter對應(yīng)一個FilterConfig實例。

Filter層級
public interface FilterConfig {

    public String getFilterName();

    public ServletContext getServletContext();

    public String getInitParameter(String name);

    public Enumeration getInitParameterNames();
}

getFilterName方法返回我們在web.xml里面配置的名稱。

getServletContext返回ServletContext實例,這個和之前介紹Servlet的時候講到的是一個東西。一個應(yīng)用就一個ServletContext實例。

getInitParameter和getInitParameterNames和Servlet的類似。就是獲取在web.xml里面配置的初始化參數(shù),如:

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.nantang.filter.TestFilter</filter-class>
    <init-param>
        <param-name>param1</param-name>
        <param-value>1</param-value>
    </init-param>
    <init-param>
        <param-name>param2</param-name>
        <param-value>2</param-value>
    </init-param>
</filter>

2 FilterChain

FilterChain就是我們上面說的過濾鏈,當(dāng)請求或響應(yīng)被filter攔截時,容器提供FilterChain實例給filter讓其使用。

public interface FilterChain {
    
    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;
}

FilterChain里面就一個方法doFilter,這個方法就是調(diào)用過濾鏈的下一個filter,如果當(dāng)前filter是鏈中最后的一個,則跳轉(zhuǎn)至請求的資源或返回響應(yīng)給客戶端。

3 Filter

Filter里面就三個方法,也就是它的生命周期。和Servlet類似。

public interface Filter {

    public void init(FilterConfig filterConfig) throws ServletException;
    
    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;

    public void destroy();
}
Filter生命周期

3.1 init

filter的初始化方法,跟servlet一樣在其生命周期內(nèi)只會被執(zhí)行一次。但是filter初始化的時機和servlet不一樣,當(dāng)servlet容器(比如Tomcat)啟動完成后就會檢索web.xml里面配置的filter,從上往下依次回調(diào)每個filter的init方法對其進行初始化。(這里的filterConfig參數(shù)是容器構(gòu)造并傳入的。)

3.2 doFilter

實現(xiàn)攔截邏輯的地方,比如一個請求被攔截,這里可以在調(diào)用具體資源之前編寫一些業(yè)務(wù)邏輯。然后調(diào)用chain.doFilter流轉(zhuǎn)到后置filter,如果當(dāng)前filter是鏈中最后的一個,則跳轉(zhuǎn)至請求的資源。當(dāng)chain.doFilter執(zhí)行完成后,可以再寫一些業(yè)務(wù)邏輯。然后容器將執(zhí)行權(quán)流轉(zhuǎn)到前置filter,如果當(dāng)前filter是鏈中最前的一個,則將響應(yīng)返回給客戶端。(這里的參數(shù)chain是容器構(gòu)造并傳入的。)

3.3 destory

和servlet的destroy方法同樣的道理,當(dāng)servlet容器關(guān)閉或需要更多內(nèi)存的時候,會銷毀filter。這個方法就使得servlet容器擁有回收資源的能力。
同樣地,destroy方法在filter的生命周期中只會被調(diào)用一次。

四、總結(jié)

到這里filter就算結(jié)束了,我們可以發(fā)現(xiàn)filter的執(zhí)行模型和servlet很類似,都是servlet容器在調(diào)度。整個生命周期都是容器在管控。

?著作權(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)容