精讲23种设计模式-007:基于责任链模式构建网关权限链系统

1 基于责任链模式课程内容介绍

课程内容

  1. 责任链设计模式基本概念
  2. 责任链模式的应用场景
  3. 基于工厂模式整合责任链
  4. 基于数据库配置整合责任链

2 责任链基本介绍

责任链基本概念
多个对象形成一个链,每个对象相互指向上一个和下一个对象。

责任链应用场景

  1. 过滤器
  2. 审批 eg:请假流程(项目组长->项目经理->人事经理->总经理)
  3. 工作流框架
  4. 风控系统 金融或者p2p 上失信名单->信用卡是否逾期->蚂蚁信用积分是否大于640
  5. 多重if判断问题 (微服务网关) ip地址是否限流->ip地址是否在黑名单->是否传递token

3 责任链类图结构分析

在这里插入图片描述
Handler 单个小的执行流程(每个if判断流程)
每个处理器对象都会指向下一个处理器对象形成一个链,这个链类似链表数据结构。
如果处理器对象指向下一个处理器对象为空的情况下,说明是尾部;如果处理器对象的上一个处理器对象为空,说明该对象为头部。

4 基于工厂模式实现责任链

基于工厂模式实现责任链

public abstract class GatewayHandler {

    /**
     * 每个不同的处理器 处理的业务逻辑
     */
    public abstract void doService();

    protected GatewayHandler nextGatewayHandler;

    public GatewayHandler(GatewayHandler nextGatewayHandler) {
        this.nextGatewayHandler = nextGatewayHandler;
    }
}
@Slf4j
public class CurrentLimitHandler extends GatewayHandler {

    public CurrentLimitHandler(GatewayHandler nextGatewayHandler) {
        super(nextGatewayHandler);
    }

    @Override
    public void doService() {
        log.info(">>>第一关 ip限流处理业务逻辑判断");
        // 指向下一个节点
        nextGatewayHandler.doService();
    }
}
@Slf4j
public class BlacklistHandler extends GatewayHandler {

    public BlacklistHandler(GatewayHandler nextGatewayHandler) {
        super(nextGatewayHandler);
    }

    @Override
    public void doService() {
        log.info(">>>第二关 ip黑名单逻辑判断");
        nextGatewayHandler.doService();
    }
}
@Slf4j
public class TokenHandler extends GatewayHandler {

    public TokenHandler(GatewayHandler nextGatewayHandler) {
        super(nextGatewayHandler);
    }

    @Override
    public void doService() {
        log.info(">>>第三关 验证token逻辑判断");
    }
}
public class FactoryHandler {

    public static CurrentLimitHandler currentLimitHandler() {
        return new CurrentLimitHandler(new BlacklistHandler(new TokenHandler(null)));
    }

    public static void main(String[] args) {
        CurrentLimitHandler currentLimitHandler = FactoryHandler.currentLimitHandler();
        currentLimitHandler.doService();
    }
}

运行结果:
请添加图片描述

5 基于Set方式实现责任链模式

public abstract class GatewayHandler {

    /**
     * 每个不同的处理器 处理的业务逻辑
     */
    public abstract void doService();

    protected GatewayHandler nextGatewayHandler;

    public GatewayHandler(){}

    public void setNextGatewayHandler(GatewayHandler nextGatewayHandler) {
        this.nextGatewayHandler = nextGatewayHandler;
    }
}
@Slf4j
public class CurrentLimitHandler extends GatewayHandler {

    public CurrentLimitHandler() {

    }

    @Override
    public void doService() {
        log.info(">>>第一关 ip限流处理业务逻辑判断");
        // 指向下一个节点
        nextGatewayHandler.doService();
    }
}
@Slf4j
public class BlacklistHandler extends GatewayHandler {

    public BlacklistHandler() {

    }

    @Override
    public void doService() {
        log.info(">>>第二关 ip黑名单逻辑判断");
        nextGatewayHandler.doService();
    }
}
@Slf4j
@Component
public class TokenHandler extends GatewayHandler {

    public TokenHandler() {

    }

    @Override
    public void doService() {
        log.info(">>>第三关 验证token逻辑判断");
    }
}
public class FactoryHandler {

    public static CurrentLimitHandler currentLimitHandler2() {
        CurrentLimitHandler currentLimitHandler = new CurrentLimitHandler();
        BlacklistHandler blacklistHandler = new BlacklistHandler();
        currentLimitHandler.setNextGatewayHandler(blacklistHandler);
        blacklistHandler.setNextGatewayHandler(new TokenHandler());
        return currentLimitHandler;
    }

    public static void main(String[] args) {
        CurrentLimitHandler currentLimitHandler2 = FactoryHandler.currentLimitHandler2();
        currentLimitHandler2.doService();
    }
}

运行结果同上图

6 基于数据库的方式实现责任链

数据库表

CREATE TABLE `gateway_handler` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `handler_name` varchar(32) DEFAULT NULL COMMENT 'handler名称',
  `handler_id` varchar(32) DEFAULT NULL COMMENT 'handler主键id',
  `prev_handler_id` varchar(32) DEFAULT NULL,
  `next_handler_id` varchar(32) DEFAULT NULL COMMENT '下一个handler',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT='权限表';

