阅读HandlerInterceptor接口源码的理解
一、阅读接口类注释
二、阅读preHandle()方法注释
Intercept the execution of a handler. Called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler.
理解:拦截一个handler处理器的执行。这个方法的调用时机:在映射处理器(HandlerMapping)指定合适的处理器对象之后,处理器适配器(HandlerAdapter)调用处理器之前。
DispatcherServlet processes a handler in an execution chain, consisting of any number of interceptors, with the handler itself at the end. With this method, each interceptor can decide to abort the execution chain, typically sending a HTTP error or writing a custom response.
理解:前端控制器调用一个处理器在一个执行链中(也就是说处理器和拦截器组成了一个执行链条),这个执行链条可以有任意个拦截器,但是handler(处理器)在这个执行链条的最后,即,先执行链条中的所有拦截器才执行处理器。通过这个方法,每一个拦截器都可以决定是否可以终止这个执行链条,通常发送一个HTTP错误或者一个自定义一个响应。
注意:special considerations apply for asynchronous request processing. For more details see {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
三、阅读postHandle()方法注释
Intercept the execution of a handler. Called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view.
理解:拦截一个处理的执行。这个方法的调用时机是:在处理器适配器调用处理器之后,但前端控制器渲染视图之前。
Can expose additional model objects to the view via the given ModelAndView.
理解:可以通过给定的 ModelAndView 对象,暴露额外的模型对象给视图。
四、阅读afterCompletion()方法注释
五、总结:
每一个拦截器都有一个preHandle()方法和postHandle()方法。在调用处理器之前后,都会调用拦截器。由许多个拦截器组成一个执行链,而这个执行链是以数组的形式存在。所以,执行这个执行链的中的所有拦截器的preHandle()方法是按照interceptor[]数组的正序执行的,也就是按数组下标从小到大执行每一个拦截器的preHandle()方法。而拦截器的postHandle()方法的执行是按照逆序执行的,也就是按照interceptor[]数组的下标从大到小的顺序执行拦截器中的postHandle()方法。而拦截器中的每一个afterCompletion()方法都是在渲染完视图以后按照interceptor[]数组的下标从大到小的顺序执行拦截器中的afterCompletion()方法,也就是说afterCompletion()方法的执行顺序跟postHandle()方法的执行顺序是一样的。说这么多还不如一张图。如下图:
以上是正常情况下的执行顺序,但是:当某一个拦截器的preHandle()方法()返回false,那么handler(处理器就不会执行)。它会直接去掉用当前拦截器的前一个拦截器的afterCompletion()方法,从这个方法开始逆序执行。比如:这里的interceptor3的preHandle()方法返回false。那么就会直接调用interceptor2的afterCompletion()方法,并从这个方法开始逆序执行至结束。