更新時(shí)間:2020年09月18日14時(shí)56分 來源:傳智播客 瀏覽次數(shù):
在一個(gè)Web應(yīng)用程序中可以注冊(cè)多個(gè)Filter程序,每個(gè)Filter程序都可以針對(duì)某一個(gè)URL進(jìn)行攔截。如果多個(gè)Filter程序都對(duì)同一個(gè)URL進(jìn)行攔截,那么這些Filter就會(huì)組成一個(gè)Filter鏈(也叫過濾器鏈)。Filter鏈用FilterChain對(duì)象來表示,F(xiàn)ilterChain對(duì)象中有一個(gè)doFilter()方法,該方法作用就是讓Filter鏈上的當(dāng)前過濾器放行,請(qǐng)求進(jìn)入下一個(gè)Filter,接下來通過一個(gè)圖例來描述Filter鏈的攔截過程,如圖1所示。
圖1 Filter鏈
在圖1中,當(dāng)瀏覽器訪問Web服務(wù)器中的資源時(shí)需要經(jīng)過兩個(gè)過濾器Filter1和Filter2,首先Filter1會(huì)對(duì)這個(gè)請(qǐng)求進(jìn)行攔截,在Filter1過濾器中處理好請(qǐng)求后,通過調(diào)用Filter1的doFilter()方法將請(qǐng)求傳遞給Filter2,F(xiàn)ilter2將用戶請(qǐng)求處理后同樣調(diào)用doFilter()方法,最終將請(qǐng)求發(fā)送給目標(biāo)資源。當(dāng)Web服務(wù)器對(duì)這個(gè)請(qǐng)求做出響應(yīng)時(shí),也會(huì)被過濾器攔截,這個(gè)攔截順序與之前相反,最終將響應(yīng)結(jié)果發(fā)送給客戶端。
為了讓讀者更好的學(xué)習(xí)Filter鏈,接下來,通過一個(gè)案例,分步驟演示如何使用Filter鏈攔截MyServlet的同一個(gè)請(qǐng)求,具體如下:
(1)在chapter04工程的cn.itcast.chapter04.filter包中新建MyFilter01和MyFilter02,如例1和2所示。
例1 MyFilter01.java
1 package cn.itcast.chapter04.filter;
2 import java.io.*;
3 import javax.servlet.*;
4 public class MyFilter01 implements Filter {
5 public void destroy() {
6 // 過濾器對(duì)象在銷毀時(shí)自動(dòng)調(diào)用,釋放資源
7 }
8 public void doFilter(ServletRequest request, ServletResponse response,
9 FilterChain chain) throws IOException, ServletException {
10 // 用于攔截用戶的請(qǐng)求,如果和當(dāng)前過濾器的攔截路徑匹配,該方法會(huì)被調(diào)用
11 PrintWriter out=response.getWriter();
12 out.write("Hello MyFilter01</br>");
13 chain.doFilter(request, response);
14 }
15 public void init(FilterConfig fConfig) throws ServletException {
16 // 過濾器對(duì)象在初始化時(shí)調(diào)用,可以配置一些初始化參數(shù)
17 }
18 }
例2 MyFilter02.java
1 package cn.itcast.chapter04.filter;
2 import java.io.*;
3 import javax.servlet.Filter;
4 import javax.servlet.*;
5 public class MyFilter02 implements Filter {
6 public void destroy() {
7 // 過濾器對(duì)象在銷毀時(shí)自動(dòng)調(diào)用,釋放資源
8 }
9 public void doFilter(ServletRequest request, ServletResponse response,
10 FilterChain chain) throws IOException, ServletException {
11 // 用于攔截用戶的請(qǐng)求,如果和當(dāng)前過濾器的攔截路徑匹配,該方法會(huì)被調(diào)用
12 PrintWriter out=response.getWriter();
13 out.write("MyFilter02 Before</br>");
14 chain.doFilter(request, response);
15 out.write("</br>MyFilter02 After</br>");
16 }
17 public void init(FilterConfig fConfig) throws ServletException {
18 // 過濾器對(duì)象在初始化時(shí)調(diào)用,可以配置一些初始化參數(shù)
19 }
20 }
(2)在web.xml文件中將MyFilter01和MyFilter02注冊(cè)在MyServlet前面,具體如下所示:
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>cn.itcast.chapter04.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
<filter-name>MyFilter02</filter-name>
<filter-class>cn.itcast.chapter04.filter.MyFilter02</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>cn.itcast.chapter04.filter.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
(3)重新啟動(dòng)Tomcat服務(wù)器,在瀏覽器地址欄中輸入http://localhost:8080/chapter04/MyServlet,此時(shí),瀏覽器窗口中的顯示結(jié)果如圖2所示。
從圖2中可以看出,MyServlet首先被MyFilter01攔截了,打印出MyFilter01中的內(nèi)容,然后被MyFilter02攔截,直到 MyServlet被MyFilter02放行后,瀏覽器才顯示出MySerlvet中的輸出內(nèi)容。
需要注意的是,F(xiàn)ilter鏈中各個(gè)Filter的攔截順序與它們?cè)趙eb.xml文件中元素的映射順序一致,由于MyFilter01的元素位于MyFilter02的元素前面,因此用戶的訪問請(qǐng)求首先會(huì)被MyFilter01攔截,然后再被MyFilter02攔截。
猜你喜歡:
什么是filter?filter是用來做什么的?
北京校區(qū)