INSERT INTO `test`.`gateway_handler`(`ID`, `handler_name`, `handler_id`, `prev_handler_id`, `next_handler_id`) VALUES (16, 'Api接口限流', 'currentLimitHandler', NULL, 'blacklistHandler');
INSERT INTO `test`.`gateway_handler`(`ID`, `handler_name`, `handler_id`, `prev_handler_id`, `next_handler_id`) VALUES (17, '黑名单拦截', 'blacklistHandler', 'currentLimitHandler', 'tokenHandler');
INSERT INTO `test`.`gateway_handler`(`ID`, `handler_name`, `handler_id`, `prev_handler_id`, `next_handler_id`) VALUES (18, 'token验证', 'tokenHandler', 'blacklistHandler', NULL);

代码类

@Data
@TableName("gateway_handler")
public class GatewayHandlerEntity implements Serializable, Cloneable {
    /** 主键ID */
    private Integer id;
    /** handler名称 */
    private String handlerName;
    /** handler主键id */
    private String handlerId;
    /** 下一个handlerId */
    private String nextHandlerId;
}
public interface GatewayHandlerMapper extends BaseMapper<GatewayHandlerEntity> {
}
@Slf4j
@Component
public class DbHandler {

    @Autowired
    private GatewayHandlerMapper gatewayHandlerMapper;

    // 通过将headGatewayHandler作为属性参数用作缓存,不用每次查询数据库
    private GatewayHandler headGatewayHandler;

    public GatewayHandler getFirstGatewayHandler() {
        // 如果调用关联关系发生变化,单独写一个接口手动将headGatewayHandler刷新为null
        if (headGatewayHandler != null) {
            return headGatewayHandler;
        }
        // 查询头节点 查询pre_handler_id为空的情况下,表名为头节点
        QueryWrapper<GatewayHandlerEntity> firstQueryWrapper = new QueryWrapper<>();
        firstQueryWrapper.isNull("prev_handler_id");
        GatewayHandlerEntity gatewayHandlerEntity = gatewayHandlerMapper.selectOne(firstQueryWrapper);
        if (gatewayHandlerEntity == null) {
            log.error(">>>没有配置头节点");
            return null;
        }
        // 2.获取头节点的handlerId
        String handlerId = gatewayHandlerEntity.getHandlerId();
        if (StringUtils.isEmpty(handlerId)) {
            log.error(">>>没有配置头节点的handler_id");
            return null;
        }
        // 3.从容器中获取头节点handler对象
        GatewayHandler headGatewayHandler = SpringUtils.getBean(handlerId, GatewayHandler.class);
        if (headGatewayHandler == null) {
            log.error(">>>没有配置" + handlerId + "对象");
            return null;
        }
        // 4.获取下一个节点id
        String nextHandlerId = gatewayHandlerEntity.getNextHandlerId();
        // 记录当前循环变量
        GatewayHandler tempGatewayHandler = headGatewayHandler;
        while (StringUtils.isNotEmpty(nextHandlerId)) {
            // 从Spring容器中获取下一个节点
            GatewayHandler nextGatewayHandler = SpringUtils.getBean(nextHandlerId, GatewayHandler.class);
            if (nextGatewayHandler == null) {
                break;
            }
            QueryWrapper<GatewayHandlerEntity> nextQueryWrapper = new QueryWrapper<>();
            nextQueryWrapper.eq("handler_id", nextHandlerId);
            GatewayHandlerEntity nextGatewayEntity = gatewayHandlerMapper.selectOne(nextQueryWrapper);
            if (nextGatewayEntity == null) {
                break;
            }
            nextHandlerId = nextGatewayEntity.getNextHandlerId();

            tempGatewayHandler.setNextGatewayHandler(nextGatewayHandler);
            tempGatewayHandler = nextGatewayHandler;
        }
        this.headGatewayHandler = headGatewayHandler;
        return headGatewayHandler;
    }
}
@RestController
public class HandlerController {

    @Autowired
    private DbHandler bbHandler;

    @GetMapping("/getHandler")
    public void getHandler() {
        bbHandler.getFirstGatewayHandler().doService();
    }
}

运行结果:
请添加图片描述
责任链设计模式优缺点
优点:实现代码解耦,动态拼接每个链的关系,不需要改动代码直接通过数据库表进行维护;
缺点:粒度拆分过于精细,后期不断产生非常多类

源码下载地址(mayikt_designPattern_7.zip):
链接:https://pan.baidu.com/s/1wWKZN1MbXICZVW1Vxtwe6A
提取码:fire

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一套被广泛应用于软件开发中的设计思想和模板,它们提供了一种解决常见设计问题的通用解决方案。这些模式帮助开发人员在设计和实现软件时遵循最佳实践,提供了可重用、可扩展和易于维护的代码结构。 Java设计模式可以分为三个主要类别:创建型模式、结构型模式和行为型模式。 首先,创建型模式包含了单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式。这些模式用于创建对象和管理它们的实例化过程,以及确保系统中只存在一个实例或一组相关对象。 其次,结构型模式包含了适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。这些模式关注对象之间的组合和关系,以提供更灵活的结构和功能,并支持系统的扩展和修改。 最后,行为型模式包含了命令模式、中介者模式、观察者模式、迭代器模式、状态模式、策略模式、模板方法模式和访问者模式。这些模式用于管理对象之间的交互和通信,以及定义对象的行为和状态。 不同的设计模式适用于不同的情况和需求。开发人员可以根据自己的需求选择合适的模式,并将其应用于项目中,以提高代码质量、可重用性和可维护性。同时,理解和掌握设计模式也有助于培养良好的设计思维和编程技巧,提高开发人员的工程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值