JavaWeb中的監聽器、過濾器、攔截器

監聽器Listener

  • web監聽器是Servlet中一種特殊的類,能監聽web中的特定時間,比如ServletContext,HttpSession,ServletRequest的創建和銷燬;變量的創建、銷燬和修改等。可以在某些動作前後增加處理,實現監控。
  • 監聽事件自身的創建和銷燬
    1. ServletContext監控:對應監控application內置對象的創建和銷燬。當web容器開啓時,執行contextInitialized方法;當容器關閉或重啓時,執行contextDestroyed方法。
      實現方式:直接實現ServletContextListener接口
    2. HttpSession監控:對應監控session內置對象的創建和銷燬。當打開一個新的頁面時,開啓一個session會話,執行sessionCreated方法;當頁面關閉session過期時,或者容器關閉銷燬時,執行sessionDestroyed方法。
      實現方式:直接實現HttpSessionListener接口
    3. ServletRequest監控:對應監控request內置對象的創建和銷燬。當訪問某個頁面時,出發一個request請求,執行requestInitialized方法;當頁面關閉時,執行requestDestroyed方法。
      實現方式,直接實現ServletRequestListener接口
  • 監聽對象屬性的新增、刪除和修改
    1. 實現ServletContextAttributeListener接口:通過調用ServletContextAttribtueEvent的getName方法可以得到屬性的名稱。
    2. 實現HttpSessionAttributeListener接口
    3. 實現ServletRequestAttributeListener接口
  • 監聽對象的狀態
    1. 針對某些POJO類,可以通過實現HttpSessionBindingListener接口,監聽POJO類對象的事件。
      HttpSessionBindingListener雖然叫做監聽器,但使用方法與HttpSessionListener完全不同。我們實際看一下它是如何使用的。
      新建類OnlineUserBindingListener,實現HttpSessionBindingListener接口,HttpSessionBindingListener內有兩個方法valueBound(HttpSessionBindingEvent event)和valueUnbound(HttpSessionBindingEvent event),前者爲數據綁定,後者爲取消綁定
      所謂對session進行數據綁定,就是調用session.setAttribute()把HttpSessionBindingListener保存進session中。
      HttpSessionListener只需要設置到web.xml中就可以監聽整個應用中的所有session。HttpSessionBindingListener必須實例化後放入某一個session中,纔可以進行監聽
  • 監聽Session數據的鈍化與活化
    1. 由於session中保存大量訪問網站相關的重要信息,因此過多的session數據就會服務器性能的下降,佔用過多的內存。因此類似數據庫對象的持久化,web容器也會把不常使用的session數據持久化到本地文件或者數據中。這些都是有web容器自己完成,不需要用戶設定。
      不用的session數據序列化到本地文件中的過程,就是鈍化;
      當再次訪問需要到該session的內容時,就會讀取本地文件,再次放入內存中,這個過程就是活化。
      類似的,只要實現HttpSeesionActivationListener接口就是實現鈍化與活化事件的監聽
  • 代碼實現
  1. 自定義監聽器類
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener{

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println(sce.getServletContext().getContextPath() + "  " + "ServletContext對象創建");
		sce.getServletContext().setAttribute("path", sce.getServletContext().getContextPath());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("ServletContext對象銷燬");
	}
}
  1. web.xml配置
	<!-- 自定義servletContext監聽器 -->
	<listener>
		<listener-class>zjq.listener.MyServletContextListener</listener-class>
	</listener>

參考文章1 參考文章2

過濾器Filter

  • 過濾器是一個服務器端的組件,它可以攔截客戶端的請求和響應信息,並對這些信息進行過濾。
    Servlet API中提供了一個Filter接口,如果編寫類實現了這個接口,則稱這個類爲過濾器。
  • 定義一個Filter類,需要繼承javax.servlet.Filter類,重寫其init、doFilter、destroy方法。init()方法會在Filter初始化後進行調用,在init()方法裏面我們可以通過FilterConfig訪問到初始化參數( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和當前Filter部署的名稱( getFilterName() )等信息。destroy()方法將在Filter被銷燬之前調用。而doFilter()方法則是真正進行過濾處理的方法,在doFilter()方法內部,我們可以過濾請求的request和返回的response,同時我們還可以利用FilterChain把當前的request和response傳遞給下一個過濾器或Servlet進行處理。
  • 代碼實現
  1. 自定義過濾器類
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 FirstFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//做相應操作
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}
}
  1. web.xml
	<!-- 自定義過濾器1 -->
	<filter>
		<filter-name>firstFilter</filter-name>
		<filter-class>zjq.filter.FirstFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>firstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

參考文章1 參考文章2

攔截器Interceptor

  • SpringMVC 中的Interceptor 攔截器也是相當重要和相當有用的,它的主要作用是攔截用戶的請求並進行相應的處理。比如通過它來進行權限驗證,或者是來判斷用戶是否登陸,或者是像12306 那樣子判斷當前時間是否是購票時間。
  • SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式:
    1. 第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,比如Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;
    2. 第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。
  • 代碼實現
  1. 自定義攔截器類
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class FirstInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//請求處理之前進行調用
		HttpSession session = request.getSession();
		String userName = (String) session.getAttribute("userName");
		if (userName == null) {
			response.sendRedirect("/ssm_demo/welcome.html");
			//當它返回爲false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行
			return false;			
		} else {
			//當返回值爲true 時就會繼續調用下一個Interceptor 的preHandle 方法
			return true;
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//在當前請求進行處理之後,也就是Controller 方法調用之後執行
		//但是它會在DispatcherServlet 進行視圖返回渲染之前被調用
		//可以在這個方法中對Controller 處理之後的ModelAndView 對象進行操作
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		//該方法將在整個請求結束之後,也就是在DispatcherServlet 渲染了對應的視圖之後執行
		//這個方法的主要作用是用於進行資源清理工作的
	}
}
  1. spring.xml配置文件
	<!-- 配置攔截器1 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/testController/toTest"/>
			<mvc:exclude-mapping path="/welcome.html"/>
			<bean id="firstInterceptor" class="zjq.interceptor.FirstInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

過濾器和攔截器的區別

  1. 攔截器是基於java的反射機制的,而過濾器是基於函數回調
  2. 攔截器不依賴與servlet容器,過濾器依賴與servlet容器
  3. 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用
  4. 攔截器可以訪問action上下文、值棧裏的對象,而過濾器不能訪問
  5. 在action的生命週期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次
  6. 攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器裏注入一個service,可以調用業務邏輯。

過濾器和攔截器的順序

  1. 先過濾再做實際的攔截操作
  2. 過濾器是JavaEE標準,採用函數回調的方式進行。是在請求進入容器之後,還未進入Servlet之前進行預處理,並且在請求結束返回給前端這之間進行後期處理
  3. 攔截器是被包裹在過濾器之中的
    在這裏插入圖片描述
    在這裏插入圖片描述
    參考文章1 參考文章2 參考文章3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章