责任链模式为请求创建了一个接收者对象的链,在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
在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请求进行拦截,而此处对于拦截器的调用就应用了责任链模式的思路:
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并跳出循环。
总结:为什么开头说不是特别典型的责任链模式,因为此处的拦截器没有包含对另一拦截器的引用,而是通过数组的方式来达到类似的效果。
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方法。
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