赞
踩
拦截器可以在进入请求方法前做一些操作,也可以在请求方法后和渲染视图后做一些事情。拦截器的实现只需要实现 HandlerInterceptor 接口,并进行配置即可。
preHandler
:进入请求方法之前执行;
postHandler
:请求方法执行完成之后执行;
afterCompletion
:视图渲染后执行。
如果只配置了一个拦截器,那么执行顺序应该是这样的:
preHandle
-> dohandle
(处理请求)-> postHandle
-> render
(渲染视图)-> afterCompletion
在 preHandle 方法中,它的返回值是 boolean 类型的,它的返回值影响着请求方法,以及 postHandle 和 afterCompletion 的执行。在 preHandle 中如果返回 false,那么后续的流程将不被执行。
当有多个自定义拦截器时这些方法的执行顺序则是不同,如果preHandler都返回true的情况下,preHandle方法按自定义拦截器配置的正序执行,而postHandle和afterCompletion方法按自定义拦截器配置的倒序执行;
如果某个拦截器返回false,postHandle方法都不会被执行,另外只有返回true的拦截器的afterCompletion方法才会执行。
一个请求打进来时,DispatcherServlet 中的 doDispatch 方法会进行拦截器的调用,如下代码注释部分
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { try { ModelAndView mv = null; Object dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; } HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } // 执行拦截器的全部 preHandle 方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } this.applyDefaultViewName(processedRequest, mv); // 执行拦截器的全部 postHandle 方法 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed", var21); } // 执行拦截器的全部 afterCompletion 方法 this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { // 异常后,执行拦截器的全部 afterCompletion 方法 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { // 异常后,执行拦截器的全部 afterCompletion 方法 this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }
在mappedHandler.applyPreHandle() 方法中,通过HandlerInterceptor[] interceptors = this.getInterceptors();
依序获得registry.addInterceptor()中加入的拦截器,for循环正序执行拦截器逻辑
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
而在mappedHandler.applyPostHandle()方法中,同样是通过HandlerInterceptor[] interceptors = this.getInterceptors(); `依序获得registry.addInterceptor()中加入的拦截器,不过在for循环中是倒序执行逻辑
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
最后看一下mappedHandler.triggerAfterCompletion() 方法,同样for循环里是倒序执行逻辑
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
}
上面的拦截器都是按照我们配置中的顺序执行,那如果我们想要自定义顺序该怎么办呢, InterceptorRegistry 类的 addInterceptor 和 getInterceptors 方法源码如下,我们可以看到addInterceptor是将拦截器加入list集合,在getInterceptors 方法中this.registrations.stream().sorted(INTERCEPTOR_ORDER_COMPARATOR)
, 拦截器list集合按照 order 升序排序,默认order为0,可以在配置中用.order(int order)
设置顺序。
public class InterceptorRegistry { private final List<InterceptorRegistration> registrations = new ArrayList(); private static final Comparator<Object> INTERCEPTOR_ORDER_COMPARATOR; public InterceptorRegistry() { } public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) { InterceptorRegistration registration = new InterceptorRegistration(interceptor); this.registrations.add(registration); return registration; } public InterceptorRegistration addWebRequestInterceptor(WebRequestInterceptor interceptor) { WebRequestHandlerInterceptorAdapter adapted = new WebRequestHandlerInterceptorAdapter(interceptor); InterceptorRegistration registration = new InterceptorRegistration(adapted); this.registrations.add(registration); return registration; } protected List<Object> getInterceptors() { return (List)this.registrations.stream().sorted(INTERCEPTOR_ORDER_COMPARATOR).map(InterceptorRegistration::getInterceptor).collect(Collectors.toList()); } static { INTERCEPTOR_ORDER_COMPARATOR = OrderComparator.INSTANCE.withSourceProvider((object) -> { if (object instanceof InterceptorRegistration) { InterceptorRegistration var10000 = (InterceptorRegistration)object; ((InterceptorRegistration)object).getClass(); return var10000::getOrder; } else { return null; } }); } }
如果不设定拦截器顺序,preHandle 方法执行顺序与拦截器注册时顺序一致,postHandle 和 afterCompletion 方法执行顺序相反;如果我们给每个拦截器设置order ,则 preHandle 方法执行顺序是按照 order 升序执行,postHandle 和 afterCompletion 方法执行顺序反之。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。