文章目录

  • 概念
  • 组成角色
  • 相关图示
  • 示例代码
  • 框架中的应用
  • 适用场景:

概念

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,其主要目的是将请求的发送者和接收者解耦。这种模式创建了一系列处理器对象,每个处理器都有一个对应的处理逻辑。当一个请求到来时,这些处理器按照顺序处理请求,直到其中一个处理器成功处理请求为止。

组成角色

  1. 抽象处理器(Handler):定义了一个处理请求的接口,包含一个指向下一个处理器的引用。
  2. 具体处理器(ConcreteHandler):实现抽象处理器接口,执行具体的处理逻辑,并决定请求是否传递给下一个处理器。
  3. 客户端(Client):负责创建处理器链,并向处理器链发送请求。

相关图示

图片来自:https://refactoringguru.cn/design-patterns/chain-of-responsibility

示例代码

//定义抽象处理器(Handler)abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);}//定义具体处理器(ConcreteHandler) HandlerA、HandlerB、HandlerCclass HandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("Handler A is processing the request");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}}class HandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("Handler B is processing the request");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}}class HandlerC extends Handler {@Overridepublic void handleRequest(String request) {if ("C".equals(request)) {System.out.println("Handler C is processing the request");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}}//客户端代码public class Client {public static void main(String[] args) {/**客户端创建了三个具体处理器,并将它们连接成一个处理器链。当客户端向处理器链发送请求时,处理器会按照顺序处理请求,直到其中一个处理器成功处理请求为止。**/// 创建处理器对象Handler handlerA = new HandlerA();Handler handlerB = new HandlerB();Handler handlerC = new HandlerC();// 构建处理器链handlerA.setNextHandler(handlerB);handlerB.setNextHandler(handlerC);// 发送请求handlerA.handleRequest("A");handlerA.handleRequest("B");handlerA.handleRequest("C");handlerA.handleRequest("D");}}

框架中的应用

拦截器链(Interceptor Chain):在Spring MVC框架中,当请求经过过滤器链处理并到达Servlet之后,请求会被传递给DispatcherServlet。DispatcherServlet的主要职责是将请求分发给适当的处理器(如Controller方法)。

Spring MVC中拦截器的执行流程:

  1. 请求到达DispatcherServlet
  2. DispatcherServlet根据请求获取处理器(Handler)和拦截器链(Interceptor Chain)。
  3. DispatcherServlet遍历拦截器链,依次执行拦截器的preHandle方法。如果某个拦截器的preHandle方法返回false,则中止后续拦截器和处理器的执行,并立即返回响应。preHandle方法通常用于执行请求预处理逻辑,例如身份验证和授权检查。
  4. 如果所有拦截器的preHandle方法都返回true,则DispatcherServlet执行处理器(Handler)来处理请求。
  5. 处理器处理完请求后,DispatcherServlet再次遍历拦截器链,按照相反的顺序依次执行拦截器的postHandle方法。postHandle方法在处理器执行之后、视图渲染之前调用,通常用于添加模型属性或对请求进行后处理。
  6. 最后,DispatcherServlet渲染视图并返回响应。
  7. 在请求处理完成并且视图渲染完成之后,DispatcherServlet再次遍历拦截器链,按照相反的顺序依次执行拦截器的afterCompletion方法。afterCompletion方法通常用于清理资源和记录日志等操作。

抽象拦截处理器(Handler)

public interface HandlerInterceptor {boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;}

处理器执行链(HandlerChain)

public class HandlerExecutionChain {private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class); // 处理器对象private final Object handler;// 拦截器数组private HandlerInterceptor[] interceptors;// 拦截器列表private List<HandlerInterceptor> interceptorList;// 当前处理的拦截器索引private int interceptorIndex;public HandlerExecutionChain(Object handler) {this(handler, (HandlerInterceptor[]) null);}public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {this.interceptorIndex = -1;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;}}public void addInterceptor(HandlerInterceptor interceptor) {this.initInterceptorList().add(interceptor);}public void addInterceptors(HandlerInterceptor... interceptors) {if (!ObjectUtils.isEmpty(interceptors)) {this.initInterceptorList().addAll(Arrays.asList(interceptors));}}private List<HandlerInterceptor> initInterceptorList() {if (this.interceptorList == null) {this.interceptorList = new ArrayList();if (this.interceptors != null) {this.interceptorList.addAll(Arrays.asList(this.interceptors));}}this.interceptors = null;return this.interceptorList;}public HandlerInterceptor[] getInterceptors() {if (this.interceptors == null && this.interceptorList != null) {this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);}return this.interceptors;}// 执行拦截器链中的preHandle方法boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {HandlerInterceptor[] interceptors = this.getInterceptors();if (!ObjectUtils.isEmpty(interceptors)) {for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {HandlerInterceptor interceptor = interceptors[i];if (!interceptor.preHandle(request, response, this.handler)) {this.triggerAfterCompletion(request, response, (Exception)null);return false;}}}return true;}// 执行拦截器链中的postHandle方法void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {HandlerInterceptor[] interceptors = this.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);}}}// 触发拦截器链中的afterCompletion方法void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {HandlerInterceptor[] interceptors = this.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 var8) {logger.error("HandlerInterceptor.afterCompletion threw exception", var8);}}}}}

适用场景:

  1. 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时,可以使用责任链模式。
  2. 当必须按顺序执行多个处理者时,可以使用该模式。
  3. 如果所需处理者及其顺序必须在运行时进行改变,可以使用责任链模式。

以下是一些责任链设计模式的典型应用场景:

  • 日志记录:不同级别的日志消息可以由不同的日志处理器处理,例如,DEBUG、INFO、WARNING和ERROR级别的日志分别由不同的处理器处理。
  • 权限验证:根据用户的权限和角色对请求进行多层次的验证。例如,先验证用户身份,然后验证用户是否有访问特定资源的权限。
  • 请求过滤:在Web应用中,可以使用责任链模式实现请求过滤器,对请求进行预处理(如身份验证、数据验证等)和后处理(如添加响应头、日志记录等)。
  • 事件处理:在图形用户界面(GUI)中,事件可以由多个处理器处理,如按钮点击、键盘输入等。责任链模式可以实现事件处理的优先级和顺序。