javaweb之Filter過濾器詳解


快速入門
1、新建一個類,實現Filter接口
2、實現doFilter()方法,打印一句話,來證明能夠進行攔截
3、在web.xml中進行配置(參照Servlet配置)
4、訪問一個頁面,看看能不能攔截

例子:

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 javax.servlet.http.HttpSession;

public class UserFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
	}


	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// 獲取session對象,判斷是否登錄
		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse res=(HttpServletResponse)response;
		HttpSession session = req.getSession();
		if(session.getAttribute("user")==null){
			// 非法訪問,沒有登錄,跳轉到登錄頁面
			session.setAttribute("error","非法訪問");
			// 保存客戶想要去的地址, 登錄成功后則直接跳轉,而不是到首頁
			// 獲取請求的地址, 包括工程名,但是不包括參數
			System.out.println(req.getRequestURI());
			// 獲取請求的參數
			System.out.println("參數:" + req.getQueryString());
			// 獲取當前項目的絕對路徑,方法已過時,不推薦使用 推薦使用  request.getServletContext().getRealPath("")
			System.out.println(req.getRealPath(""));
			// 獲取請求的地址, 但是不包括工程名和參數
			System.out.println(req.getServletPath());
			// 此方法需要在servlet 3.0的版本上使用, 開發的環境需要J2EE6 運行需要Tomcate7.0
			//System.out.println("request.getServletContext().getRealPath:" +request.getServletContext().getRealPath(""));
			String goURL=req.getServletPath();
			if(req.getQueryString()!=null){
				goURL += "?" + req.getQueryString();
			}
			System.out.println(goURL);
			session.setAttribute("goURL", goURL);
			res.sendRedirect(req.getContextPath() + "/login.jsp");
			System.out.println(req.getContextPath());
		}else{
			// 如果有下一個過濾器則跳轉到下一個過濾器否則目標頁面
			chain.doFilter(request, response);
		}
	}
}

 在web.xml中進行配置

<filter>
  	<filter-name>userFilter</filter-name>
  	<filter-class>
  		cn.***.UserFilter
  	</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>userFilter</filter-name>
  	<url-pattern>/user/*</url-pattern>
    <dispatcher>REQUEST</dispatcher> <!-- 沒有配置dispatcher就是默認request方式的 -->        <dispatcher>FORWARD</dispatcher>        <dispatcher>ERROR</dispatcher>        <dispatcher>INCLUDE</dispatcher> </filter-mapping>

 四、Filter的應用場景
   通過對filter過濾器的了解,可以得知在以下三種情況下可以做些處理:
    1> 通過控制對chain.doFilter的方法的調用,來決定是否需要訪問目標資源。
  比如,可以在用戶權限驗證等等。判斷用戶是否有訪問某些資源的權限,有權限放行,沒權限不執行chain.doFilter方法。
    2> 通過在調用chain.doFilter方法之前,做些處理來達到某些目的。
  比如,解決中文亂碼的問題等等。可以在doFilter方法前,執行設置請求編碼與響應的編碼。甚至可以對request接口進行封裝裝飾來處理get請求方式的中文亂碼問題(重寫相  應的request.getParameter方法)。
    3> 通過在調用chain.doFilter方法之后,做些處理來達到某些目的。
  比如對整個web網站進行壓縮。在調用chain.doFilter方法之前用類A對response對象進行封裝裝飾,重寫 getOutputStream和重寫getWriter方法。在類A內部中,將輸出  內容緩存進ByteArrayOutputStream流中,然后在 chain.doFilter方法執行后,獲取類A中ByteArrayOutputStream流緩存數據,用GZIPOutputStream流進行 壓縮下。
五、Filter實現攔截的原理
    Filter接口中有一個doFilter方法,當開發人員編寫好Filter類實現doFilter方法,並配置對哪個web資源進行攔截后,WEB服 務器每次在調用web資源的service方法之前  (服務器內部對資源的訪問機制決定的),都會先調用一下filter的doFilter方法。
六、Filter生命周期
    和Servlet一樣Filter的創建和銷毀也是由WEB服務器負責。不過與Servlet區別的是,它是

  1>在應用啟動的時候就進行裝載 Filter類(與Servlet的load-on-startup配置效  果相同)。

  2>容器創建好Filter對象實例后,調用init()方 法。接着被Web容器保存進應用級的集合容器中去了等待着,用戶訪問資源。

  3>當用戶訪問的資源正好被Filter的url-pattern攔截 時,容器會取出Filter類調用doFilter方法,下次或多次訪問被攔截的資源時,Web容器會直接取出指定Filter對象實例調  用 doFilter方法(Filter對象常駐留Web容器了)。

  4>當應用服務被停止或重新裝載了,則會執行Filter的destroy方 法,Filter對象銷毀。
  注意:init方法與destroy方法只會直接一次。
七、Filter部署應用注意事項
   1> filter-mapping標簽中servlet-name與url-pattern。
  Filter不僅可以通過url-pattern來指定攔截哪些url匹配的資源。而且還可以通過servlet-name來指定攔截哪個指定的servlet(專門為某個servlet服務了,servlet-name對應    Servlet的相關配置)。
  2> filter-mapping標簽中dispatcher。
  指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認REQUEST。用戶可以設置多 個<dispatcher> 子元素  用來指定 Filter 對資源的多種調用方式進行攔截。


REQUEST:
當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問或ERROR情況時,那么該過濾器就不會被調用。
INCLUDE:
如果目標資源是通過RequestDispatcher的include()方法訪問時,那么該過濾器將被調用。除此之外,該過濾器不會被調用。
FORWARD:
如果目標資源是通過RequestDispatcher的forward()方法訪問時,那么該過濾器將被調用,除此之外,該過濾器不會被調用。
ERROR:
如若在A.jsp頁面page指令中指定了error屬性=examError.jsp,那么A.jsp中若出現了異常,會跳轉到examError.jsp中處理。而在跳轉到examError.jsp時,若過濾器配置了ERROR的dispather那么則會攔截,否則不會攔截。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM