如何使用责任链设计模式 + 事务 + 回滚 + 异步 + 监控 + 可中断等实现业务流程动态编排
适用场景:
- 电商订单流程(校验→锁库存→扣减→支付→物流)
- 审批流程(申请人→部门经理→HR→财务)
- 风控/审核流程
- 可动态调整步骤顺序、增删节点
一、核心思想
- 每个业务步骤 = 一个独立处理器(Handler)
- 处理器之间形成链式调用
- 流程顺序不写死在代码,可配置(数据库/JSON/YAML)
- 支持中断、跳过、异常回滚
- 可热插拔:新增步骤只需新增类,无需修改主流程
示例整体结构
- FlowContext ------ 流程上下文(携带数据、状态、标记)
- FlowHandler ------ 标准处理器接口(handle + rollback + getName)
- AbstractFlowHandler ------ 抽象链(自动管理 next、统一异常、统一监控)
- FlowEngine ------ 流程引擎(动态构建责任链)
- 业务处理器 ------ 校验/锁库存/支付/发货(可插拔)
- 事务 + 回滚 ------ 某一步失败,前面步骤自动回滚
- 异步 + 监控 ------ 计时、日志、告警
1. 流程上下文(贯穿全链)
java
@Data
public class FlowContext {
// 业务标识
private String orderId;
private Long userId;
// 流程控制
private boolean breakFlow = false;
private String errorMsg;
// 事务/回滚使用:记录已执行节点
private List<String> executedHandlers = new ArrayList<>();
// 扩展数据
private Map<String, Object> data = new HashMap<>();
}
2. 标准处理器接口(含回滚)
java
public interface FlowHandler {
/**
* 执行节点
*/
void handle(FlowContext context);
/**
* 回滚节点(事务失败时)
*/
void rollback(FlowContext context);
/**
* 节点唯一名称
*/
String getName();
}
3. 抽象链实现(核心:异常、监控、next、中断)
java
public abstract class AbstractFlowHandler implements FlowHandler {
protected FlowHandler next;
public void setNext(FlowHandler next) {
this.next = next;
}
@Override
public final void handle(FlowContext context) {
if (context.isBreakFlow()) {
fireNext(context);
return;
}
String handlerName = getName();
Stopwatch stopwatch = Stopwatch.createStarted();
try {
// 执行业务逻辑
doHandle(context);
// 记录已执行,用于回滚
context.getExecutedHandlers().add(handlerName);
} catch (Exception e) {
log.error("节点[{}]执行异常: {}", handlerName, e.getMessage());
context.setBreakFlow(true);
context.setErrorMsg(e.getMessage());
} finally {
log.info("节点[{}] 耗时: {}ms", handlerName, stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
// 执行下一个
fireNext(context);
}
/**
* 子类实现真正业务
*/
protected abstract void doHandle(FlowContext context);
/**
* 驱动下一个节点
*/
protected void fireNext(FlowContext context) {
if (next != null && !context.isBreakFlow()) {
next.handle(context);
}
}
}
4. 业务节点示例(3 个可插拔节点)
4.1 订单校验
java
@Component
public class OrderCheckHandler extends AbstractFlowHandler {
@Override
public String getName() {
return "orderCheck";
}
@Override
protected void doHandle(FlowContext context) {
log.info("执行订单校验 orderId: {}", context.getOrderId());
// 模拟失败
// if (true) throw new RuntimeException("订单参数非法");
}
@Override
public void rollback(FlowContext context) {
log.info("回滚订单校验 orderId: {}", context.getOrderId());
}
}
4.2 锁定库存
java
@Component
public class StockLockHandler extends AbstractFlowHandler {
@Override
public String getName() {
return "stockLock";
}
@Override
protected void doHandle(FlowContext context) {
log.info("执行锁定库存 orderId: {}", context.getOrderId());
}
@Override
public void rollback(FlowContext context) {
log.info("解锁库存 orderId: {}", context.getOrderId());
}
}
4.3 支付扣款
java
@Component
public class PayHandler extends AbstractFlowHandler {
@Override
public String getName() {
return "pay";
}
@Override
protected void doHandle(FlowContext context) {
log.info("执行支付扣款 orderId: {}", context.getOrderId());
}
@Override
public void rollback(FlowContext context) {
log.info("支付退款 orderId: {}", context.getOrderId());
}
}
5. 流程引擎(动态编排核心)
java
@Component
public class FlowEngine {
@Autowired
private Map<String, FlowHandler> handlerMap;
/**
* 根据步骤列表构建责任链
*/
public FlowHandler buildChain(List<String> handlerNames) {
AbstractFlowHandler head = null;
AbstractFlowHandler prev = null;
for (String name : handlerNames) {
FlowHandler handler = handlerMap.get(name);
if (handler == null) {
throw new RuntimeException("节点不存在: " + name);
}
AbstractFlowHandler current = (AbstractFlowHandler) handler;
if (head == null) {
head = current;
} else {
prev.setNext(current);
}
prev = current;
}
return head;
}
/**
* 统一回滚已执行节点
*/
public void rollback(FlowContext context) {
List<String> executed = context.getExecutedHandlers();
Collections.reverse(executed);
for (String name : executed) {
FlowHandler handler = handlerMap.get(name);
if (handler != null) {
try {
handler.rollback(context);
} catch (Exception e) {
log.error("回滚节点[{}]异常", name, e);
}
}
}
}
}
6. 统一执行入口(带事务 + 异步 + 回滚)
java
@Service
public class FlowService {
@Autowired
private FlowEngine flowEngine;
@Autowired
private ThreadPoolTaskExecutor asyncExecutor;
/**
* 同步执行流程
*/
@Transactional(rollbackFor = Exception.class)
public void executeFlow(List<String> handlerNames, FlowContext context) {
FlowHandler chain = flowEngine.buildChain(handlerNames);
chain.handle(context);
// 失败自动回滚
if (context.isBreakFlow()) {
flowEngine.rollback(context);
throw new RuntimeException(context.getErrorMsg());
}
}
/**
* 异步执行(生产推荐)
*/
public CompletableFuture<Void> executeAsync(List<String> handlerNames, FlowContext context) {
return CompletableFuture.runAsync(() -> {
executeFlow(handlerNames, context);
}, asyncExecutor);
}
}
7. 控制器测试(动态编排任意流程)
java
@RestController
@RequestMapping("/flow")
public class FlowController {
@Autowired
private FlowService flowService;
@GetMapping("/start")
public String start() {
// 1. 构建上下文
FlowContext context = new FlowContext();
context.setOrderId("ORDER_" + System.currentTimeMillis());
context.setUserId(1001L);
// 2. 动态编排流程(可来自数据库)
List<String> flow = Arrays.asList(
"orderCheck",
"stockLock",
"pay"
);
// 3. 执行
flowService.executeFlow(flow, context);
return "执行完成";
}
}
8. 总结
✅ 动态编排 :步骤顺序由配置/数据库决定,不写死
✅ 可插拔 :新增节点只加类,不改主流程
✅ 自动回滚 :任意节点失败,前面节点自动反向回滚
✅ 统一异常 :不抛裸异常,流程安全中断
✅ 统一监控 :每个节点自动计时、日志埋点
✅ 异步支持 :高并发不阻塞,不占用请求线程
✅ 事务保证 :Spring 事务控制,数据一致
✅ 可中断、可跳过、可重试