Filter過濾器
與Servlet一樣,Filter也是一門web開發中的三大核心技術之一。
見名知義,過濾器的功能其實很好理解:我允許你通過,你就能通過,不允許你通過,想通過門都沒有,當然想通過還是有辦法的,但是決定權在過濾器,說不定過濾器把你加工一下,你就能達到通過的標準了。
欸,差不多就這個意思。我們之前在編寫Servlet的時候,一遇到中文字符的請求或者響應都忘不了在一開始就加上下面兩句話保證在處理請求,發出響應的過程中編解碼統一,對吧:
//請求亂碼處理
request.setCharacterEncoding("utf-8");
//響應亂碼處理
response.setContentType("text/html;charset=utf-8");
試想,如果有好多好多的Servlet都需要這樣處理,是不是會比較麻煩呢,既然都需要,我完全可以在他們進入Servlet之前對請求進行一波加工,出來之後對響應也進行一波加工,會方便許多。
//可提取爲初始化參數,這裏默認utf-8了
private String encode = "utf-8";
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//全局響應亂碼解決
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding(encode);
response.setContentType("text/html;charset="+encode);
chain.doFilter(request, response);
}
這時候,就可以引出web中的過濾器了:一旦對方訪問的資源路徑正好和url-pattern配置的攔截路徑匹配,就將其request對象攔截,攔截之後可以選擇放行,也可以選擇增加一些小操作,通過過濾器,我們就能完成許多通用的操作,如登錄驗證、統一編碼處理等。
Filter接口
所有的自定義都必須實現javax.servlet.Filter
接口,下面是接口中定義的三個方法。
public interface Filter {
//web應用加載進容器,Filter對象創建之後,執行init方法初始化,用於加載資源,只執行一次。
void init(FilterConfig var1) throws ServletException;
//每次請求或響應被攔截時執行,可執行多次。
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
//web應用移除容器,服務器被正常關閉,則執行destroy方法,用於釋放資源,只執行一次。
void destroy();
}
參數詳解
FilterConfig var1
:代表當前Filter在web.xml中的配置信息對象。
ServletRequest var1
:攔截的請求對象。
ServletResponse var2
:攔截的響應對象。
FilterChain var3
:過濾器鏈,提供doFilter()
方法,放行過濾器。
定義Filter
【方式一】web.xml配置
- 創建一個Filter類,實現
javax.servlet.Filter
接口。
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("FilterDemo1.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo1.doFilter");
}
@Override
public void destroy() {
System.out.println("FilterDemo1.destroy");
}
}
- 在web.xml中配置。
<filter>
<filter-name>Filter1</filter-name>
<filter-class>com.my.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/*</url-pattern><!--攔截路徑/*表示攔截所有資源-->
</filter-mapping>
【方式二】註解配置
@WebFilter("/*")
public class FilterDemo1 implements Filter
生命週期
web應用被加載到容器中時,過濾器對象被創建,並執行init方法初始化。
過濾器對象創建之後,一直存在於內存中,每攔截一次請求或響應時都會執行doFilter方法。
執行doFilter方法之後,可以選擇對處理結果放行,處理邏輯依據具體情況。
直到web應用被移除容器,Filter對象纔會銷燬,在銷燬之前會執行destroy方法。
配置細節
【攔截路徑配置】:
- 具體資源路徑:
/index.jsp
只攔截index.jsp
。 - 攔截目錄:
/demo/*
攔截/demo
目錄下的所有資源。 - 後綴名攔截:
*.jsp
攔截所有後綴名爲.jsp
的資源。 - 攔截所有資源:
/*
攔截所有資源。
【攔截方式配置】:
註解設置dispatcherTypes
屬性,如:@WebFilter(value = "/FilterDemo4",dispatcherTypes = DispatcherType.REQUEST)
。
- REQUEST:瀏覽器直接請求資源(默認)
- FORWARD:轉發訪問資源
- INCLUDE:包含訪問資源
- ERROR:錯誤跳轉資源
- ASYNC:異步訪問資源
web.xml配置
- 設置
<dispatcher></dispatcher>
標籤,如:<dispatcher>REQUEST</dispatcher>
。
過濾器鏈
執行流程
執行順序
【註解配置】
過濾器先後順序,按照類名的字符串比較規則比較,值小的先執行,Filter1在Filter2之前執行。
【web.xml】配置
過濾器先後順序由<filter-mapping>
的配置順序決定,先配置的先攔截。