java.servlet.Filter的應用
轉自:http://ajava.org/course/servlet/1459.html
java.servlet.Filter的應用
關鍵字: Filter的應用
Filter 技術是servlet 2.3 新增加的功能.servlet2.3是sun公司與2000年10月釋出的,它的開發者包括許多個人和公司團體,充分展現了sun公司所倡導的代碼開放性原則.由于衆多的參與者的共同努力,servlet2.3比以往功能都強大了許多,而且性能也有了大幅提高.
它新增加的功能包括:
1. 應用程式生命周期事件控制;
2. 新的國際化;
3. 澄清了類的裝載規則;
4. 新的錯誤及 安全屬性;
5. 不贊成使用HttpUtils 類;
6. 各種有用的方法;
7. 闡明并擴充了幾個servlet DTD;
8. filter功能.
其中最重要的就是filter功能.它使使用者可以改變一個request和修改一個response. Filter 不是一個servlet,它不能産生一個response,它能夠在一個request到達servlet之前預處理request,也可以在離開servlet時處理response.換種說法,filter其實是一個”servlet chaining”(servlet 鍊).一個filter 包括:
1. 在servlet被調用之前截獲;
2. 在servlet被調用之前檢查servlet request;
3. 根據需要修改request頭和request資料;
4. 根據需要修改response頭和response資料;
5. 在servlet被調用之後截獲.
你能夠配置一個filter 到一個或多個servlet;單個servlet或servlet組能夠被多個filter 使用.幾個實用的filter 包括:使用者辨認filter,日志filter,稽核filter,加密filter,符号filter,能改變xml内容的XSLT filter等.
一個filter必須實作javax.servlet.Filter接口并定義三個方法:
1.void setFilterConfig(FilterConfig config) //設定filter 的配置對象;
2. FilterConfig getFilterConfig() //傳回filter的配置對象;
3. void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) //執行filter 的工作.
伺服器每次隻調用setFilterConfig方法一次準備filter 的處理;調用doFilter方法多次以處理不同的請求.FilterConfig接口有方法可以找到filter名字及初始化參數資訊. 伺服器可以設定FilterConfig為空來指明filter已經終結.
每一個filter從doFilter()方法中得到目前的request及response.在這個方法裡,可以進行任何的針對request及response的操作.(包括收集資料,包裝資料等).filter調用chain.doFilter()方法把控制權交給下一個filter.一個filter在doFilter()方法中結束.如果一個filter想停止request處理而獲得對response的完全的控制,那它可以不調用下一個filter.
一個filter可以包裝request 或response以改變幾個方法和提供使用者定制的屬性.Api2.3提供了HttpServletRequestWrapper 和HttpServletResponseWrapper來實作.它們能分派最初的request和response.如果要改變一個方法的特性,必須繼承wapper和重寫方法.下面是一段簡單的日志filter用來記錄所有request的持續時間.
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)); } } |
當server調用setFilterConfig(),filter儲存config資訊.在doFilter()方法中通過config資訊得到servletContext.如果要運作這個filter,必須去配置到web.xml中.以tomcat4.01為例:
log //filter 名字
LogFilter //filter class(上例的servlet) log
servletname
servletname
servletclass
servletname
*
把這個web.xml放到web-inf中(詳請參考tomcat幫助文檔).
當每次請求一個request時(如index.jsp),先到LogFilter中去并調用doFilter()方法,然後才到各自的servlet中去.如果是一個簡單的servlet(隻是一個頁面,無任何輸出語句),那麼可能的輸出是:
Request to /index.jsp: 10 Servlet和Filter的url比對以及url-pattern詳解
一,servlet容器對url的比對過程:
當一個請求發送到servlet容器的時候,容器先會将請求的url減去目前應用上下文的路徑作為servlet的映射url,比如我通路的是 http://localhost/test/aaa.html,我的應用上下文是test,容器會将 http://localhost/test去掉,剩下的/aaa.html部分拿來做servlet的映射比對。這個映射比對過程是有順序的,而且當有一個servlet比對成功以後,就不會去理會剩下的servlet了(filter不同,後文會提到)。其比對規則和順序如下:
1. 精确路徑比對。例子:比如servletA 的url-pattern為 /test,servletB的url-pattern為
package filter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
public class EncodingFilter implements Filter
{
protected FilterConfig filterConfig;
private String targetEncoding;
public EncodingFilter()
{
targetEncoding = "gb2312";//直接初始化0912
}
public void init(FilterConfig filterconfig) throws ServletException
{
filterConfig = filterconfig;
//targetEncoding = filterconfig.getInitParameter("encoding");//web.xml挂參初始化
}
public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException
{
HttpServletRequest httpservletrequest = (HttpServletRequest)servletrequest;
httpservletrequest.setCharacterEncoding(targetEncoding);
system.out.println("使用" targetEncoding "對請求進行編碼過濾");
filterchain.doFilter(servletrequest, servletresponse);
}
public void setFilterConfig(FilterConfig filterconfig)
{
filterConfig = filterconfig;
}
public void destroy()
{
filterConfig = null;
}
}
package filter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class ManageFilter implements Filter
{
String LOGIN_PAGE;
protected FilterConfig filterConfig;
public ManageFilter()
{
LOGIN_PAGE = "/login.jsp";
}
public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletrequest;
HttpServletResponse response = (HttpServletResponse) servletresponse;
HttpSession session = request.getSession();
String key = "";
try
{
//通過驗證時在session中存的一個标志
key = (String) session.getAttribute("key");
if (key!= null&&key.equals("ok"))
{
filterchain.doFilter(servletrequest, servletresponse);
}
else
{
response.sendRedirect(LOGIN_PAGE);
system.out.println("被攔截一個未認證的請求");
}
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
public void setFilterConfig(FilterConfig filterconfig)
{
filterConfig = filterconfig;
}
public void destroy()
{
filterConfig = null;
}
public void init(FilterConfig filterconfig)
throws ServletException
{
filterConfig = filterconfig;
}
}
2、在web.xml中做一些設定
code
filter.EncodingFilter
manage
filter.ManageFilter
code
/*
manage
<!-- <url-pattern>/ShuiBaoRHPWK_NEW/system/ruhepaiwukou/*</url-pattern>-->
/servlets-examples/*