1. 程式人生 > >Filter過濾器與listener監聽器的簡單使用

Filter過濾器與listener監聽器的簡單使用

Filter過濾器是一種對客戶端訪問的過濾技術,簡單來說就是我們瀏覽器訪問伺服器檔案時,如果設定了特定的過濾配置,則會先經過過濾器,然後再將請求放給伺服器去執行,最常見的就是我們過濾使用者是否登入的使用。

listener監聽器,見名得意,他就是起到一個監聽的作用,主要是用來監聽web應用的建立和銷燬,以及他們attribute的建立、移除和更新等。 當然也包括用來監聽session、request的生命週期以及他們attribute的動態。

一:Filter過濾器

這裡我們以過濾器驗證使用者是否登入為例,進行解釋。

首先完整的使用Filter我們需要在web.xml中配置filter的相關資訊,告訴伺服器我要過濾什麼請求還是所有請求都過濾。然後對映到過濾器的類檔案中。

 	<filter>
		<filter-name>FirstFilter</filter-name>
		<filter-class>FirstFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>FirstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

這裡配置的是過濾所有請求,當然也可以針對有一個或者某一類請求進行過濾。例如*.mml那所有的.mml結尾的請求都會過濾到過濾器中去處理。

2. 然後新建FirstFilter類檔案,需要實現Filter介面,並重寫該介面的三個方法。

執行銷燬方法:destory()、

執行過濾操作的方法:doFilter()、

初始化方法:init()。

其中doFilter()方法使我們過濾器執行實際過濾過程的方法,我們的實際業務邏輯就是寫在這個方法裡面的。該方法中有三個引數。

init()方法是過濾器的初始化方法,他跟servlet的init方法不一樣,servlet需要配置自啟動才會隨著tomcat的啟動執行init方法。二Filter的init方法一定會隨著tomcat的啟動而執行該方法的。

在這裡我們通過該過濾器打印出一句話,來驗證當我們請求時,會執行過濾器操作。程式碼如下:


//攔截器與servlet的執行順序,當訪問一個servlet請求時,先對servlet進行例項化、初始化、進入過濾器,
//執行過濾器的過濾,過濾器放行之後,再執行servlet的service方法。
public class FirstFilter implements Filter {

	@Override
	public void destroy() {
		
	}

	//執行攔截的方法
	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String url = request.getRequestURI().toString();
		System.out.printf("訪問了 %s%n",url);
		request.setCharacterEncoding("UTF-8");		 
		chain.doFilter(request, response);
	}

	//攔截器的init初始化方法一定會隨著tomcat的啟動而啟動,不需要配置
	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}

}

因為doFilter方法中的引數是servletRequest型別的,我們先把引數轉化成HttpServletRequest型別的,然後獲取到請求的URL,列印在控制檯。通過chain.doFilter(request,response)這個方法,放行該請求,他就可以訪問伺服器上的資源了。代表著過濾器完成了過濾。

此時我們啟動tomcat,請求一個地址,就會看到控制檯上列印了我們輸出的URL地址。

這就是簡單使用過濾器的過程,下面我們在doFilter方法中加入驗證登入的過濾邏輯。

3. 驗證使用者是否登入,我們的核心思想就是

使用者開啟瀏覽器訪問該網址(此時伺服器自動建立一個session物件),當用戶登入並驗證成功之後,會在session中建立一個key為login的值為"yes"的鍵值對,

然後如果使用者請求的是login.jsp或者login結尾的登入頁面,過濾器放行。否則就判斷session存在login的值是否為空,如果為空,說明使用者沒有登入過,就跳轉到登入頁面,如果不為空,則放行。程式碼如下:

先是login的servlet驗證:如果驗證成功,就session中存一個鍵值對。

public class Login extends HttpServlet {

	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
		
		if("root".equals(request.getParameter("userName")) && "root".equals(request.getParameter("password"))) {
			request.getSession().setAttribute("user", request.getParameter("userName"));
			response.sendRedirect("heroList");
		}else {
			response.sendRedirect("login.html");
		}
	}
}

然後是Filter過濾器的邏輯:

public class FirstFilter implements Filter {
	//執行攔截的方法
	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String url = request.getRequestURI().toString();
		System.out.printf("訪問了 %s%n",url);
		request.setCharacterEncoding("UTF-8");
		
		if(url.endsWith("login.html") || url.endsWith("login")) {
			chain.doFilter(request, response);
			return;
		}
		
		String isUser = (String)request.getSession().getAttribute("user");
		if(null == isUser || "" == isUser) {
			response.sendRedirect("login.html");
			return;
		}
		 
		chain.doFilter(request, response);
	}

}

這樣設定完成之後,我們開啟瀏覽器,如果先訪問heroList請求,則過濾器沒有獲取到session中的值,會調到登入頁面,直到我們登入驗證通過了,session中才會存入值,才會通過過濾器的已經登入的驗證。

二:listener監聽器:

1. 首先也需要在web.xml中告訴伺服器設定了監聽類:

	<listener>
		<listener-class>listener.OnlineNumberListener</listener-class>
		<listener-class>listener.RequestListener</listener-class>
		<listener-class>listener.SessionListener</listener-class>
		<listener-class>listener.SessionListenerAttrute</listener-class>
	</listener>

2. 首先新建RequseListener用來監聽request的生命週期和attribute的動態。程式碼如下:如果建立了reques物件就會執行該類中的對應的方法(相當於發起一次請求,就會執行該方法,因為request物件是請求物件,每重新發起請求都會建立一個request),建立attribute也一樣。

package listener;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class RequestListener implements ServletRequestListener, ServletRequestAttributeListener {

	@Override
	public void attributeAdded(ServletRequestAttributeEvent arg0) {
		System.out.println("建立了attribute:");
		System.out.println("name:"+arg0.getName());
		System.out.println("value:"+arg0.getValue());
	}

	@Override
	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
		syso:監聽attribute的移除
	}

	@Override
	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
		syso:監聽attribute的替換
	}

	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		syso:監聽request的銷燬
	}

	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		System.out.println("建立了Request");
	}

}

3. 新建SessionListener、SessionListenerAttrute類監聽session和attribute的動態,因為session比較特殊,需要用兩個監聽器分別來監聽。程式碼如下:

public class SessionListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent arg0) {
		System.out.println("監聽到session建立:Id是"+arg0.getSession().getId());
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent arg0) {
		
	}

}

 

public class SessionListenerAttrute implements HttpSessionAttributeListener {

	@Override
	public void attributeAdded(HttpSessionBindingEvent arg0) {
		System.out.println("監聽到建立了session的attribute,是:"+arg0.getName()+arg0.getValue());
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent arg0) {
		System.out.println("******************退出了登入***********************");
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent arg0) {
		
	}

}

使用session的建立和銷燬可以模糊的統計線上人數,因為開啟瀏覽器訪問頁面,就會建立session,也就是一次會話,就相當於一個線上人數,可以用作粗略統計。

 

感謝閱讀!