力不竭!!!战不止!!!

力不竭!!!战不止!!!

概念

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

组成角色

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

相关图示

责任链设计模式(Chain of Responsibility Pattern)[论点:概念、组成角色、图示、相关代码、框架中的运用、适用场景]-LMLPHP

示例代码

//定义抽象处理器(Handler)
abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(String request);
}



//定义具体处理器(ConcreteHandler) HandlerA、HandlerB、HandlerC
class HandlerA extends Handler {
    @Override
    public 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 {
    @Override
    public 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 {
    @Override
    public 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)中,事件可以由多个处理器处理,如按钮点击、键盘输入等。责任链模式可以实现事件处理的优先级和顺序。
04-13 04:22