微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

责任链模式-以SpringMVC中DispatcherServlet的HandlerExecutionChain为例

责任链模式的定义:

责任链模式为请求创建了一个接收者对象的链,在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

在SpringMVC中dispatcherServlet的HandlerExecutionChain也应用了这一设计模式的思路(可能并不是太典型,这个最后总结):

protected void dodispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
               ...
                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);// Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                ...
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applydefaultviewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            
            ...
        
        
    }


重点看标红的代码,在dodispatch方法中定义并获取了HandlerExecutionChain的对象,然后调用了applyPreHandle、applyPostHandle方法

首先看下HandlerExecutionChain的作用:

public class HandlerExecutionChain {
private final Object handler;

    @Nullable
    private handlerinterceptor[] interceptors;

    @Nullable
    private List<handlerinterceptor> interceptorList;

    private int interceptorIndex = -1;
       ...

HandlerExecutionChain持有http请求的处理器,即代码中的handler对象,以及拦截器的数组interceptors,既处理http请求的具体逻辑,又使用拦截器对http请求进行拦截,而此处对于拦截器的调用就应用了责任链模式的思路:

applyPreHandle方法

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;
    }

此处遍历拦截器的数组,调用拦截器的preHandle方法对请求进行处理,并且只有当本次preHandle处理返回true时,下一个拦截器才会进行执行preHandle方法;如果返回false,就执行triggerAfterCompletion并跳出循环。

总结:为什么开头说不是特别典型的责任链模式,因为此处的拦截器没有包含对另一拦截器的引用,而是通过数组的方式来达到类似的效果

triggerAfterCompletion方法

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);
                }
            }
        }
    }

此处逻辑类似,只不过这里调用的是拦截器的afterCompletion方法

applyPostHandle方法

    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);
            }
        }
    }

此处逻辑类似,只不过这里调用的是拦截器的postHandle方法

典型责任链模式:

https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