一、流程模型的核心概念
一个工作流由「流程定义」和「流程实例」组成。定义是模板,实例是某次具体执行。
| 概念 | 说明 |
|---|---|
| 流程定义(Process) | 包含节点、连线、条件规则的静态模板 |
| 流程实例(Instance) | 基于定义创建的某次运行,含当前状态 |
| 节点(Node) | 流程中的步骤,如审批、抄送、条件判断 |
| 流转(Transition) | 节点之间的有向连接,可附带条件表达式 |
| 任务(Task) | 分配给具体用户或角色的待办事项 |
二、数据库表结构设计
采用「定义-实例-任务」三层模型,支持版本管理与流程历史追溯。
workflow_schema.sql
/* 流程定义 */ CREATE TABLE wf_process ( id BIGINT PRIMARY KEY, key VARCHAR(64) NOT NULL, /* 业务标识,如 "leave_approval" */ name VARCHAR(128), version INT DEFAULT 1, definition JSON NOT NULL, /* 节点与连线的 JSON 描述 */ is_active BOOLEAN DEFAULT TRUE, created_at DATETIME ); /* 流程实例 */ CREATE TABLE wf_instance ( id BIGINT PRIMARY KEY, process_id BIGINT NOT NULL, business_key VARCHAR(64), /* 关联业务表主键 */ status VARCHAR(20), /* RUNNING / COMPLETED / REJECTED */ current_node VARCHAR(64), /* 当前节点 ID */ variables JSON, /* 流程变量,如 {"amount": 5000} */ started_at DATETIME, ended_at DATETIME ); /* 审批任务 */ CREATE TABLE wf_task ( id BIGINT PRIMARY KEY, instance_id BIGINT NOT NULL, node_id VARCHAR(64) NOT NULL, assignee BIGINT, /* 具体处理人 */ candidate_role BIGINT, /* 候选角色(会签/或签) */ action VARCHAR(20), /* APPROVE / REJECT / TRANSFER */ comment TEXT, created_at DATETIME, completed_at DATETIME );
三、节点类型与状态机驱动
每种节点类型对应一个处理器,核心逻辑是「接收事件 → 更新状态 → 计算下一个节点」。
workflow_engine.java(伪代码)
public interface NodeHandler { List<String> execute(WfInstance instance, WfNode node, ActionRequest req); } /* 审批节点:根据或签/会签策略决定流转 */ public class ApproveHandler implements NodeHandler { public List<String> execute(WfInstance inst, WfNode node, ActionRequest req) { if (node.getStrategy() == Strategy.ANY) { /* 或签:一人通过即过 */ return List.of(node.getNextNodeId(req.getAction())); } else if (node.getStrategy() == Strategy.ALL) { /* 会签:全部通过才过 */ int total = taskService.countPending(inst.getId(), node.getId()); if (total == 1) { /* 最后一个审批人 */ return List.of(node.getNextNodeId("APPROVE")); } return List.of(); /* 继续等待其他人 */ } /* 依次审批:按预设顺序触发下一个处理人 */ String nextAssignee = node.getNextAssignee(inst); taskService.createTask(inst.getId(), node.getId(), nextAssignee); return List.of(); } }
四、条件分支与表达式引擎
流程连线可附带条件,如「金额 > 5000 走经理审批,否则走自动审批」。使用轻量级表达式引擎(如 Aviator、QLExpress 或自研)解析。
condition.json(流程定义片段)
{
"transitions": [
{
"from": "submit",
"to": "manager_approve",
"condition": "${amount > 5000 || days > 3}"
},
{
"from": "submit",
"to": "auto_approve",
"condition": "${amount <= 5000 && days <= 3}"
}
]
}
安全提示: 表达式引擎必须做沙箱隔离,禁止调用 System.exit、文件 IO 等危险操作。建议白名单化可用函数与变量。
五、自动化动作:审批后的连锁反应
流程节点可配置「通过后自动执行」的动作,如发送通知、更新业务状态、调用外部 API。
auto_action.java(伪代码)
public interface AutoAction { void run(WfInstance instance, Map<String, Object> params); } /* 实现示例 */ public class SendNotificationAction implements AutoAction { public void run(WfInstance inst, Map<String, Object> p) { String tmpl = (String) p.get("template"); Long userId = (Long) p.get("toUser"); notifyService.send(userId, render(tmpl, inst.getVariables())); } }
六、版本管理与流程迁移
已发布的流程定义不应直接修改,而是创建新版本。运行中的实例继续使用旧版本,新实例使用最新版本。这样可避免正在审批的流程因规则变更而异常中断。
七、总结
工作流引擎的设计要点:状态机驱动保证流转确定性,节点策略支持或签/会签/依次审批,条件表达式实现灵活分支,自动化动作打通业务系统,版本管理保障运行稳定性。这些机制组合在一起,才能支撑企业复杂的业务流程需求。