Spring mvc之HandlerExecutionChain

2021-03-31  本文已影响0人  engineer_tang

处理程序执行链,由处理程序对象和任何处理程序拦截器组成。由HandlerMapping的HandlerMapping.getHandler方法返回。
其属性有:

  1. Object类型的handler;
  2. HandlerInterceptor[]类型的interceptors;
  3. List<HandlerInterceptor>类型的interceptorList;
  4. int类型的interceptorIndex;
    其构造方法有两个,如下所示:
public HandlerExecutionChain(Object handler);
public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors);

构造方法具体实现代码:

    public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) {
        if (handler instanceof HandlerExecutionChain) {
            HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
            this.handler = originalChain.getHandler();
            this.interceptorList = new ArrayList<>();
            CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
            CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
        }
        else {
            this.handler = handler;
            this.interceptors = interceptors;
        }
    }

从构造方法可以发现,实例化入参有2个,分别是handler和interceptors数组。首先,判断handler是否为HandlerExecutionChain的实例,如果是则进行强制类型转换,获取handler并存入当前对象的handler中,然后把handler入参的interceptors对象存入当前实例化的interceptorList中,以及入参中的interceptors存入当前对象的interceptorList中;如果handler不是HandlerExecutionChain的实例,则直接把handler存入当前实例的handler字段中,interceptors数组对象存入当前实例的interceptors属性字段中。

1. applyPreHandle方法

返回值:如果执行链应继续处理下一个拦截器或处理程序本身,则为true。否则,DispatcherServlet假设这个拦截器已经处理了响应本身。

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            for (int i = 0; i < interceptors.length; i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i;
            }
        }
        return true;
    }

2. applyPostHandle方法

应用已注册拦截器的postHandle方法。

    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
            throws Exception {

        HandlerInterceptor[] interceptors = 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);
            }
        }
    }

3. triggerAfterCompletion方法

在映射的HandlerInterceptors上触发完成后回调。将只为其预处理调用已成功完成并返回true的所有拦截器调用afterCompletion。

    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
            throws Exception {

        HandlerInterceptor[] interceptors = 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 ex2) {
                    logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
                }
            }
        }
    }

4. applyAfterConcurrentHandlingStarted方法

在映射的AsyncHandlerInterceptors上应用afterConcurrentHandlerStarted回调。

    void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
        HandlerInterceptor[] interceptors = getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            for (int i = interceptors.length - 1; i >= 0; i--) {
                HandlerInterceptor interceptor = interceptors[i];
                if (interceptor instanceof AsyncHandlerInterceptor) {
                    try {
                        AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptor;
                        asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
                    }
                    catch (Throwable ex) {
                        if (logger.isErrorEnabled()) {
                            logger.error("Interceptor [" + interceptor + "] failed in afterConcurrentHandlingStarted", ex);
                        }
                    }
                }
            }
        }
    }

5. 装载拦截器

AbstractHandlerMapping类中,获取到HandlerMethod对象后,如果不为空就会给其包装成一个HandlerExecutionChain对象,该对象将被加入拦截器信息。
为给定的处理程序构建HandlerExecutionChain,包括适用的拦截器。
默认实现使用给定的处理程序、处理程序映射的公共拦截器以及与当前请求URL匹配的任何MappedInterceptors构建标准HandlerExecutionChain。拦截器按注册顺序添加。子类可以重写它以扩展/重新排列拦截器列表。
如下代码所示:

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

        String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
            if (interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            }
            else {
                chain.addInterceptor(interceptor);
            }
        }
        return chain;
    }
上一篇下一篇

猜你喜欢

热点阅读