可动态配置的责任链设计模式

什么是责任链

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

使用场景

责任链的使用场景还是比较多的:

  • 多条件流程判断:权限控制

  • ERP 系统流程审批:总经理、人事经理、项目经理

  • Java 过滤器的底层实现 Filter

如果不使用该设计模式,那么当需求有所改变时,就会使得代码臃肿或者难以维护

责任链设计

  • 抽象处理者(Handler)角色: 定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

  • 具体处理者(Concrete Handler)角色: 实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

  • 客户类(Client)角色: 创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

  

代码片段

把这个关系维护到配置文件中或者一个枚举中。使用枚举动态的配置请求链并且将每个请求者形成一条调用链。以下通过统一网关demo来列举示例

public enum GatewayEnum {

    API_HANDLER(new GatewayEntity(1, "接口限流", "com.lyk.handler.ApiLimitGatewayHandler", null, 2)),
    BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截", "com.lyk.handler.BlacklistGatewayHandler", 1, 3)),
    PARSE_HANDLER(new GatewayEntity(3, "请求解析", "com.lyk.handler.ParseGatewayHandler", 2, 4)),
    ROUTE_HANDLER(new GatewayEntity(4, "路由转发", "com.lyk.handler.RouteGatewayHandler", 3, null));

    final GatewayEntity gatewayEntity;

    public GatewayEntity getGatewayEntity() {
        return gatewayEntity;
    }

    GatewayEnum(GatewayEntity gatewayEntity) {
        this.gatewayEntity = gatewayEntity;
    }
}

 实体类

public class GatewayEntity {

    // 拦截者名称
    private String name;

    // 全限定类名
    private String conference;

    // ID
    private Integer handlerId;

    // 上一个ID
    private Integer preHandlerId;

    // 下一个ID
    private Integer nextHandlerId;
}

 处理接口

public interface GatewayDao {
    /**
     * 根据 handlerId 获取配置项
     *
     * @param handlerId
     * @return
     */
    GatewayEntity getGatewayEntity(Integer handlerId);

    /**
     * 获取第一个处理者
     *
     * @return
     */
    GatewayEntity getFirstGatewayEntity();
}

处理接口实现

public class GatewayImpl implements GatewayDao {
    /**
     * 初始化,将枚举中配置的handler初始化到map中,方便获取
     */
    private static final Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();

    static {
        GatewayEnum[] values = GatewayEnum.values();
        for (GatewayEnum value : values) {
            GatewayEntity gatewayEntity = value.getGatewayEntity();
            gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
        }
    }

    @Override
    public GatewayEntity getGatewayEntity(Integer handlerId) {
        return gatewayEntityMap.get(handlerId);
    }

    @Override
    public GatewayEntity getFirstGatewayEntity() {
        for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {
            GatewayEntity value = entry.getValue();
            //  没有上一个handler的就是第一个
            if (value.getPreHandlerId() == null) {
                return value;
            }
        }
        return null;
    }
}

hander枚举工厂

public class GatewayHandlerEnumFactory {
    private static GatewayDao gatewayDao = new GatewayImpl();

    // 提供静态方法,获取第一个handler
    public static GatewayHandler getFirstGatewayHandler() {

        GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();
        GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);
        if (firstGatewayHandler == null) {
            return null;
        }

        GatewayEntity tempGatewayEntity = firstGatewayEntity;
        Integer nextHandlerId = null;
        GatewayHandler tempGatewayHandler = firstGatewayHandler;

        // 迭代遍历所有handler,以及将它们链接起来
        while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {
            GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);
            GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);
            tempGatewayHandler.setNext(gatewayHandler);
            tempGatewayHandler = gatewayHandler;
            tempGatewayEntity = gatewayEntity;
        }
        // 返回第一个handler
        return firstGatewayHandler;
    }

    /**
     * 反射实体化具体的处理者
     *
     * @param firstGatewayEntity
     * @return
     */
    private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {
        // 获取全限定类名
        String className = firstGatewayEntity.getConference();
        try {
            // 根据全限定类名,加载并初始化该类,即会初始化该类的静态段
            Class<?> clazz = Class.forName(className);
            return (GatewayHandler) clazz.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

抽象handler

public abstract class GatewayHandler {
    /**
     * 下一关用当前抽象类来接收
     */
    protected GatewayHandler next;

    public void setNext(GatewayHandler next) {
        this.next = next;
    }

    public abstract void handler();
}

 责任者实现类

public class ParseGatewayHandler extends GatewayHandler {
    @Override
    public void handler() {
        System.out.println("请求解析开始");
        if (this.next != null) {
            this.next.handler();
        }
    }
}

客户端调用

public class GetewayClient {
    public static void main(String[] args) {
        GatewayHandler firstGetewayHandler = GatewayHandlerEnumFactory.getFirstGatewayHandler();
        firstGetewayHandler.handler();
    }
}

 完整项目链接:https://github.com/liyukun00f/lyk_gateway

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值