workflow-engine
SKILL.md
工作流引擎开发指南
通用模板。如果项目有专属技能,优先使用。
设计原则
- 流程与业务分离:流程引擎负责流转控制,业务逻辑通过事件监听器/回调接入。
- 状态可追溯:每次流转记录操作人、操作时间、操作意见,形成完整审批链。
- 灵活可配:流程定义应支持可视化设计、动态修改,无需改代码。
- 异常可恢复:流程实例支持挂起、恢复、终止、撤销等操作。
流程引擎选型对比
| 维度 | Flowable | Camunda | Activiti | 轻量方案(WarmFlow 等) |
|---|---|---|---|---|
| 成熟度 | 高 | 高 | 高(社区版停滞) | 中 |
| 学习曲线 | 中等 | 中等 | 中等 | 低 |
| BPMN 2.0 | 完整支持 | 完整支持 | 完整支持 | 部分支持 |
| DMN 决策表 | 支持 | 支持 | 有限 | 不支持 |
| CMMN 案例 | 支持 | 支持 | 不支持 | 不支持 |
| 流程设计器 | 内置 Web | 内置 Web + Desktop | 旧版 Eclipse | 简易 Web |
| 性能 | 优秀 | 优秀 | 良好 | 轻量高效 |
| Spring Boot | 原生支持 | 原生支持 | 原生支持 | 通常支持 |
| 商业版 | 有 | 有 | N/A | 通常免费 |
| 适用场景 | 企业级复杂流程 | 企业级复杂流程 | 已有项目维护 | 简单审批流 |
选型决策树
流程复杂度?
├── 简单审批(3-5步线性流程)
│ └── 状态机模式 或 轻量流程引擎
├── 中等(分支、并行、会签)
│ └── Flowable / Camunda
└── 复杂(子流程、多实例、DMN、事件)
└── Flowable / Camunda
实现模式
模式一:状态机(简单场景)
适用于线性或简单分支的审批流程。
// 状态枚举
public enum OrderStatus {
DRAFT, // 草稿
PENDING, // 待审批
APPROVED, // 已通过
REJECTED, // 已驳回
CANCELLED; // 已撤销
}
// 状态流转规则
public class OrderStateMachine {
private static final Map<OrderStatus, Set<OrderStatus>> TRANSITIONS = Map.of(
OrderStatus.DRAFT, Set.of(OrderStatus.PENDING, OrderStatus.CANCELLED),
OrderStatus.PENDING, Set.of(OrderStatus.APPROVED, OrderStatus.REJECTED),
OrderStatus.REJECTED, Set.of(OrderStatus.PENDING, OrderStatus.CANCELLED)
);
public void transition(Order order, OrderStatus targetStatus, String operator, String comment) {
OrderStatus current = order.getStatus();
if (!TRANSITIONS.getOrDefault(current, Set.of()).contains(targetStatus)) {
throw new [你的异常类](
String.format("不允许从 %s 流转到 %s", current, targetStatus));
}
order.setStatus(targetStatus);
// 记录流转日志
saveFlowLog(order.getId(), current, targetStatus, operator, comment);
}
}
模式二:流程引擎集成
核心概念
| 概念 | 说明 |
|---|---|
| 流程定义(Definition) | 流程模板(BPMN XML),可版本化管理 |
| 流程实例(Instance) | 基于定义创建的运行时实例 |
| 任务(Task) | 等待人工处理的节点 |
| 历史(History) | 已完成的流程/任务记录 |
| 变量(Variable) | 流程运行时数据,用于条件判断 |
启动流程
@Service
public class WorkflowService {
@Autowired
private [你的流程引擎] engine;
// 启动流程
public String startProcess(String processKey, String businessId, Map<String, Object> variables) {
variables.put("businessId", businessId);
variables.put("initiator", [你的安全工具类].getCurrentUserId());
// 启动流程实例
var instance = engine.startProcessByKey(processKey, businessId, variables);
return instance.getId();
}
// 办理任务(审批通过)
public void completeTask(String taskId, String comment, Map<String, Object> variables) {
// 记录审批意见
engine.addComment(taskId, comment);
// 完成任务
engine.completeTask(taskId, variables);
}
// 驳回
public void rejectTask(String taskId, String targetNodeId, String comment) {
engine.addComment(taskId, comment);
engine.rejectToNode(taskId, targetNodeId);
}
// 转办
public void transferTask(String taskId, String targetUserId, String comment) {
engine.addComment(taskId, comment);
engine.setAssignee(taskId, targetUserId);
}
// 撤销
public void cancelProcess(String instanceId, String comment) {
engine.deleteProcessInstance(instanceId, comment);
}
}
业务集成 - 事件监听
@Component
public class OrderWorkflowListener {
@Autowired
private OrderService orderService;
// 监听流程状态变更事件
@EventListener(condition = "#event.processKey == 'order_approve'")
public void onProcessEvent(ProcessStatusEvent event) {
String businessId = event.getBusinessId();
switch (event.getStatus()) {
case "submitted" -> orderService.updateStatus(businessId, "PENDING");
case "approved" -> orderService.updateStatus(businessId, "APPROVED");
case "rejected" -> orderService.updateStatus(businessId, "REJECTED");
case "cancelled" -> orderService.updateStatus(businessId, "CANCELLED");
}
}
// 监听任务创建事件(发送通知)
@EventListener(condition = "#event.processKey == 'order_approve'")
public void onTaskCreated(TaskCreatedEvent event) {
notificationService.sendNotice(
event.getAssignee(),
"您有新的审批任务:" + event.getTaskName()
);
}
}
办理人类型设计
| 类型 | 标识格式 | 示例 |
|---|---|---|
| 指定用户 | 用户ID | 1001 |
| 角色 | role:角色编码 |
role:finance_manager |
| 部门 | dept:部门ID |
dept:100 |
| 岗位 | post:岗位编码 |
post:cfo |
| 表达式 | SpEL / UEL | ${order.amount > 10000 ? 'role:director' : 'role:manager'} |
API 接口设计参考
任务相关
| 接口 | 方法 | 说明 |
|---|---|---|
/workflow/start |
POST | 启动流程 |
/workflow/task/complete |
POST | 办理任务(审批通过) |
/workflow/task/reject |
POST | 驳回 |
/workflow/task/transfer |
POST | 转办 |
/workflow/task/delegate |
POST | 委派 |
/workflow/task/todo |
GET | 当前用户待办列表 |
/workflow/task/done |
GET | 当前用户已办列表 |
/workflow/task/copy |
GET | 抄送列表 |
实例相关
| 接口 | 方法 | 说明 |
|---|---|---|
/workflow/instance/running |
GET | 运行中实例 |
/workflow/instance/finished |
GET | 已完成实例 |
/workflow/instance/cancel |
PUT | 撤销申请 |
/workflow/instance/history/{businessId} |
GET | 审批记录 |
常见错误
// 1. 流程与业务强耦合
// 在流程引擎的 ServiceTask 中直接操作数据库
// 应通过事件监听/消息解耦
// 2. 未处理并发审批
// 多人同时审批同一任务 -> 数据不一致
// 应在 completeTask 中加锁或使用乐观锁
// 3. 流程变量存放大对象
variables.put("orderDetail", hugeObject); // 序列化到数据库,性能差
// 应只存关键ID,通过 businessId 关联查询
// 4. 忽略流程版本管理
// 修改流程定义后,已运行的实例可能出错
// 应使用版本化部署,运行中实例按启动时版本执行
// 5. 审批意见未持久化
engine.completeTask(taskId, variables); // 忘记 addComment
// 应在 complete 前记录审批意见
// 6. 通知不及时
// 任务创建后没有通知办理人 -> 任务积压
// 应通过事件监听器自动发送通知
Weekly Installs
3
Repository
xu-cell/ai-engi…ing-initGitHub Stars
8
First Seen
7 days ago
Security Audits
Installed on
gemini-cli3
github-copilot3
codex3
kimi-cli3
cursor3
amp3