天天看點

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中

pringMVC 中的Interceptor 攔截器也是相當重要和相當有用的,它的主要作用是攔截使用者的請求并進行相應的處理。比如通過它來進行權限驗證,或者是來判斷使用者是否登陸,或者是像12306 那樣子判斷目前時間是否是購票時間。  

一、定義Interceptor實作類

   SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實作的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實作了Spring 的HandlerInterceptor 接口,或者是這個類繼承實作了HandlerInterceptor 接口的類,比如Spring 已經提供的實作了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;第二種方式是實作Spring的WebRequestInterceptor接口,或者是繼承實作了WebRequestInterceptor的類。

   (一)實作HandlerInterceptor接口

   HandlerInterceptor 接口中定義了三個方法,我們就是通過這三個方法來對使用者的請求進行攔截處理的。

   (1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法将在請求處理之前進行調用。SpringMVC 中的Interceptor 是鍊式的調用的,在一個應用中或者說是在一個請求中可以同時存在多個Interceptor 。每個Interceptor 的調用會依據它的聲明順序依次執行,而且最先執行的都是Interceptor 中的preHandle 方法,是以可以在這個方法中進行一些前置初始化操作或者是對目前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的傳回值是布爾值Boolean 類型的,當它傳回為false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行;當傳回值為true 時就會繼續調用下一個Interceptor 的preHandle 方法,如果已經是最後一個Interceptor 的時候就會是調用目前請求的Controller 方法。

   (2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋我們知道這個方法包括後面要說到的afterCompletion 方法都隻能是在目前所屬的Interceptor 的preHandle 方法的傳回值為true 時才能被調用。postHandle 方法,顧名思義就是在目前請求進行處理之後,也就是Controller 方法調用之後執行,但是它會在DispatcherServlet 進行視圖傳回渲染之前被調用,是以我們可以在這個方法中對Controller 處理之後的ModelAndView 對象進行操作。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會後執行,這和Struts2 裡面的Interceptor 的執行過程有點類型。Struts2 裡面的Interceptor 的執行過程也是鍊式的,隻是在Struts2 裡面需要手動調用ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的調用,然後每一個Interceptor 中在invoke 方法調用之前的内容都是按照聲明順序執行的,而invoke 方法之後的内容就是反向的。

   (3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是需要目前對應的Interceptor 的preHandle 方法的傳回值為true 時才會執行。顧名思義,該方法将在整個請求結束之後,也就是在DispatcherServlet 渲染了對應的視圖之後執行。這個方法的主要作用是用于進行資源清理工作的。

下面是一個簡單的代碼說明:

Java代碼

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
  1. import javax.servlet.http.HttpServletRequest;  
  2. import javax.servlet.http.HttpServletResponse;  
  3. import org.springframework.web.servlet.HandlerInterceptor;  
  4. import org.springframework.web.servlet.ModelAndView;  
  5. public class SpringMVCInterceptor implements HandlerInterceptor {  
  6.     @Override  
  7.     public boolean preHandle(HttpServletRequest request,  
  8.             HttpServletResponse response, Object handler) throws Exception {  
  9.         // TODO Auto-generated method stub  
  10.         return false;  
  11.     }  
  12.     @Override  
  13.     public void postHandle(HttpServletRequest request,  
  14.             HttpServletResponse response, Object handler,  
  15.             ModelAndView modelAndView) throws Exception {  
  16.         // TODO Auto-generated method stub  
  17.     }  
  18.     @Override  
  19.     public void afterCompletion(HttpServletRequest request,  
  20.             HttpServletResponse response, Object handler, Exception ex)  
  21.     throws Exception {  
  22.         // TODO Auto-generated method stub  
  23.     }  
  24. }  
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class SpringMVCInterceptor implements HandlerInterceptor {


	/**
	 * preHandle方法是進行處理器攔截用的,顧名思義,該方法将在Controller處理之前進行調用,SpringMVC中的Interceptor攔截器是鍊式的,可以同時存在
	 * 多個Interceptor,然後SpringMVC會根據聲明的前後順序一個接一個的執行,而且所有的Interceptor中的preHandle方法都會在
	 * Controller方法調用之前調用。SpringMVC的這種Interceptor鍊式結構也是可以進行中斷的,這種中斷方式是令preHandle的返
	 * 回值為false,當preHandle的傳回值為false的時候整個請求就結束了。
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}
	
	/**
	 * 這個方法隻會在目前這個Interceptor的preHandle方法傳回值為true的時候才會執行。postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之
	 * 後,也就是在Controller的方法調用之後執行,但是它會在DispatcherServlet進行視圖的渲染之前執行,也就是說在這個方法中你可以對ModelAndView進行操
	 * 作。這個方法的鍊式結構跟正常通路的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會後調用,這跟Struts2裡面的攔截器的執行過程有點像,
	 * 隻是Struts2裡面的intercept方法中要手動的調用ActionInvocation的invoke方法,Struts2中調用ActionInvocation的invoke方法就是調用下一個Interceptor
	 * 或者是調用action,然後要在Interceptor之前調用的内容都寫在調用invoke之前,要在Interceptor之後調用的内容都寫在調用invoke方法之後。
	 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		
	}

	/**
	 * 該方法也是需要目前對應的Interceptor的preHandle方法的傳回值為true時才會執行。該方法将在整個請求完成之後,也就是DispatcherServlet渲染了視圖執行,
	 * 這個方法的主要作用是用于清理資源的,當然這個方法也隻能在目前這個Interceptor的preHandle方法的傳回值為true時才會執行。
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
	throws Exception {
		// TODO Auto-generated method stub
		
	}
	
}
           

   (二)實作WebRequestInterceptor 接口

  WebRequestInterceptor 中也定義了三個方法,我們也是通過這三個方法來實作攔截的。這三個方法都傳遞了同一個參數WebRequest ,那麼這個WebRequest 是什麼呢?這個WebRequest 是Spring 定義的一個接口,它裡面的方法定義都基本跟HttpServletRequest 一樣,在WebRequestInterceptor 中對WebRequest 進行的所有操作都将同步到HttpServletRequest 中,然後在目前請求中一直傳遞。

   (1 )preHandle(WebRequest request) 方法。該方法将在請求處理之前進行調用,也就是說會在Controller 方法調用之前被調用。這個方法跟HandlerInterceptor 中的preHandle 是不同的,主要差別在于該方法的傳回值是void ,也就是沒有傳回值,是以我們一般主要用它來進行資源的準備工作,比如我們在使用Hibernate 的時候可以在這個方法中準備一個Hibernate 的Session 對象,然後利用WebRequest 的setAttribute(name, value, scope) 把它放到WebRequest 的屬性中。這裡可以說說這個setAttribute 方法的第三個參數scope ,該參數是一個Integer 類型的。在WebRequest 的父層接口RequestAttributes 中對它定義了三個常量:

   SCOPE_REQUEST :它的值是0 ,代表隻有在request 中可以通路。

   SCOPE_SESSION :它的值是1 ,如果環境允許的話它代表的是一個局部的隔離的session,否則就代表普通的session,并且在該session範圍内可以通路。

   SCOPE_GLOBAL_SESSION :它的值是2 ,如果環境允許的話,它代表的是一個全局共享的session,否則就代表普通的session,并且在該session 範圍内可以通路。

   (2 )postHandle(WebRequest request, ModelMap model) 方法。該方法将在請求處理之後,也就是在Controller 方法調用之後被調用,但是會在視圖傳回被渲染之前被調用,是以可以在這個方法裡面通過改變資料模型ModelMap 來改變資料的展示。該方法有兩個參數,WebRequest 對象是用于傳遞整個請求資料的,比如在preHandle 中準備的資料都可以通過WebRequest 來傳遞和通路;ModelMap 就是Controller 處理之後傳回的Model 對象,我們可以通過改變它的屬性來改變傳回的Model 模型。

   (3 )afterCompletion(WebRequest request, Exception ex) 方法。該方法會在整個請求處理完成,也就是在視圖傳回并被渲染之後執行。是以在該方法中可以進行資源的釋放操作。而WebRequest 參數就可以把我們在preHandle 中準備的資源傳遞到這裡進行釋放。Exception 參數表示的是目前請求的異常對象,如果在Controller 中抛出的異常已經被Spring 的異常處理器給處理了的話,那麼這個異常對象就是是null 。

   下面是一個簡單的代碼說明:

Java代碼

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
  1. import org.springframework.ui.ModelMap;  
  2. import org.springframework.web.context.request.WebRequest;  
  3. import org.springframework.web.context.request.WebRequestInterceptor;  
  4. public class AllInterceptor implements WebRequestInterceptor {  
  5.     @Override  
  6.     public void preHandle(WebRequest request) throws Exception {  
  7.         // TODO Auto-generated method stub  
  8.         System.out.println("AllInterceptor...............................");  
  9.         request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);//這個是放到request範圍内的,是以隻能在目前請求中的request中擷取到  
  10.         request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);//這個是放到session範圍内的,如果環境允許的話它隻能在局部的隔離的會話中通路,否則就是在普通的目前會話中可以通路  
  11.         request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);//如果環境允許的話,它能在全局共享的會話中通路,否則就是在普通的目前會話中通路  
  12.     }  
  13.     @Override  
  14.     public void postHandle(WebRequest request, ModelMap map) throws Exception {  
  15.         // TODO Auto-generated method stub  
  16.         for (String key:map.keySet())  
  17.             System.out.println(key + "-------------------------");;  
  18.         map.put("name3", "value3");  
  19.         map.put("name1", "name1");  
  20.     }  
  21.     @Override  
  22.     public void afterCompletion(WebRequest request, Exception exception)  
  23.     throws Exception {  
  24.         // TODO Auto-generated method stub  
  25.         System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");  
  26.     }  
  27. }  
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;

public class AllInterceptor implements WebRequestInterceptor {
	
	/**
	 * 在請求處理之前執行,該方法主要是用于準備資源資料的,然後可以把它們當做請求屬性放到WebRequest中
	 */
	@Override
	public void preHandle(WebRequest request) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("AllInterceptor...............................");
		request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);//這個是放到request範圍内的,是以隻能在目前請求中的request中擷取到
		request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);//這個是放到session範圍内的,如果環境允許的話它隻能在局部的隔離的會話中通路,否則就是在普通的目前會話中可以通路
		request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);//如果環境允許的話,它能在全局共享的會話中通路,否則就是在普通的目前會話中通路
	}

	/**
	 * 該方法将在Controller執行之後,傳回視圖之前執行,ModelMap表示請求Controller處理之後傳回的Model對象,是以可以在
	 * 這個方法中修改ModelMap的屬性,進而達到改變傳回的模型的效果。
	 */
	@Override
	public void postHandle(WebRequest request, ModelMap map) throws Exception {
		// TODO Auto-generated method stub
		for (String key:map.keySet())
			System.out.println(key + "-------------------------");;
		map.put("name3", "value3");
		map.put("name1", "name1");
	}

	/**
	 * 該方法将在整個請求完成之後,也就是說在視圖渲染之後進行調用,主要用于進行一些資源的釋放
	 */
	@Override
	public void afterCompletion(WebRequest request, Exception exception)
	throws Exception {
		// TODO Auto-generated method stub
		System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");
	}
	
}
           

  二、把定義的攔截器類加到SpringMVC的攔截體系中

         1.在SpringMVC的配置檔案中加上支援MVC的schema

