还是老样子,在DispatcherServlet类中的doDispatch()方法打上断点,如图:
拦截器的使用
见上篇文章!!!
分析
接下来,客户端发起请求,方法中拿到对应的请求,接着往下继续调试。
- 到1036行处执行完后拿到对应的处理器(HandlerExecutionChain,可以处理请求的handler以及handler的所有拦截器)。
我们可以发现在处理器链中包含了我们自己定义的了。 - 接着往下走,拿到对应的适配器之后(HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler();),在执行目标方法之前还有一个步骤——执行拦截器的preHandle()方法。
进入其中我们根据源码发现,拿到拦截器链的size,顺序循环执行拦截器的preHandle()方法。
如果当前拦截器的preHandle()方法返回false,则执行triggerAfterCompletion(request, response, null)进入其中根据源码我们又可以得知,直接倒序执行所有已经执行了的拦截器的afterCompletion()。
根据以下源码又可得知,如若任何一个拦截器调用方法返回false,直接return不执行目标方法。
- 正常情况一切运行正常,继续往下调试,目标方法被执行(mv = ha.handle(processedRequest, response, mappedHandler.getHandler())),接着往下。
- 目标方法被执行之后,接下来在1067行处执行拦截器中的postHandle()方法。在这里有点要注意,是倒序执行所有拦截器的postHandle方法!!! 源码如下
进入目前方法,可得知是倒序执行所有拦截器的postHandle()方法。
执行完postHandle()方法之后,就进行页面处理,在这里要注意的是有个==try{}catch(Exception ex)finally{}==异常处理块,作用就是之前的步骤任何一处发生异常都会直接倒序触发 afterCompletion()方法!!!
- 接下来就是页面处理(processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException)),进入此方法。如图:
其中就包括页面渲染render()等等,在页面渲染之后,也会倒序触发 afterCompletion()方法,标注了两个断点,可方便小伙伴们定位。
总结
如若有问题,谢谢提醒,共同进步!!!