filter簡介
1、 Filter中文意思爲過濾器。顧名思義,過濾器可在瀏覽器以及目標資源之間起到一個過濾的作用。例如:水淨化器,可以看成是生活中的一個過濾器,他可以將污水中的雜質過濾,從而使進入的污水變成淨水。
2、 對於WEB應用來說,過濾器是一個駐留在服務器中的WEB組件,他可以截取客戶端和WEB資源之間的請求和響應信息。
3、 WEB資源可能包括Servlet、JSP、HTML頁面等
4、 當服務器收到特定的請求後,會先將請求交給過濾器,程序員可以在過濾器中對請求信息進行讀取修改等操作,然後將請求信息再發送給目標資源。目標資源作出響應後,服務器會再次將響應轉交給過濾器,在過濾器中同樣可以對響應信息做一些操作,然後再將響應發送給服務器。
5、 也就是說過濾器可以在WEB資源收到請求之前,瀏覽器收到響應之前,對請求和響應信息做一些相應的操作。
6、 在一個WEB應用中可以部署多個過濾器,多個過濾器就組成了一個過濾器鏈,請求和響應必須在經過多個過濾器後才能到達目標;
7、 過濾器不是必須將請求傳送到下一個過濾器(或WEB資源),也可以自己來處理請求,發送響應。
Filter相關接口
1、 編寫Filter和編寫Servlet類似,都需要實現接口。
2、 編寫Filter需要實現Filter接口,Filter接口的主要方法有:
Filter接口,實現Filter需要實現該接口
1. init()方法用於初始化Filter
2. doFilter()作用和service()方法類似,是過濾請求和響應的主要方法。
3. destroy()用於在Filter對象被銷燬前做一些收尾工作。如:釋放資源等。
FilterConfig對象在服務器調用init()方法時傳遞進來。
1. getFilterName() 獲取Filter的名字
2. getServletContext() 獲取ServletContext對象(即application)
3. getInitParameter() 獲取Filter的初始化參數
4. getInitParameterNames() 獲取所有初始化參數的名字
FilterChain對象是在doFilter()方法被調用時作爲參數傳遞進來的。
1. doFilter()方法用於調用Filter鏈上的下一個過濾器,如果當前過濾器爲最後一個過濾器則將請求發送到目標資源。
創建Filter
1、實現Filter接口public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
System.out.println("Hello Filter");
}
@Override
public void destroy() {
}
}
2、在web.xml註冊Filter<filter>
<filter-name>HelloFilter</filter-name>
<filter-class>com.atguigu.web.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HelloFilter</filter-name>
<url-pattern>/index.html</url-pattern>
</filter-mapping>
(1) 我們編寫的這個Filter用來過濾發送到index.html的請求。
(2) 在doFilter()方法中我們只寫了一個打印語句,並沒有將請求轉交給目標資源處理。
(3) 所以這個過濾器的效果是我們將不能正常查看到index.html頁面,在訪問index.html時頁面上將會是一片空白。同時,控制檯將輸出Hello Filter。
(4) 如果想要index.html正確顯示,需要在輸出語句後,調用一個chain.doFilter(request, response)將請求放行。
(5) Filter的配置文件和Servlet的配置文件類似
a) filter-name 指定的是過濾器的名字
b) filter-class 指定的是過濾器的全類名
c) url-pattern 指定的是需要過濾器處理的請求地址
(6) 除此之外在filter-mapping還有一個子標籤dispatcher,該標籤用來指定需要Filter處理的請求類型,該標籤可以配置四個值:
a) <dispatcher>REQUEST</dispatcher>
用戶直接訪問資源時,會調用Filter
b) <dispatcher>FORWARD</dispatcher>
通過轉發訪問時,會調用Filter
c) <dispatcher>INCLUDE</dispatcher>
通過動態包含獲取時,會調用Filter
d) <dispatcher>ERROR</dispatcher>
當通過異常處理訪問頁面時,會調用Filter
(7) 這四種情況可以設置一個,也可以同時設置多個,如果不設置那麼默認爲REQUEST。
Filter的生命週期
Filter的生命週期和Servlet類似
a) 構造器:創建Filter實例是調用,Filter實例服務器一旦啓動就會被創建
b) init():實例創建後馬上被調用,用來對Filter做一些初始化的操作
c) doFilter():Filter的主要方法,用來完成過濾器主要功能的方法,每次訪問目標資源時都會調用。
d) destroy():服務器停止時調用,用來釋放資源。
Filter的目標資源
1、 Filter的目標資源指的是需要調用Filter來進行過濾處理的資源,例如上文我們配置的/index.html就是我們的目標資源,當我們訪問項目根目錄下的index.html時就會調用HelloFilter來進行過濾。
2、 目標資源的配置方式主要有兩種:
(1) 第一種:
a) 通過filter-mapping的url-pattern來配置
b) 這裏的配置和Servlet的url-pattern的規則相同
1) 精確匹配:/路徑/資源名。
如:/index.html 、/hello/index.jsp 、 /client/LoginServlet
精確匹配只要在請求地址完全一樣時纔會調用Filter
2) 路徑匹配:/路徑名/*
如:/hello/* 、/*
路徑匹配只要是所請求的資源是在設置的路徑下就會調用Filter
如:/hello/* 只要訪問項目根目錄/hello/ 下的任意資源就會調用Filter
如: /* 只要訪問項目根目錄下的資源就會調用Filter
3) 後綴匹配:*.後綴名
如:*.jsp 、*.html
後綴匹配只要訪問的資源路徑是以指定後綴結尾就會調用Filter
(2) 第二種
a) 通過filter-mapping中的servlet-name來指定要過濾的Servlet
b) 如:以下是一個項目中的web.xml配置文件,在項目中有一個Filter加做HelloFilter,一個Servlet叫做HelloServlet。在Filter的filter-mapping中增加了一個servlet-name標籤,將該標籤的值設置成Servlet的名字,在訪問Servlet時就會調用該過濾器過濾請求。
<filter>
<filter-name>HelloFilter</filter-name>
<filter-class>com.atguigu.web.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HelloFilter</filter-name>
<servlet-name>HelloServlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.atguigu.web.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
Filter的執行順序
我們可以爲一個資源配置多個Filter,當配置多個Filter以後就有一個執行順序的問題,實際執行順序是按照在web.xml文件中servlet-mapping的順序決定的,如果順序越靠前越先被調用。