作者: 李文軍
Filter 技術(shù)是servlet 2.3 新增加的功能.servlet2.3是sun公司與2000年10月發(fā)布的,它的開發(fā)者包括許多個(gè)人和公司團(tuán)體,充分體現(xiàn)了sun公司所倡導(dǎo)的代碼開放性原則.由于眾多的參與者的共同努力,servlet2.3比以往功能都強(qiáng)大了許多,而且性能也有了大幅提高. 它新增加的功能包括: 1. 應(yīng)用程序生命周期事件控制; 2. 新的國(guó)際化; 3. 澄清了類的裝載規(guī)則; 4. 新的錯(cuò)誤及安全屬性; 5. 不贊成使用HttpUtils 類; 6. 各種有用的方法; 7. 闡明并擴(kuò)展了幾個(gè)servlet DTD; 8. filter功能. 其中最重要的就是filter功能.它使用戶可以改變一個(gè)request和修改一個(gè)response. Filter 不是一個(gè)servlet,它不能產(chǎn)生一個(gè)response,它能夠在一個(gè)request到達(dá)servlet之前預(yù)處理request,也可以在離開servlet時(shí)處理response.換種說(shuō)法,filter其實(shí)是一個(gè)”servlet chaining”(servlet 鏈).一個(gè)filter 包括: 1. 在servlet被調(diào)用之前截獲; 2. 在servlet被調(diào)用之前檢查servlet request; 3. 根據(jù)需要修改request頭和request數(shù)據(jù); 4. 根據(jù)需要修改response頭和response數(shù)據(jù); 5. 在servlet被調(diào)用之后截獲. 你能夠配置一個(gè)filter 到一個(gè)或多個(gè)servlet;單個(gè)servlet或servlet組能夠被多個(gè)filter 使用.幾個(gè)實(shí)用的filter 包括:用戶辨認(rèn)filter,日志filter,審核filter,加密filter,符號(hào)filter,能改變xml內(nèi)容的XSLT filter等. 一個(gè)filter必須實(shí)現(xiàn)javax.servlet.Filter接口并定義三個(gè)方法: 1.void setFilterConfig(FilterConfig config) //設(shè)置filter 的配置對(duì)象; 2. FilterConfig getFilterConfig() //返回filter的配置對(duì)象; 3. void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) //執(zhí)行filter 的工作. 服務(wù)器每次只調(diào)用setFilterConfig方法一次準(zhǔn)備filter 的處理;調(diào)用doFilter方法多次以處理不同的請(qǐng)求.FilterConfig接口有方法可以找到filter名字及初始化參數(shù)信息.服務(wù)器可以設(shè)置FilterConfig為空來(lái)指明filter已經(jīng)終結(jié). 每一個(gè)filter從doFilter()方法中得到當(dāng)前的request及response.在這個(gè)方法里,可以進(jìn)行任何的針對(duì)request及response的操作.(包括收集數(shù)據(jù),包裝數(shù)據(jù)等).filter調(diào)用chain.doFilter()方法把控制權(quán)交給下一個(gè)filter.一個(gè)filter在doFilter()方法中結(jié)束.如果一個(gè)filter想停止request處理而獲得對(duì)response的完全的控制,那它可以不調(diào)用下一個(gè)filter. 一個(gè)filter可以包裝request 或response以改變幾個(gè)方法和提供用戶定制的屬性.Api2.3提供了HttpServletRequestWrapper 和HttpServletResponseWrapper來(lái)實(shí)現(xiàn).它們能分派最初的request和response.如果要改變一個(gè)方法的特性,必須繼承wapper和重寫方法.下面是一段簡(jiǎn)單的日志filter用來(lái)記錄所有request的持續(xù)時(shí)間. public class LogFilter implements Filter { FilterConfig config;
public void setFilterConfig(FilterConfig config) { this.config = config; }
public FilterConfig getFilterConfig() { return config; }
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { ServletContext context = getFilterConfig().getServletContext(); long bef = System.currentTimeMillis(); chain.doFilter(req, res); // no chain parameter needed here long aft = System.currentTimeMillis(); context.log("Request to " + req.getRequestURI() + ": " + (aft-bef)); } } 當(dāng)server調(diào)用setFilterConfig(),filter保存config信息.在doFilter()方法中通過(guò)config信息得到servletContext.如果要運(yùn)行這個(gè)filter,必須去配置到web.xml中.以tomcat4.01為例: <filter> <filter-name> log //filter 名字 </filter-name> <filter-class> LogFilter //filter class(上例的servlet) </filter-class> </filter> <filter-mapping> <filter-name>log</filter-name> <servletname>servletname</servlet-name> </filter-mapping> <servlet> <servlet-name>servletname</servletname> <servletclass>servletclass</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletname</servlet-name> <url-pattern>*</url-pattern> </servlet-mapping>
把這個(gè)web.xml放到web-inf中(詳請(qǐng)參考tomcat幫助文檔). 當(dāng)每次請(qǐng)求一個(gè)request時(shí)(如index.jsp),先到LogFilter中去并調(diào)用doFilter()方法,然后才到各自的servlet中去.如果是一個(gè)簡(jiǎn)單的servlet(只是一個(gè)頁(yè)面,無(wú)任何輸出語(yǔ)句),那么可能的輸出是: Request to /index.jsp: 10
|