Filter

1.Filter是什麼?

1)JavaWEB 的一個重要組件,既可以對發送到 Servlet 的請求進行攔截,也可以對 Servlet 返回的響應進行攔截


2)Filter 是實現了 Filter 接口的 Java 類。與 Servlet 程序相似,它由 Servlet 容器進行調用和執行
3)Filter 程序需要在 web.xml 文件中進行註冊和設置它所能攔截的資源:Filter 程序可以攔截 Jsp, Servlet, 靜態圖片文件和靜態 html 文件


2.如何創建 Filter ,並運行 Filter

1)創建一個 Filter 類:實現 Filter 接口:public class HelloFilter implements 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;

public class HelloFilter implements Filter {

	@Override
	public void destroy() {
		System.out.println("destroy...");
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		System.out.println("doFilter...");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init...");
	}

}

2)在 web.xml 文件中配置並映射該 Filter,其中 url-pattern 指定了該 Filter 可以攔截哪些資源,既可以通過那些 url 可以訪問到該 Filter

(1)<dispatcher>指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認REQUEST. 可以設置多個<dispatcher> 子元素用來指定 Filter 對資源的多種調用方式進行攔截

①REQUEST:當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問時,那麼該過濾器就不會被調用。

②INCLUDE:如果目標資源是通過RequestDispatcher的include()方法訪問時,那麼該過濾器將被調用。除此之外,該過濾器不會被調用。

③FORWARD:如果目標資源是通過RequestDispatcher的forward()方法訪問時,那麼該過濾器將被調用,除此之外,該過濾器不會被調用。

④ERROR:如果目標資源是通過聲明式異常處理機制調用時,那麼該過濾器將被調用。除此之外,過濾器不會被調用。

	<!-- 註冊 Filter -->
	<filter>
		<filter-name>helloFilter</filter-name>
		<filter-class>com.javaweb.filter.HelloFilter</filter-class>
		
		<!-- 配置初始化參數 -->
		<init-param>
			<param-name>user</param-name>
			<param-value>root</param-value>
		</init-param>
	</filter>
	<!-- 配置 Filter -->
	<filter-mapping>
		<filter-name>helloFilter</filter-name>
		<url-pattern>/app1/hello.jsp</url-pattern>
	</filter-mapping>

3)Filter 相關的 API

(1)Filter 接口的:

①public void init(FilterConfig arg0):類似與  Servlet 的 init 方法,在創建 Filter 對象(Filter 對象在 Servlet 容器加載當前 WEB 應用時即被創建)後,立即被調用,且只被調用一次。該方法用於對當前的 Filter 進行初始化操作

----a. FilterConfig類似於 ServletConfig  String getFilterName() ServletContext getServletContext()   String getInitParameter(String name)   Enumeration getInitParameterNames()

----b. 可以在 web.xml 文件中配置當前 Filter 初始化參數,配置方式也和 Servlet 方式一致

②public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2):真正 Filter 的邏輯代碼需要寫在該方法中,每次攔截都會調用該方法。

----a. FilterChain : Filter 鏈,多個 Filter 可以構成一個 Filter 鏈。

---------void doFilter(ServletRequest request,ServletResponse response):把請求傳給 Filter 鏈的下一個 Filter,若當前 Filter 是Filter 鏈的最後一個 Filter,將把請求給目標 Servlet(或JSP)

----b. 多個 Filter 攔截順序和<filter-mapping> 配置順序有關,靠前的先被調用。

③public void destroy()

(2)自定義的 HttpFilter

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;

public abstract class HttpFilter implements Filter {

	private FilterConfig filterConfig;

	//不建議子類直接覆蓋,若直接覆蓋可能導致 FilterConfig 對象初始化失敗
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		this.filterConfig = filterConfig;
		init();
	}

	/**
	 * 供子類繼承的初始化方法,可以通過 getFilterConfig() 方法獲取 FilterConfige 對象
	 */
	protected void init() {}

	public FilterConfig getFilterConfig() {
		return filterConfig;
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse rep,
			FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) rep;
		doFilter(request, response, arg2);
	}

	public abstract void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException;

	@Override
	public void destroy() {
	}
}

3.典型應用

1)使瀏覽器不緩存頁面的過濾器:
(1)有 3 個 HTTP 響應頭字段都可以禁止瀏覽器緩存當前頁面,它們在 Servlet 中的示例代碼如下:response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache"); 
(2)並不是所有的瀏覽器都能完全支持上面的三個響應頭,因此最好是同時使用上面的三個響應頭

public class NoCache extends HttpFilter  {

	@Override
	public void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		response.setDateHeader("Expires",-1);
		response.setHeader("Cache-Control","no-cache");
		response.setHeader("Pragma","no-cache");
		
		chain.doFilter(request, response);
	}
}

2)字符編碼的過濾器:通過配置參數encoding指明使用何種字符編碼,以處理Html Form請求參數的中文問題

(1)

public class EncodingFilter extends HttpFilter {

	private String encoding;
	
	@Override
	protected void init() {
		encoding = getFilterConfig().getServletContext().getInitParameter("encoding");
	}

	public String getEncoding() {
		return encoding;
	}
	
	@Override
	public void doFilter(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		request.setCharacterEncoding(encoding);
		chain.doFilter(request, response);
	}
}
































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章