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

2022/4/12 23:15:43

本文主要是介绍责任链模式-以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

 



这篇关于责任链模式-以SpringMVC中DispatcherServlet的HandlerExecutionChain为例的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程