SpringBoot源码系列(8):拦截器执行顺序
前言
在SpringBoot/SpringMVC中,拦截器有三个方法
applyPreHandle
(前置操作,目标方法执行前)applyPostHandle
(后置操作,目标方法执行后)triggerAfterCompletion
(最终操作,渲染结束后)
正常情况下,会顺序执行所有前置操作,逆序执行所有后置操作,逆序执行所有最终操作。
如果中间被拦截,会顺序执行所有前置操作,直至被拦截,逆序执行所有放行的后置操作。
我们根据源码来看一看其中的原理
原文地址:https://xuedongyun.cn/post/5855/
拦截器原理
DispatcherServlet
我知道,请求的核心函数是DispatcherServlet
中的doDispatch
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { try { mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
mappedHandler.applyPostHandle(processedRequest, response, mv); processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } }
|
目标方法出错,也会执行后置操作
HandlerExecutionChain
mappedHandler
中包含:handler
和拦截器链
1 2 3 4 5 6 7 8
| mappedHandler = {HandlerExecutionChain} handler = {HandlerMethod} interceptorList = {ArrayList} size = 3 0={Onelnterceptor} 1={Twolnterceptor} 2={Threelnterceptor} 3={ConversionServiceExposinglnterceptor} 4={ResourceUrlProviderExposinglnterceptor}
|
applyPreHandle
(前置处理):可以看到,顺序执行了所有拦截器的前置操作。每次都记录了this.interceptorIndex
。如果中间有返回false
的,则立刻执行triggerAfterCompletion
方法。
1 2 3 4 5 6 7 8 9 10 11
| boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { for (int i = 0; i < this.interceptorList.size(); i++) { HandlerInterceptor interceptor = this.interceptorList.get(i); if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } return true; }
|
而triggerAfterCompletion
则是从this.interceptorIndex
开始逆序执行了所有的后置操作
1 2 3 4 5 6
| void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); interceptor.afterCompletion(request, response, this.handler, ex); } }
|
applyPostHandle
(后置处理):可以看到,逆序执行了所有后置操作
1 2 3 4 5 6 7 8
| void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); interceptor.postHandle(request, response, this.handler, mv); } }
|
processDispatchResult
(渲染页面):可以看到,渲染完成后,逆序执行了所有的最终操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
if (mv != null && !mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
|
1 2 3 4 5 6 7 8
| void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); interceptor.afterCompletion(request, response, this.handler, ex); } }
|