天天看點

【轉】 java.servlet.Filter的應用

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比以往

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/*