來源:視頻資料,網上博客
一、Filter概述
1.概念
Filter稱之爲過濾器,是用來做一些攔截的任務。客戶端每次向服務器發送資源請求時,都會被Filter攔截,只有當Filter同意請求時,纔可以訪問該資源。
- 客戶端發送http請求,進入到Filter攔截器中,進行相關業務邏輯
- 判定通行,進入到Servlet,Servlet執行完畢,又返回Filter,進行一些增強,最後響應回到服務器
- 判斷不通行,訪問超時
2.一些使用例子
登錄驗證、統一編碼處理、敏感字符過濾等等
二、快速入門
- 編寫java類實現Filter接口
- 複寫其方法
- 配置攔截路徑(使用註解或者是在web.xml中配置)
在web項目中,直接右鍵創建一個Filter,然後複寫裏面的doFilter方法,這裏使用註解的方式
//配置攔截路徑
@WebFilter("/*")
public class Filter implements javax.servlet.Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("訪問前使用了Filter");
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
在web.xml中配置
<filter>
<filter-name>demo1</filter-name>
<!-- 攔截器全限定類名 -->
<filter-class>com.Filter.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 攔截路徑 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
這樣就配置好了一個Filter過濾器
三、Filter的生命週期
我們發現,在要實現Filter類的3個方法,分別是init、doFilter、destroy這和Servlet很相似,這3個方法代表着Filter的生命週期
- init:在服務器啓動時,會創建Filter對象,這時會調用init方法,這個方法只執行一次,主要是用於加載資源
- doFilter:每一次請求被攔截資源時,會執行。執行多次
- destroy:在服務器關閉後,Filter對象被銷燬。如果服務器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
四、過濾器執行過程分析
當配置好過濾器,並且配置好需要攔截的資源目錄後(注意:這裏爲了簡便,說的都是隻有一個攔截器的情況),如果是服務器第一次啓動,那麼調用Filter的init方法,當客戶端訪問服務器的資源時,首先會執行doFilter方法,這個doFilter方法會傳遞一個FilterChain對象,這個對象也有一個doFilter方法,用於判定是否通行。在調用這個方法之前的代碼都是攔截前執行的代碼,這個方法之後的代碼在響應之後會執行,
也就是說chain.doFilter(req, resp);這行代碼就是個分界線,前面的代碼是攔截,後面的代碼是做一些響應時的增強
五、過濾器配置
1.攔截路徑寫法
- /index.jsp 只有訪問index.jsp資源時,過濾器纔會被執行,也就是攔截具體的資源路徑
- /user/* 攔截目錄訪問/user下的所有資源時,過濾器都會被執行
- *.jsp 訪問所有後綴名爲jsp資源時,過濾器都會被執行,後綴名攔截
- /* 攔截所有資源
2.攔截類型配置
(1)使用註解的方式
使用註解的方式配置的是dispatcherTypes值
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
String description() default "";
String displayName() default "";
WebInitParam[] initParams() default {};
String filterName() default "";
String smallIcon() default "";
String largeIcon() default "";
String[] servletNames() default {};
String[] value() default {};
String[] urlPatterns() default {};
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
boolean asyncSupported() default false;
}
public enum DispatcherType {
FORWARD,
INCLUDE,
REQUEST,
ASYNC,
ERROR;
private DispatcherType() {
}
}
可以看到dispatcherTypes的默認值是REQUEST,值得是瀏覽器直接請求資源。DispatcherType是一個枚舉類型,其值爲:
- FORWARD:轉發訪問資源
- INCLUDE:包含訪問資源
- ERROR:錯誤跳轉資源
- ASYNC:異步訪問資源
- REQUEST:默認值。瀏覽器直接請求資源
(2)web.xml配置
設置dispatcher標籤即可
六、配置多個過濾器
filter是支持配置多個過濾器的,只要該類i實現了過濾器的接口 javax.servlet.Filter就會被認爲是一個過濾器。那麼這裏涉及到一個過濾器鏈執行的先後順序問題,哪一個過濾器先執行,哪一個過濾器後執行。
當然如果過濾器的執行順序確定了,那麼請求和響應時過濾器執行的順序應該時剛好相反的,例如:
過濾器1
過濾器2
資源執行
過濾器2
過濾器1
對於不同的配置,有不同的判定先後順序的方法:
(1) 註解:按照類名的字符串比較規則比較,值小的先執行
(2) xml配置:filter-mapping誰定義在上邊,誰先執行
(3)即有註解,又有xml配置:那麼會優先執行web.xml中配置的Filter