当前位置:   article > 正文

springboot中的拦截器_springboot拦截器执行顺序

springboot拦截器执行顺序

一、拦截器介绍

拦截器可以在进入请求方法前做一些操作,也可以在请求方法后和渲染视图后做一些事情。拦截器的实现只需要实现 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);
            }
 
        }
    }
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

在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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

而在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);
            }
        }
 
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最后看一下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);
                }
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上面的拦截器都是按照我们配置中的顺序执行,那如果我们想要自定义顺序该怎么办呢, 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;
            }
        });
    }
}
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

五、总结

如果不设定拦截器顺序,preHandle 方法执行顺序与拦截器注册时顺序一致,postHandle 和 afterCompletion 方法执行顺序相反;如果我们给每个拦截器设置order ,则 preHandle 方法执行顺序是按照 order 升序执行,postHandle 和 afterCompletion 方法执行顺序反之。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/716398
推荐阅读
相关标签
  

闽ICP备14008679号