SpringMVC教程之多个拦截器的执行顺序

一、前言

接着上一个章节,我们新建一个新的工程SpringMVCInterceptors,用以研究多个拦截器执行的顺序。工程结构目录如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 1

二、案例

♦第一个拦截器FirstInterceptorHandler

public class FirstInterceptorHandler implements HandlerInterceptor{

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

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

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

}

♦第二个拦截器SecondInterceptorHandler

public class SecondInterceptorHandler implements HandlerInterceptor{

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

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

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

}

♦springmvc核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	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-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<!-- 定义Controller的扫描包 -->
	<context:component-scan base-package="com.queen.springmvc" />

	<!-- 配置视图解析器 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>

	<mvc:default-servlet-handler/>
	<mvc:annotation-driven />

	<mvc:interceptors>
		<bean class="com.queen.springmvc.handlers.FirstInterceptorHandler"></bean>
		<bean class="com.queen.springmvc.handlers.SecondInterceptorHandler"></bean>
	</mvc:interceptors>
</beans>

♦定义控制器MyHandler

@Controller
@RequestMapping(value = "myhandler")
public class MyHandler {

	@RequestMapping(value = "hello")
	public String hello() {
		System.out.println("Hello World!");
		return "hello";
	}

}

♦启动服务运行

执行完后,控制台打印如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 3

♦下面我们从源码的角度看一下整个代码流程是怎么样的

前面《SpringMVC教程之自定义拦截器》这一节我们也简单的从源码角度看了一下拦截器执行的过程,这次我们再来看一下,分别在FirstInterceptorHandler和SecondInterceptorHandler的6个实现方法处打上断点

SpringMVC教程之多个拦截器的执行顺序的照片 - 5

SpringMVC教程之多个拦截器的执行顺序的照片 - 7

在DispatcherServlet的doDispatch方法的三个地方打上断点

SpringMVC教程之多个拦截器的执行顺序的照片 - 9

Debug运行起来

代码再938行停住,F5进入该方法

SpringMVC教程之多个拦截器的执行顺序的照片 - 11

这段代码想必大家也能看懂。获取所有的拦截器,并对所有的拦截器进行遍历,每次遍历的时候调用preHandler方法,如果preHandler方法返回false,那么就会执行triggerAfterCompletion方法,并释放资源,整个方法return false,不会后续执行,如果都是正常的,将会执行完applyPreHandle这段方法,这时候控制台打印如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 13

继续往下面执行,当执行完mv = ha.handle(processedRequest, response, mappedHandler.getHandler());方法后,控制台打印出hello World!

SpringMVC教程之多个拦截器的执行顺序的照片 - 15

执行到applyPostHandle方法,F5进入该方法

SpringMVC教程之多个拦截器的执行顺序的照片 - 17

从这段方法可以看出,这里的for循环,是倒序的。先调用SecondInterceptorHandler的postHandler方法,再调用FirstInterceptorHandler的postHandler方法,执行完之后,控制台打印如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 19

继续往下面执行,Debug到processDispatchResult方法的mappedHandler.triggerAfterCompletion(request, response, null);方法处

SpringMVC教程之多个拦截器的执行顺序的照片 - 21

F5进入该方法

SpringMVC教程之多个拦截器的执行顺序的照片 - 23

我们发现这段方法也是逆序的,先调用SecondInterceptorHandler的afterCompletion方法,再调用FirstInterceptorHandler的afterCompletion方法,执行完之后,控制台打印如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 25

正常情况,如果每个拦截器执行正常,控制台打印结果如上图,整个流程可以画一张流程图如下:

SpringMVC教程之多个拦截器的执行顺序的照片 - 27

那么,如果是非正常情况下的拦截器执行

①比如第一个拦截器拦截,第二个拦截器放行

SpringMVC教程之多个拦截器的执行顺序的照片 - 29

再次启动系统拦截器的执行顺序

控制台打印结果如下:

FirstInterceptorHandler preHandle...

得出的结论是:

  • 拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
  • 拦截器1 preHandle不放行,拦截器2不执行。

②比如第一个拦截器放行,第二个拦截器拦截,又会怎样呢?

SpringMVC教程之多个拦截器的执行顺序的照片 - 31

再次启动系统拦截器的执行顺序

控制台打印结果如下:

FirstInterceptorHandler preHandle...
SecondInterceptorHandler preHandle...
FirstInterceptorHandler afterCompletion...

得出的结论是:

  • 拦截器1放行,拦截器2 preHandle才会执行。
  • 拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
  • 只要有一个拦截器不放行,postHandle不会执行

至此,我们关于SpringMVC教程之多个拦截器的执行顺序介绍完毕。想要了解更多关于SpringMVC开发的教程,请参考http://www.marsitman.com/springmvc
博客地址:http://www.marsitman.com/springmvc/springmvc-interceptor-order.html
版权声明:本文为博主原创文章,允许转载,但转载必须标明出处。

 

 

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!



点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注