1. 程式人生 > >【Maven+SSM】Springmvc的統一處理之攔截器

【Maven+SSM】Springmvc的統一處理之攔截器

前言:

攔截器的使用場景:

程式中的所有請求的共同問題。

1、例如上一篇文章的亂碼問題。本文最後會講到亂碼問題的解決。

2、例如解決許可權驗證的問題。本文最後也會提到。

攔截器與過濾器的區別:

過濾器基於Servlet容器,基於回撥函式,範圍大。

攔截器Interceptor依賴於框架,基於反射,只過濾請求。

正文:

一、寫一個攔截器Interceptor

package interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

public class TestInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("---------preHandle--------");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("---------postHandle--------");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("---------afterCompletion--------");
	}

}

其中preHandle返回true說明不中斷請求,否則中斷請求。

二、註冊到SpringMVC。

在springmvc-servlet.xml中配置攔截器

<!-- 註冊攔截器 -->
	<mvc:interceptors>
		<bean class="interceptor.TestInterceptor"></bean>	
	</mvc:interceptors>
預設對所有走controller的請求攔截。

三、請求測試:

會按照如下順序列印:

---------preHandle--------


---------postHandle--------


---------afterCompletion--------

因此,可見,三個方法的呼叫時機。

preHandle請求被處理之前。

postHandle請求被處理之後。

afterCompletion請求結束之後呼叫。

四、修改攔截規則:

僅僅針對部分請求攔截。修改在springmvc-servlet.xml中攔截器如下:

	<!-- 註冊攔截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- 配置攔截規則 -->
			<mvc:mapping path="/*.do"/>	
			<bean class="interceptor.TestInterceptor"></bean>	
		</mvc:interceptor>		
	</mvc:interceptors>
只針對/*.do結尾的路徑攔截。可以測試一下。略。

五、通過攔截器修改請求跳轉及引數。

跳轉頁面的請求修改,攔截器如下:讓請求處理之後跳轉springmvc指定路徑下的login.jsp,而不是原來的頁面。

package interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

public class TestInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("---------preHandle--------");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("---------postHandle--------");
		modelAndView.setViewName("/login");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("---------afterCompletion--------");
	}

}
此方式僅僅針對原本就是跳轉頁面的請求有效。如果是responseBody的json返回請求則報錯。

同樣可通過修改ModelAndView修改傳遞的引數。例如:

@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("---------postHandle--------");
		modelAndView.setViewName("/login");
		modelAndView.addObject("msg", "我已經被攔截修改了");
	}
這樣在頁面中就會獲得msg這個欄位。如果之前有這個欄位,則會被攔截器替換。

六、多個攔截器的攔截順序。

<!-- 註冊攔截器 -->
	<mvc:interceptors>
		<!-- <mvc:interceptor>
			配置攔截規則
			<mvc:mapping path="/*.do"/>	
			<bean class="interceptor.TestInterceptor"></bean>	
		</mvc:interceptor>		 -->
		<bean class="interceptor.TestInterceptor"></bean>	
		<bean class="interceptor.OtherInterceptor"></bean>	
	</mvc:interceptors>
執行順序如何?原因,其實就是一個圍繞方法的代理模式。
---------preHandle--------
---------preHandle2--------
略
---------postHandle2--------
---------postHandle--------
略
---------afterCompletion2--------
---------afterCompletion--------

七、攔截器的其他實現方式。

package interceptor;

import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;

public class WebInterceptor implements WebRequestInterceptor{

	@Override
	public void preHandle(WebRequest request) throws Exception {
		// 區別,沒有返回值
		
	}

	@Override
	public void postHandle(WebRequest request, ModelMap model) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void afterCompletion(WebRequest request, Exception ex) throws Exception {
		// TODO Auto-generated method stub
		
	}

}

區別:不能中斷請求。

八、通過攔截器對亂碼問題的解決。

不僅可以如下處理請求的亂碼,也可以處理響應請求的亂碼問題。

package interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

public class TestInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("---------preHandle--------");
		//處理中文請求亂碼問題
		request.setCharacterEncoding("UTF-8");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("---------postHandle--------");
//		modelAndView.setViewName("/login");
//		modelAndView.addObject("msg", "我已經被攔截修改了");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("---------afterCompletion--------");
	}

}

九、攔截器解決許可權驗證的問題。

package interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

public class OtherInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("---------preHandle2--------");
		if (request.getSession().getAttribute("user")==null) {
			//回到登陸頁面
			request.getRequestDispatcher("/login.jsp").forward(request, response);;
			return false;
		}else {
			return true;
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("---------postHandle2--------");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("---------afterCompletion2--------");
	}

}