拦截器

拦截器作用的位置

客户端发送一个请求,首先是经过过滤器Fitter来进行处理,过滤器通过后就交给DispatherServlet来处理,然后DispatherServlet就会找到控制层中对应的控制方法,就是xxxhandler,而拦截器的作用位置就是DispatherServlet和xxxhandler之间的一层

简介

Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter 适配器类
接口里面有三个方法:

preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。
如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,
或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再
调用其他的组件去处理请求,则返回false。
postHandle():这个方法在业务处理器处理完请求后,
但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request进行处理。
afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,
可以在该方法中进行一些资源清理的操作。

每个方法的作用位置

SpringMVC框架:拦截器_数组


结合原码也可以发现他们的作用位置

SpringMVC框架:拦截器_拦截器_02


SpringMVC框架:拦截器_数组_03

自定义拦截方式

<mvc:interceptors>
<!-- 默认拦截所有请求 -->
<!-- 第一种方法配置拦截器 -->
<bean class="com.intercepor.FirstInterceptor"></bean>
<!-- 在拦截器加@Component注解,然后在这里配置ref属性 -->
<ref bean="firstInterceptor"/>

<!-- 自定义拦截方式
<bean></bean>:是拦截器
<mvc:mapping path=""/>:定义拦截的路径
<mvc:exclude-mapping path=""/>:定义上面大的拦截路径中排除的拦截
-->
<!--
<mvc:interceptor>
<bean></bean>
<mvc:mapping path=""/>
<mvc:exclude-mapping path=""/>
</mvc:interceptor>
-->
</mvc:interceptors>

多个拦截器的执行顺序(原码分析)

首先是debug进行跟踪查看

从debug界面可以看出,

Handler execution chain, consisting of handler object and any handler interceptors.Returned by HandlerMapping’s HandlerMapping.getHandler method.

mappedHandler是一个执行处理器,包含处理对象(就是控制层的每一个RequestMapping)和拦截器,而且可以看出拦截器是用一个ArrayList来存储

SpringMVC框架:拦截器_拦截器_04


Interface to be implemented by objects that define a mapping betweenrequests and handler objects.

这个接口就是被定义在请求和对象之间的对象实现,就是处理器吧

SpringMVC框架:拦截器_mvc_05


这个是拦截前的方法

如果返回的是false,表示拦截,就会进到方法里面,直接结束这个方法

如果返回true,代表的是拦截器放行,所以就不会进到这个if里面

SpringMVC框架:拦截器_数组_06


进入applyPreHandle

会先判断getInterceptors数组里面有没有拦截器

数组有拦截器就对数组进行遍历拦截器,然后取出来拦截器进行执行

执行先调用你重写的preHandle方法

如果返回false,就是拦截的话,就会进入if里面,调用triggerAfterCompletion方法就结束,具体的triggerAfterCompletion方法干什么后面描述

如果返回的是true,那么就会this.interceptorIndex = i;就没了

然后我们得了解一下interceptorIndex的意思,后面描述

SpringMVC框架:拦截器_拦截器_07


SpringMVC框架:拦截器_拦截器_08


PreHandle执行完了,现在到PostHandle

SpringMVC框架:拦截器_拦截器_09


进入applyPostHandle发现它是从数组后面进行遍历的

SpringMVC框架:拦截器_mvc_10


现在到AfterCompletion

SpringMVC框架:拦截器_mvc_11


进入triggerAfterCompletion,也是从后面进行遍历的

SpringMVC框架:拦截器_拦截器_12


经过上面,我们还有两个疑惑,就是triggerAfterCompletion方法的作用和interceptorIndex的作用是干嘛的,因为这两个东西都是返回false才会执行的和使用的,所以我们将第二个改成返回false,第一个还是返回true现在interceptorIndex是1,我们遍历到第二个拦截器了,进入到triggerAfterCompletion里面看看

SpringMVC框架:拦截器_拦截器_13


triggerAfterCompletion就是调用AfterCompletion,而且是将interceptorIndex之前的拦截器的afterCompletion都执行

SpringMVC框架:拦截器_mvc_14