责任链模式实现流程动态编排

张开发
2026/4/19 0:01:05 15 分钟阅读

分享文章

责任链模式实现流程动态编排
如何使用责任链设计模式 事务 回滚 异步 监控 可中断等实现业务流程动态编排适用场景电商订单流程校验→锁库存→扣减→支付→物流审批流程申请人→部门经理→HR→财务风控/审核流程可动态调整步骤顺序、增删节点一、核心思想每个业务步骤 一个独立处理器Handler处理器之间形成链式调用流程顺序不写死在代码可配置数据库/JSON/YAML支持中断、跳过、异常回滚可热插拔新增步骤只需新增类无需修改主流程示例整体结构FlowContext—— 流程上下文携带数据、状态、标记FlowHandler—— 标准处理器接口handle rollback getNameAbstractFlowHandler—— 抽象链自动管理 next、统一异常、统一监控FlowEngine—— 流程引擎动态构建责任链业务处理器—— 校验/锁库存/支付/发货可插拔事务 回滚—— 某一步失败前面步骤自动回滚异步 监控—— 计时、日志、告警1. 流程上下文贯穿全链DatapublicclassFlowContext{// 业务标识privateStringorderId;privateLonguserId;// 流程控制privatebooleanbreakFlowfalse;privateStringerrorMsg;// 事务/回滚使用记录已执行节点privateListStringexecutedHandlersnewArrayList();// 扩展数据privateMapString,ObjectdatanewHashMap();}2. 标准处理器接口含回滚publicinterfaceFlowHandler{/** * 执行节点 */voidhandle(FlowContextcontext);/** * 回滚节点事务失败时 */voidrollback(FlowContextcontext);/** * 节点唯一名称 */StringgetName();}3. 抽象链实现核心异常、监控、next、中断publicabstractclassAbstractFlowHandlerimplementsFlowHandler{protectedFlowHandlernext;publicvoidsetNext(FlowHandlernext){this.nextnext;}Overridepublicfinalvoidhandle(FlowContextcontext){if(context.isBreakFlow()){fireNext(context);return;}StringhandlerNamegetName();StopwatchstopwatchStopwatch.createStarted();try{// 执行业务逻辑doHandle(context);// 记录已执行用于回滚context.getExecutedHandlers().add(handlerName);}catch(Exceptione){log.error(节点[{}]执行异常: {},handlerName,e.getMessage());context.setBreakFlow(true);context.setErrorMsg(e.getMessage());}finally{log.info(节点[{}] 耗时: {}ms,handlerName,stopwatch.elapsed(TimeUnit.MILLISECONDS));}// 执行下一个fireNext(context);}/** * 子类实现真正业务 */protectedabstractvoiddoHandle(FlowContextcontext);/** * 驱动下一个节点 */protectedvoidfireNext(FlowContextcontext){if(next!null!context.isBreakFlow()){next.handle(context);}}}4. 业务节点示例3 个可插拔节点4.1 订单校验ComponentpublicclassOrderCheckHandlerextendsAbstractFlowHandler{OverridepublicStringgetName(){returnorderCheck;}OverrideprotectedvoiddoHandle(FlowContextcontext){log.info(执行订单校验 orderId: {},context.getOrderId());// 模拟失败// if (true) throw new RuntimeException(订单参数非法);}Overridepublicvoidrollback(FlowContextcontext){log.info(回滚订单校验 orderId: {},context.getOrderId());}}4.2 锁定库存ComponentpublicclassStockLockHandlerextendsAbstractFlowHandler{OverridepublicStringgetName(){returnstockLock;}OverrideprotectedvoiddoHandle(FlowContextcontext){log.info(执行锁定库存 orderId: {},context.getOrderId());}Overridepublicvoidrollback(FlowContextcontext){log.info(解锁库存 orderId: {},context.getOrderId());}}4.3 支付扣款ComponentpublicclassPayHandlerextendsAbstractFlowHandler{OverridepublicStringgetName(){returnpay;}OverrideprotectedvoiddoHandle(FlowContextcontext){log.info(执行支付扣款 orderId: {},context.getOrderId());}Overridepublicvoidrollback(FlowContextcontext){log.info(支付退款 orderId: {},context.getOrderId());}}5. 流程引擎动态编排核心ComponentpublicclassFlowEngine{AutowiredprivateMapString,FlowHandlerhandlerMap;/** * 根据步骤列表构建责任链 */publicFlowHandlerbuildChain(ListStringhandlerNames){AbstractFlowHandlerheadnull;AbstractFlowHandlerprevnull;for(Stringname:handlerNames){FlowHandlerhandlerhandlerMap.get(name);if(handlernull){thrownewRuntimeException(节点不存在: name);}AbstractFlowHandlercurrent(AbstractFlowHandler)handler;if(headnull){headcurrent;}else{prev.setNext(current);}prevcurrent;}returnhead;}/** * 统一回滚已执行节点 */publicvoidrollback(FlowContextcontext){ListStringexecutedcontext.getExecutedHandlers();Collections.reverse(executed);for(Stringname:executed){FlowHandlerhandlerhandlerMap.get(name);if(handler!null){try{handler.rollback(context);}catch(Exceptione){log.error(回滚节点[{}]异常,name,e);}}}}}6. 统一执行入口带事务 异步 回滚ServicepublicclassFlowService{AutowiredprivateFlowEngineflowEngine;AutowiredprivateThreadPoolTaskExecutorasyncExecutor;/** * 同步执行流程 */Transactional(rollbackForException.class)publicvoidexecuteFlow(ListStringhandlerNames,FlowContextcontext){FlowHandlerchainflowEngine.buildChain(handlerNames);chain.handle(context);// 失败自动回滚if(context.isBreakFlow()){flowEngine.rollback(context);thrownewRuntimeException(context.getErrorMsg());}}/** * 异步执行生产推荐 */publicCompletableFutureVoidexecuteAsync(ListStringhandlerNames,FlowContextcontext){returnCompletableFuture.runAsync(()-{executeFlow(handlerNames,context);},asyncExecutor);}}7. 控制器测试动态编排任意流程RestControllerRequestMapping(/flow)publicclassFlowController{AutowiredprivateFlowServiceflowService;GetMapping(/start)publicStringstart(){// 1. 构建上下文FlowContextcontextnewFlowContext();context.setOrderId(ORDER_System.currentTimeMillis());context.setUserId(1001L);// 2. 动态编排流程可来自数据库ListStringflowArrays.asList(orderCheck,stockLock,pay);// 3. 执行flowService.executeFlow(flow,context);return执行完成;}}8. 总结✅动态编排步骤顺序由配置/数据库决定不写死✅可插拔新增节点只加类不改主流程✅自动回滚任意节点失败前面节点自动反向回滚✅统一异常不抛裸异常流程安全中断✅统一监控每个节点自动计时、日志埋点✅异步支持高并发不阻塞不占用请求线程✅事务保证Spring 事务控制数据一致✅可中断、可跳过、可重试

更多文章