美文网首页
Spring mvc之HandlerExecutionChain

Spring mvc之HandlerExecutionChain

作者: engineer_tang | 来源:发表于2021-03-31 06:51 被阅读0次

    处理程序执行链,由处理程序对象和任何处理程序拦截器组成。由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;
        }
    

    相关文章

      网友评论

          本文标题:Spring mvc之HandlerExecutionChain

          本文链接:https://www.haomeiwen.com/subject/zgrghltx.html