工作流
工作流用于把业务流程显式建模,例如请假审批、报销审批、合同审批、订单流转。相比把流程写死在代码里,工作流引擎可以更清晰地表达节点、审批人、条件分支和流程状态。
为什么需要工作流
如果所有流程都写在 Java if/else 里,刚开始会很快,但流程一变复杂就会出现维护问题:审批节点散落在代码里,谁审批过不清楚,流程改动需要发版,历史轨迹需要自己补表,测试也很难覆盖所有分支。
工作流解决的是“流程可建模、可运行、可追踪、可调整”的问题。
| 没有工作流时 | 使用工作流后 |
|---|---|
| 流程藏在业务代码里 | 流程定义用 BPMN 显式表达 |
| 审批记录要自己设计 | 引擎保存任务、实例和历史 |
| 改节点要改代码发版 | 流程定义可以独立版本化 |
| 分支条件难以可视化 | 网关条件和流向在图中可见 |
| 待办、已办、催办都要自己造 | 引擎提供任务 API 和查询能力 |
工作流不是为了替代业务系统。业务数据仍然应该保存在业务表中,工作流引擎负责“谁下一步处理、流程走到哪里、历史轨迹是什么”。
本目录内容
- Activiti从零学习路线与工作原理总览
- Activiti 从零到生产级掌握
- BPMN流程设计与可执行建模
- 任务生命周期、待办已办与并发审批
- 网关、Execution与分支汇聚
- 业务表、流程表与分布式一致性
- 部署、版本、缓存与生产发布
- Activiti商业场景训练营
- Activiti 从零到精通验收清单
- Activiti 面试题
基本概念
| 概念 | 说明 |
|---|---|
| 流程定义 | 设计好的流程模板 |
| 流程实例 | 一次真实运行的流程 |
| 任务 | 等待某个人或系统处理的节点 |
| 网关 | 条件分支、并行分支 |
| 流程变量 | 流程运行中的数据 |
核心原理
mermaid
flowchart TD
A["流程定义<br/>BPMN 模板"] --> B["部署到工作流引擎"]
B --> C["发起流程实例"]
C --> D["生成当前任务"]
D --> E["用户处理任务"]
E --> F["引擎根据变量和网关计算下一步"]
F --> G{"流程是否结束"}
G -- "否" --> D
G -- "是" --> H["写入历史轨迹"]理解工作流时一定要分清“定义”和“实例”:流程定义是模板,流程实例是某一次真实业务流转。就像 Java 类和对象的关系,类定义结构,对象承载一次具体数据。
审批流程示例
mermaid
flowchart TD
A[提交请假申请] --> B[直属领导审批]
B --> C{是否超过 3 天?}
C -->|否| D[审批通过]
C -->|是| E[部门负责人审批]
E --> F{是否同意?}
F -->|同意| D
F -->|拒绝| G[流程结束: 驳回]什么时候适合使用工作流
- 流程节点多,且经常调整。
- 审批人、条件、分支比较复杂。
- 需要记录完整流程轨迹。
- 需要可视化流程图。
- 需要催办、转办、撤回、驳回等能力。
如果流程非常简单,例如只有一个状态字段从 0 改为 1,直接使用状态机可能更轻量。
代码 Demo:不用工作流时的状态机
简单流程可以先用状态机表达,避免过早引入工作流引擎。
java
public enum LeaveStatus {
DRAFT,
WAIT_LEADER_APPROVE,
WAIT_MANAGER_APPROVE,
APPROVED,
REJECTED
}java
@Service
public class LeaveService {
@Transactional
public void approve(Long leaveId, Long approverId) {
LeaveApply apply = leaveRepository.findById(leaveId)
.orElseThrow(() -> new BizException("申请不存在"));
if (apply.getStatus() == LeaveStatus.WAIT_LEADER_APPROVE && apply.getDays() <= 3) {
apply.setStatus(LeaveStatus.APPROVED);
return;
}
if (apply.getStatus() == LeaveStatus.WAIT_LEADER_APPROVE && apply.getDays() > 3) {
apply.setStatus(LeaveStatus.WAIT_MANAGER_APPROVE);
return;
}
if (apply.getStatus() == LeaveStatus.WAIT_MANAGER_APPROVE) {
apply.setStatus(LeaveStatus.APPROVED);
return;
}
throw new BizException("当前状态不能审批");
}
}当审批节点、审批人、条件分支经常变化时,再考虑 Activiti、Flowable 这类工作流引擎。
