设计模式之责任链模式

1. 责任链模式

1.1 责任链模式定义

当你想要让一个以上的对象 有机会能够处理某个请求的时候,就使用责任链模式

责任链模式为请求创建了一个接收者对象的链。执行链上有多个对象节点,每个对象节点都有机会(条件匹配)处理请求事务,如果某个对象节点处理完了,就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。

关键点

  • 解耦:请求的发送者不需要知道谁会处理这个请求,也不需要知道处理请求的具体过程。
  • 灵活性:可以在运行时动态地改变处理者链,使得系统更加灵活。
  • 可扩展性:可以轻松地向现有系统中添加新的处理者,而无需修改现有的代码。

结构

  • 抽象处理者(Handler) :定义了一个处理请求的接口,并且有一个指向其后续处理者的引用。

    具体处理者(Concrete Handler):实现抽象处理者的接口,根据实际情况决定是否处理请求或将其转发给下一个处理者。

  • 具体处理者(Concrete Handler):实现抽象处理者的接口,根据实际情况决定是否处理请求或将其转发给下一个处理者。

  • 客户端(Client):创建一个处理者链,并将请求提交给第一个处理者。

Spring AOP、Spring事务管理的一个重要特性是它使用了责任链模式;Spring MVC中的拦截器(Interceptor)等都用到了责任链模式。

1.2 责任链模式使用

责任链模式怎么使用呢?

  • 一个接口或者抽象类
  • 每个对象差异化处理
  • 对象链(数组)初始化(连起来)

1.3 具体代码

首先创建一个接口或者抽象类
java 复制代码
public abstract class AbstractHandler {

    /**
     * 责任链中的下一个对象
     */
    private AbstractHandler nextHandler;

    /**
     * 责任链的下一个对象
     */
    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 具体参数拦截逻辑,给子类去实现
     */
    public void filter(HttpServletRequest request, HttpServletResponse response) {
        doFilter(request, response);
        if (getNextHandler() != null) {
            getNextHandler().filter(request, response);
        }
    }

    public AbstractHandler getNextHandler() {
        return nextHandler;
    }

    /**
     * 抽象方法
     * @param filterRequest
     * @param response
     */
    abstract void doFilter(HttpServletRequest filterRequest, HttpServletResponse response);

}
每个对象差异化处理
java 复制代码
@Component
@Order(1)
public class CheckRequestHeaderFilterObject extends AbstractHandler {
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("请求头校验");
    }
}
java 复制代码
@Component
@Order(2)
public class CheckCorsFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("cors校验");
    }
}
java 复制代码
@Component
@Order(3)
public class CheckParamFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("参数合法校验");
    }
}
java 复制代码
@Component
@Order(4)
public class CheckBlackFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("黑名单校验");
    }
}
对象链连起来(初始化)&& 使用
java 复制代码
@Component("ChainPatternTest")
public class ChainPatternTest {

    /**
     * 自动注入各个责任链的对象
     */
    @Resource
    private List<AbstractHandler> abstractHandleList;

    private AbstractHandler abstractHandler;

    /**
     * spring注入后自动执行,责任链的对象连接起来
     */
    @PostConstruct
    public void initializeChainFilter() {
        for (int i = 0; i < abstractHandleList.size(); i++) {
            if (i == 0) {
                abstractHandler = abstractHandleList.get(0);
            } else {
                AbstractHandler currentHandler = abstractHandleList.get(i - 1);
                AbstractHandler nextHandler = abstractHandleList.get(i);
                currentHandler.setNextHandler(nextHandler);
            }
        }
    }

    /**
     * 直接调用这个方法使用,根据实际使用来返回数据内容等
     *
     * @param request
     * @param response
     * @return
     */
    public HttpServletResponse exec(HttpServletRequest request, HttpServletResponse response) {
        abstractHandler.filter(request, response);
        return response;
    }

    public AbstractHandler getAbstractHandler() {
        return abstractHandler;
    }

    public void setAbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }
}

调用运行结果如下:

json 复制代码
请求头校验
cors校验
参数合法校验
黑名单校验
相关推荐
ylfhpy4 分钟前
Java面试黄金宝典22
java·开发语言·算法·面试·职场和发展
风象南37 分钟前
Spring Boot 实现文件秒传功能
java·spring boot·后端
橘猫云计算机设计38 分钟前
基于django优秀少儿图书推荐网(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·小程序·django·毕业设计
黑猫Teng42 分钟前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
星河浪人1 小时前
Spring Boot启动流程及源码实现深度解析
java·spring boot·后端
佩奇的技术笔记1 小时前
中级:Maven面试题精讲
java·面试·maven
Lizhihao_1 小时前
JAVA-堆 和 堆排序
java·开发语言
极客先躯1 小时前
高级java每日一道面试题-2025年3月21日-微服务篇[Nacos篇]-什么是Nacos?
java·开发语言·微服务
工业互联网专业1 小时前
基于springboot+vue的动漫交流与推荐平台
java·vue.js·spring boot·毕业设计·源码·课程设计·动漫交流与推荐平台
雷渊1 小时前
深入分析Spring的事务隔离级别及实现原理
java·后端·面试