(责任链模式)java可插拔式逻辑处理流程的实现

本文深入解析了责任链模式的概念、实现方式及应用实例,通过具体的代码示例展示了如何使用类Servlet的Filter实现逻辑处理流程的可插拔和独立维护,同时讨论了模式的优缺点。

关于责任链模式的学习资料

一、责任链模式的概念

【菜鸟教程】责任链模式

二、责任链模式的实现方式

【atheva】责任链模式实现的三种方式

这里采用了类servlet的Filter的实现方式,基本实现了逻辑处理流程在运行中的可插拔以及每个逻辑处理节点的独立维护

在责任链的不同节点中,使用k-v进行参数传递

public class ChainParam {
    private Map<ChainParamKeyEnum, Object> param = new ConcurrentHashMap<ChainParamKeyEnum, Object>();
    public static ChainParam newChainParam() {
        return new ChainParam();
    }
    public Object getParam(ChainParamKeyEnum key) {
        Object value = param.get(key);
        if (key.getClazz().isInstance(value)) {
            return value;
        }
        if (null != value) {
            throw new ClassCastException("get value is not type of clazz");
        }
        return null;
    }
    public Object putParam(ChainParamKeyEnum key, Object value) {
        if (null == value) {
            return null;
        }
        if (null != value && !key.getClazz().isInstance(value)) {
            throw new ClassCastException("put value is not type of clazz");
        }
        return param.put(key, value);
    }
    @Override
    public String toString() {
        return param.toString();
    }
}
public enum ChainParamKeyEnum {
    // dataInKey start
    DATA_IN_STRING(String.class),
    // dataInKey end
    // dataOutKey start
    DATA_OUT_STRING(String.class),
    // dataOutKey end
    // chainContextKey start
    CHAIN_CONTEXT_STRING(String.class)
    // chainContextKey end
    ;
    private Class<?> clazz;
    private ChainParamKeyEnum(Class<?> clazz) {
        this.clazz = clazz;
    }
    public Class<?> getClazz() {
        return this.clazz;
    }
}

责任链的实现框架

public interface Action {
    public void doChainAction(ChainParam dataIn, ChainParam dataOut, ChainParam chainContext, Chain chain);
}
public interface ChainNode<C, V> {
    C link(V t);
    C next();
    V nodeValue();
}
public class Chain implements Action, ChainNode<Chain, Action> {
    private static final Chain EOFChain = new Chain(null);
    private Chain nextChain;
    private final Action nodeAction;
    private Chain(Action nodeAction) {
        this.nodeAction = nodeAction;
        this.nextChain = EOFChain;
    }
    public static Chain newChain(Action nodeValue) {
        return new Chain(nodeValue);
    }
    @Override
    public Chain link(Action action) {
        Chain tNextChain = new Chain(action);
        this.nextChain = tNextChain;
        return tNextChain;
    }
    @Override
    public Chain next() {
        return this.nextChain;
    }
    @Override
    public Action nodeAction() {
        return this.nodeAction;
    }
    @Override
    public void doChainAction(ChainParam dataIn, ChainParam dataOut, ChainParam chainContext, Chain chain) {
        Action tAction = null;
        if (null == chain || null == (tAction = chain.nodeAction())) {
            return;
        }
        if (EOFChain == chain) {
            return;
        }
        tAction.doChainAction(dataIn, dataOut, chainContext, chain.next());
    }
}

责任链的处理节点编写

public class PrintDataIn implements Action {
    @Override
    public void doChainAction(ChainParam dataIn, ChainParam dataOut, ChainParam chainContext, Chain chain) {
        System.out.println(String.format("PrintDataIn print ChainParam dataIn:%s", dataIn));
        chain.doChainAction(dataIn, dataOut, chainContext, chain);
    }
}
public class GenerateDataOut implements Action {
    private static final ChainParamKeyEnum DATA_OUT_STRING = ChainParamKeyEnum.DATA_OUT_STRING;
    @Override
    public void doChainAction(ChainParam dataIn, ChainParam dataOut, ChainParam chainContext, Chain chain) {
        System.out.println(String.format("GenerateDataOut print ChainParam dataOut:%s", dataOut));
        System.out.println(String.format("GenerateDataOut generate ChainParam key:%s value:%s", DATA_OUT_STRING, "this is a dataOutValue"));
        dataOut.putParam(DATA_OUT_STRING, "this is a dataOutValue");
        chain.doChainAction(dataIn, dataOut, chainContext, chain);
    }
}
public class PrintChainContext implements Action {
    @Override
    public void doChainAction(ChainParam dataIn, ChainParam dataOut, ChainParam chainContext, Chain chain) {
        System.out.println(String.format("PrintChainContext print ChainParam chainContext:%s", chainContext));
        chain.doChainAction(dataIn, dataOut, chainContext, chain);
    }
}

