Filter,FilterChain,FilterConfig
實例:
package com.zillion.app.filter;import java.io.IOException;import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger;import com.util.AppConfig; import com.util.SpringContextUtil; import com.util.ThreadlocalUtil; /*** loginToken攔截處理器**/ public class LoginTokenFilter implements Filter{private static final Logger log = Logger.getLogger(LoginTokenFilter.class);@Overridepublic void destroy() {// TODO Auto-generated method stub }@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {try{HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;boolean isOptions = StringUtils.equals("OPTIONS", request.getMethod());ThreadlocalUtil.setIsOptions(isOptions);ThreadlocalUtil.setNewVersion(false);//跨域設置AppConfig appConfig = (AppConfig) SpringContextUtil.getBean("appConfig");if(StringUtils.equals("1", appConfig.getCrossDomainFlag())){response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "x-requested-with");response.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept,X-Requested-With,POWERED-BY-MENGXIANHUI,logintoken,userID");}chain.doFilter(request, res);} catch (Exception e){log.error("LoginTokenFilter is error!",e);throw e;}}@Overridepublic void init(FilterConfig arg0) throws ServletException {}} <!-- loginToken : http-header中的轉換到request參數中 --><filter><filter-name>loginTokenFilter</filter-name><filter-class>com.zillion.app.filter.LoginTokenFilter</filter-class></filter><filter-mapping><filter-name>loginTokenFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>?
?
一、Filter的基本工作原理
1、Filter程序是一個實現了特殊接口的Java類,與Servlet類似,也是由Servlet容器進行調用和執行的。
2、當在web.xml注冊了一個Filter來對某個Servlet程序進行攔截處理時,它可以決定是否將請求繼續傳遞給Servlet程序,以及對請求和響應消息是否進行修改。
3、當Servlet容器開始調用某個Servlet程序時,如果發現已經注冊了一個Filter程序來對該Servlet進行攔截,那么容器不再直接調用Servlet的service方法,而是調用Filter的doFilter方法,再由doFilter方法決定是否去激活service方法。
4、但在Filter.doFilter方法中不能直接調用Servlet的service方法,而是調用FilterChain.doFilter方法來激活目標Servlet的service方法,FilterChain對象時通過Filter.doFilter方法的參數傳遞進來的。
5、只要在Filter.doFilter方法中調用FilterChain.doFilter方法的語句前后增加某些程序代碼,這樣就可以在Servlet進行響應前后實現某些特殊功能。
6、如果在Filter.doFilter方法中沒有調用FilterChain.doFilter方法,則目標Servlet的service方法不會被執行,這樣通過Filter就可以阻止某些非法的訪問請求。
二、Filter鏈
1、在一個Web應用程序中可以注冊多個Filter程序,每個Filter程序都可以對一個或一組Servlet程序進行攔截。如果有多個Filter程序都可以對某個Servlet程序的訪問過程進行攔截,當針對該Servlet的訪問請求到達時,Web容器將把這多個Filter程序組合成一個Filter鏈(也叫過濾器鏈)。
2、Filter鏈中的各個Filter的攔截順序與它們在web.xml文件中的映射順序一致,上一個Filter.doFilter方法中調用FilterChain.doFilter方法將激活下一個Filter的doFilter方法,最后一個Filter.doFilter方法中調用的FilterChain.doFilter方法將激活目標Servlet的service方法。
3、只要Filter鏈中任意一個Filter沒有調用FilterChain.doFilter方法,則目標Servlet的service方法都不會被執行。
三、Filter接口
一個Filter程序就是一個Java類,這個類必須實現Filter接口。javax.servlet.Filter接口中定義了三個方法:init、doFilter、destory。
1、init方法
(1)、在Web應用程序啟動時,Web服務器(Web容器)將根據其web.xml文件的配置信息來創建每個注冊的Filter的實例對象,并將其保存在內存中。
(2)、Web容器創建Filter的實例對象后,將立即調用該Filter對象的init方法。init方法在Filter生命周期中僅被執行一次,Web容器在調用init方法時,會傳遞一個包含Filter的配置和運行環境信息的FilterConfig對象。
?(3)開發人員可以在init方法中完成與構造方法類似的初始化功能,要注意的是:如果初始化代碼要使用到FilterConfig對象,這些代碼只能在init方法中編寫,而不能在構造方法中編寫(尚未調用init方法,即并沒有創建FilterConfig對象,要使用它則必然出錯)。
2、doFilter方法
當一個Filter對象能夠攔截訪問請求時,Servlet容器將調用Filter對象的doFilter方法。
?其中,參數request和response為Web容器或Filter鏈中上一個Filter傳遞過來的請求和響應對象;參數chain為代表當前Filter鏈的對象
3、destroy方法
該方法在Web容器卸載Filter對象之前被調用,也僅執行一次。可以完成與init方法相反的功能,釋放被該Filter對象打開的資源,例如:關閉數據庫連接和IO流。
四、FilterChain接口
該接口用于定義一個Filter鏈的對象應該對外提供的方法,這個接口只定義了一個doFilter方法。
?FilterChain接口的doFilter方法用于通知Web容器把請求交給Filter鏈中的下一個Filter去處理,如果當前調用此方法的Filter對象是Filter鏈中的最后一個Filter,那么將把請求交給目標Servlet程序去處理。
五、FilterConfig接口
1、與普通的Servlet程序一樣,Filter程序也很可能需要訪問Servlet容器。Servlet規范將代表ServletContext對象和Filter的配置參數信息都封裝到一個稱為FilterConfig的對象中。
2、FilterConfig接口則用于定義FilterConfig對象應該對外提供的方法,以便在Filter程序中可以調用這些方法來獲取ServletContext對象,以及獲取在web.xml文件中為Filter設置的友好名稱和初始化參數。
3、FilterConfig接口定義的各個方法:
-
getFilterName方法,返回<filter-name>元素的設置值。
-
getServletContext方法,返回FilterConfig對象中所包裝的ServletContext對象的引用。
-
getInitParameter方法,用于返回在web.xml文件中為Filter所設置的某個名稱的初始化的參數值。
-
getInitParameterNames方法,返回一個Enumeration集合對象。
六、Filter的注冊與映射
1、注冊Filter
一個<filter>元素用于注冊一個Filter。其中,<filter-name>元素是必需的,<filter-class>元素也是必需的,<init-param>元素是可選的,可以有多個<init-param>元素。
?2、映射Filter
<filter-mapping>元素用于設置一個Filter所負責攔截的資源。一個Filter攔截的資源可以通過兩種方式來指定:資源的訪問請求路徑和Servlet名稱。
第一種:指定資源的訪問路徑
?<url-pattern>元素中的訪問路徑的設置方式遵循Servlet的URL映射規范。http://my.oschina.net/u/1171518/blog/220147。eg:
/*:表示攔截所有的訪問請求
/filter/*:表示攔截filter目錄下的所有訪問請求,如:http://localhost:8888/testFilter_001/filter/xxxxxx
/test.html:表示攔截根目錄下以test.html為資源名的訪問請求,訪問鏈接只會是:http://localhost:8888/test.html
第二種:指定Servlet的名稱
?(1)、<servlet-name>元素與<url-pattern>元素是二選一的關系,其值是某個Servlet在web.xml文件中的注冊名稱。
(2)、<dispatcher>元素的設置值有4種:REQUEST、INCLUDE、FORWARD、ERROR,分別對應Servlet容器調用資源的4種方式:
-
通過正常的訪問請求調用;
-
通過RequestDispatcher.include方法調用;
-
通過RequestDispatcher.forward方法調用;
-
作為錯誤響應資源調用。
如果沒有設置<dispatcher>子元素,則等效于REQUEST的情況。也可以設置多個<dispatcher>子元素,用于指定Filter對資源的多種調用方式都進行攔截。
七、Filter程序示例
1、
FitstFilter.java
?web.xml
?test.html(位于WebContent路徑的filter目錄中)
?訪問:http://localhost:8888/testFilter_001/filter/test.html
瀏覽器顯示頁面:
?
Tomcat后臺(第一次訪問):
?
2、
把FirstFilter.java中如下語句的注釋去掉:(整個過程,并未特意或無意改變了test.html文件的內容)
?
等Tomcat Reload完成,刷新頁面,驚奇地發現瀏覽器頁面并未發生改變,Tomcat后天多了三個請求頭:
原因(存在疑問,是否真的是If-Modified-Since標簽來決定是否采用緩存):
(1)、緩存里存儲的不只是網頁文件,還有服務器發過來的該文件的最后服務器修改時間;
(2)、客戶端發HTTP請求時,使用If-Modified-Since標簽,把上次服務器告訴它的文件最后修改時間返回到服務器端了;
(3)、服務器會把這個時間與服務器上實際文件的最后修改時間進行比較;
(4)、如果時間一致,那么返回HTTP狀態碼304,盡管FirstFilter程序在攔截處理中向ServletResponse對象中寫入的數據也傳送給了瀏覽器。但是瀏覽器因為收到304則顯示原來緩存的內容;
(5)、如果時間不一致,就返回HTTP狀態碼200,瀏覽器接到之后,會丟棄舊文件,把新文件緩存起來,并顯示到瀏覽器中。
解決:
在test.html文件中增加一個空格又刪去這個空格,造成text.html文件被修改過的假象,然后在瀏覽器刷新test.html頁面的訪問。
轉載于:https://www.cnblogs.com/therunningfish/p/6639192.html
總結
以上是生活随笔為你收集整理的Filter,FilterChain,FilterConfig的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【bzoj2705】[SDOI2012]
- 下一篇: jsp内置对象+Servlet