Xml代碼

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
  1.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  2.     xsi:schemaLocation=" http://www.springframework.org/schema/mvc  
  3.         http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"  
xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation=" http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"      

         下面是我的聲明示例:

Xml代碼

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  3.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  6.      http://www.springframework.org/schema/context  
  7.      http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  8.      http://www.springframework.org/schema/mvc  
  9.      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/mvc
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">      

         這樣在SpringMVC的配置檔案中就可以使用mvc标簽了,mvc标簽中有一個mvc:interceptors是用于聲明SpringMVC的攔截器的。

        (二)使用mvc:interceptors标簽來聲明需要加入到SpringMVC攔截器鍊中的攔截器

Xml代碼

SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
SpringMVC中使用Interceptor攔截器一、定義Interceptor實作類  二、把定義的攔截器類加到SpringMVC的攔截體系中
  1. <mvc:interceptors>  
  2.     <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor将攔截所有的請求 -->  
  3.     <bean class="com.host.app.web.interceptor.AllInterceptor"/>  
  4.     <mvc:interceptor>  
  5.         <mvc:mapping path="/test/number.do"/>  
  6.         <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->  
  7.         <bean class="com.host.app.web.interceptor.LoginInterceptor"/>  
  8.     </mvc:interceptor>  
  9. </mvc:interceptors>  
<mvc:interceptors>
		<!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor将攔截所有的請求 -->
		<bean class="com.host.app.web.interceptor.AllInterceptor"/>
		<mvc:interceptor>
			<mvc:mapping path="/test/number.do"/>
			<!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->
			<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>      

          由上面的示例可以看出可以利用mvc:interceptors标簽聲明一系列的攔截器,然後它們就可以形成一個攔截器鍊,攔截器的執行順序是按聲明的先後順序執行的,先聲明的攔截器中的preHandle方法會先執行,然而它的postHandle方法和afterCompletion方法卻會後執行。

          在mvc:interceptors标簽下聲明interceptor主要有兩種方式:

                    (1)直接定義一個Interceptor實作類的bean對象。使用這種方式聲明的Interceptor攔截器将會對所有的請求進行攔截。

                    (2)使用mvc:interceptor标簽進行聲明。使用這種方式進行聲明的Interceptor可以通過mvc:mapping子标簽來定義需要進行攔截的請求路徑。

          經過上述兩步之後,定義的攔截器就會發生作用對特定的請求進行攔截了。



繼續閱讀