将处理节点根据需要拼接成处理链条对dataIn进行处理,输出dataOut

public class Main {
    private static final ChainParamKeyEnum DATA_IN_STRING = ChainParamKeyEnum.DATA_IN_STRING;
    private static final ChainParamKeyEnum CHAIN_CONTEXT_STRING = ChainParamKeyEnum.CHAIN_CONTEXT_STRING;
    public static void main(String[] args) {
        // dataIn用于存储输入,dataOut用于存储链条中的处理输出,chainContext用于存储链条处理中的环境参数
        ChainParam dataIn = ChainParam.newChainParam();
        ChainParam dataOut = ChainParam.newChainParam();
        ChainParam chainContext = ChainParam.newChainParam();
        dataIn.putParam(DATA_IN_STRING, "this is a dataInValue");
        chainContext.putParam(CHAIN_CONTEXT_STRING, "this is a chainContextValue");
        // 拼装处理链条
        Chain chain = null;
        (chain = Chain.newChain(new PrintDataIn())).link(new GenerateDataOut()).link(new PrintChainContext());
        chain.doChainAction(dataIn, dataOut, chainContext, chain);
        // 获取处理结果dataOut
        System.out.println(String.format("chain action finish dataOut:%s", dataOut));
    }
}

缺点:

  1. 链条节点中参数的传递通过key-value形式,虽然比较灵活,但是当参数比较多时,会比较难维护
  2. 链条的处理是单向的,在处理过程中不可任意跳转

推荐:

  1. 将节点中用到的service(例如数据库操作)作为context中的参数传递进去
  2. 链条的生成使用工厂模式进行统一的管理
  3. 每个节点通过常量标记所使用到的dataIn,dataOut,chainContext参数的key
作为资深Java架构师,请设计一套自动处理微信投诉系统,满足以下详细需求,采用Spring Boot + MyBatis + Java 8技术栈,遵循异步流水线函数编程风格,实现可插拔架构。 ## 一、系统核心组件设计 1. 接入层: - 设计投诉通知回调接口,实现微信回调请求的接收、解密与验签 - 实现action_type事件分发机制,根据不同事件类型路由到相应处理器 2. 业务逻辑层: - 投诉处理流程编排组件,支持可配置的处理步骤 - 事件处理器接口及各action_type对应的实现类 - 微信API调用客户端,封装与微信投诉接口的交互 3. 数据访问层: - 投诉单数据访问接口及实现 - 消息记录、处理日志等辅助数据的持久化 4. 基础设施层: - 异步任务执行框架 - 可插拔组件管理机制 - 配置中心集成 ## 二、关键类结构设计 1. 核心接口定义: - `ComplaintEventHandler`:事件处理接口,定义各action_type的处理方法 - `WechatApiClient`:微信API调用接口,定义获取投诉详情、回复投诉等方法 - `ComplaintRepository`:投诉数据访问接口 - `Plugin`:插件接口,定义可插拔组件的生命周期方法 2. 核心实现类: - `WechatCallbackController`:回调接口实现类 - `DefaultComplaintEventHandler`:默认事件处理器 - `WechatApiClientImpl`:微信API调用客户端实现 - `ComplaintPipeline`:投诉处理流水线 - `AsyncTaskExecutor`:异步任务执行器 ## 三、事件处理流程设计 针对不同action_type设计处理流程,以CREATE_COMPLAINT为例: 1. 接收回调事件,解密验签 2. 异步调用微信接口获取投诉详情 3. 将投诉信息入库(新增或更新) 4. 根据投诉内容判断是否需要自动回复 5. 如需自动回复,调用回复接口 6. 判断是否需要退还押金,如需则调用押金退款接口 7. 再次回复用户处理结果 8. 标记投诉处理完成 ## 四、事务管理策略 1. 采用最终一致性事务模型 2. 关键操作(如退款、状态更新)实现幂等处理 3. 使用本地消息表记录待处理任务 4. 实现任务重试机制,处理临时失败情况 5. 关键业务流程增加事务补偿机制 ## 五、异步处理机制 1. 基于Spring的@Async注解实现方法级异步 2. 使用CompletableFuture实现函数异步编程 3. 设计异步任务队列,支持任务优先级 4. 实现异步任务监控与管理 ## 六、可插拔设计方案 1. 基于SPI机制实现插件加载 2. 设计事件总线,支持插件订阅和发布事件 3. 实现配置驱动的插件启用/禁用 4. 提供插件扩展点,支持业务逻辑定制 ## 七、关键技术实现细节 1. 微信接口调用的签名生成与验证 2. 敏感数据加密存储方案 3. 分布实现,防止并发处理冲突 4. 系统监控与告警机制设计 5. 异常处理与日志记录策略 请提供上述架构设计的详细实现方案,包括核心类代码片段、关键配置及组件交互时序图。
最新发布
11-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值