BPM引擎系列(一) BPMN是个啥-工作流引擎的通用语言
BPMN是个啥?——工作流引擎的"通用语言"
系列第一篇:在折腾Activiti、Flowable、Camunda之前,咱们先把BPMN这门"通用语言"学明白。
一、从一个让人崩溃的需求说起
最近接手了一个新项目,产品经理丢过来一张"流程图":
[提交申请] → [经理审批] → [通过?] → [是] → [结束] ↓ [否] ↓ [驳回]我看完有点懵:“这是用Word画的?箭头怎么连的?'通过?'这个判断条件写在哪?驳回之后还能重新提交吗?”
产品经理一脸无辜:“就是个简单的审批流啊,你们开发不是有工作流引擎吗,配一下不就行了?”
问题就在这了。
没有统一的标准,每个人画的流程图都不一样,开发拿到手根本不知道怎么"翻译"成代码。你画你的,我理解我的,最后做出来的东西和需求对不上,互相甩锅。
这时候就需要一个大家都能看懂的"通用语言"——BPMN。
二、BPMN到底是啥?
BPMN,全称Business Process Model and Notation(业务流程模型和标记法)。
说白了,它就是一套画流程图的国际标准。就像五线谱是音乐界的通用语言,BPMN就是工作流界的通用语言。
它的核心作用就两个:
- 业务人员能看懂——产品经理、业务分析师用它画流程,不用写代码
- 技术人员能执行——开发可以直接把BPMN图丢给工作流引擎跑起来
一张BPMN图,业务看了说"对,就是这么个流程",引擎看了说"好,我知道怎么执行"。两边不打架,完美。
三、BPMN的"三大件"
BPMN 2.0规范里元素不少,但日常工作中常用的就三大类,记住它们,看懂80%的流程图没问题。
1. 事件(Event)——圆圈
事件就是"发生了某件事"。圆圈里的图标不同,代表的事件类型不同。
| 图标 | 名称 | 含义 |
|---|---|---|
| ○(细线) | 开始事件 | 流程从这里启动 |
| ○(粗线) | 结束事件 | 流程到这里结束 |
| ○(带时钟) | 定时事件 | 到了某个时间点触发 |
| ○(带信封) | 消息事件 | 收到某个消息触发 |
○ ◎ 开始事件 结束事件 (细圈) (粗圈)举个栗子:请假流程,"员工提交申请"就是开始事件,"流程结束"就是结束事件。
2. 活动(Activity)——圆角矩形
活动就是"要干点啥"。最常见的有两种:
| 图标 | 名称 | 含义 |
|---|---|---|
| ▭(圆角) | 用户任务 | 需要人手动处理的任务 |
| ▭(圆角+齿轮) | 服务任务 | 系统自动执行的任务 |
┌─────────────┐ ┌─────────────┐ │ 经理审批 │ │ 发送邮件 │ │ (用户任务) │ │ (服务任务) │ └─────────────┘ └─────────────┘用户任务:需要人登录系统点"同意"或"驳回",引擎会把这个任务推到待办列表里。
服务任务:系统自动干,比如"发送通知邮件"、“调用外部API扣库存”,不需要人干预。
3. 网关(Gateway)——菱形
网关就是"走到这,要判断一下怎么走"。
| 图标 | 名称 | 含义 |
|---|---|---|
| ◇(空心) | 排他网关 | 多选一,走其中一条 |
| ◇(加号) | 并行网关 | 多条路同时走 |
| ◇(叉号) | 包容网关 | 满足条件的都走 |
◇ 排他网关 / \ 通过 驳回 / \排他网关(XOR):最常用的,“如果金额>1000需要总监审批,否则经理审批就行”。
并行网关(AND):“请假需要经理审批同时HR备案,两个都完成才能结束”。
四、画一个完整的BPMN流程
光说元素有点抽象,咱们来画一个完整的请假流程,这也是后面几篇代码示例要用的流程。
场景
小明要请假,流程如下:
- 小明提交请假申请
- 直属经理审批
- 如果经理驳回,流程结束(小明可以重新发起)
- 如果经理同意,继续
- 如果请假天数 > 3天,需要总监审批
- 总监驳回,流程结束
- 总监同意,继续
- HR备案(系统自动记录)
- 发送通知邮件给小明
- 流程结束
BPMN图
┌─────────────┐ ┌─────────→│ 经理驳回 │ │ │ (结束事件) │ │ └─────────────┘ │ ○ ↓ ┌─────────────┐ ◇ ┌─────────────┐ 开始 ───→ │ 经理审批 │──→ 通过? │ │ 事件 │ (用户任务) │ 排他网关 │ │ └─────────────┘ │ 驳回 │ │ └──┬─────┘ │ │ 通过 │ ↓ │ ┌─────────────┐ │ │ 天数>3? │ │ │ 排他网关 │ │ └──────┬──────┘ │ 是 / \ 否 │ / \ │ ↓ ↓ │ ┌────────┐ ┌────────┐ │ │总监审批│ │ │ │ │用户任务│ │ │ │ └───┬────┘ │ │ │ 通过│驳回 │ │ │ ↓ ↓ │ │ │ ┌────┐ ┌────┐ │ │ │继续│ │结束│ │ │ └──┬─┘ └────┘ │ │ │ │ │ └────────┬────────┘ │ ↓ │ ┌─────────────┐ │ │ HR备案 │ │ │ (服务任务) │ │ └──────┬──────┘ │ ↓ │ ┌─────────────┐ │ │ 发送通知邮件│ │ │ (服务任务) │ │ └──────┬──────┘ │ ↓ │ ┌─────────────┐ │ │ 流程结束 │←───────┘ │ (结束事件) │ └─────────────┘对应的BPMN 2.0 XML(核心片段)
<?xml version="1.0" encoding="UTF-8"?><definitionsxmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"id="Definitions_1"targetNamespace="http://example.org/leave-process"><processid="leave-process"name="请假流程"isExecutable="true"><!-- 1. 开始事件 --><startEventid="start"name="提交申请"/><!-- 2. 经理审批(用户任务) --><userTaskid="manager-approval"name="经理审批"assignee="${managerId}"/><!-- 3. 排他网关:经理是否通过 --><exclusiveGatewayid="manager-decision"name="经理审批结果"/><!-- 4. 经理驳回 → 结束 --><endEventid="manager-reject-end"name="经理驳回"/><!-- 5. 排他网关:天数是否大于3天 --><exclusiveGatewayid="days-check"name="天数>3?"/><!-- 6. 总监审批(用户任务) --><userTaskid="director-approval"name="总监审批"assignee="${directorId}"/><!-- 7. 总监驳回 → 结束 --><endEventid="director-reject-end"name="总监驳回"/><!-- 8. HR备案(服务任务) --><serviceTaskid="hr-record"name="HR备案"camunda:class="com.example.HrRecordDelegate"/><!-- 9. 发送邮件(服务任务) --><serviceTaskid="send-email"name="发送通知邮件"camunda:class="com.example.SendEmailDelegate"/><!-- 10. 结束事件 --><endEventid="end"name="流程结束"/><!-- ========== 连线(Sequence Flow)========== --><!-- 开始 → 经理审批 --><sequenceFlowid="flow1"sourceRef="start"targetRef="manager-approval"/><!-- 经理审批 → 决策网关 --><sequenceFlowid="flow2"sourceRef="manager-approval"targetRef="manager-decision"/><!-- 决策网关 → 驳回(条件:approved == false) --><sequenceFlowid="flow3-reject"sourceRef="manager-decision"targetRef="manager-reject-end"name="驳回"><conditionExpressionxsi:type="tFormalExpression">${approved == false}</conditionExpression></sequenceFlow><!-- 决策网关 → 天数检查(条件:approved == true) --><sequenceFlowid="flow3-pass"sourceRef="manager-decision"targetRef="days-check"name="通过"><conditionExpressionxsi:type="tFormalExpression">${approved == true}</conditionExpression></sequenceFlow><!-- 天数检查 → 总监审批(条件:days > 3) --><sequenceFlowid="flow4-director"sourceRef="days-check"targetRef="director-approval"name="是"><conditionExpressionxsi:type="tFormalExpression">${days > 3}</conditionExpression></sequenceFlow><!-- 天数检查 → 跳过总监(条件:days <= 3) --><sequenceFlowid="flow4-skip"sourceRef="days-check"targetRef="hr-record"name="否"><conditionExpressionxsi:type="tFormalExpression">${days <= 3}</conditionExpression></sequenceFlow><!-- 总监审批 → 决策(通过/驳回由任务完成时的变量决定) --><sequenceFlowid="flow5"sourceRef="director-approval"targetRef="hr-record"/><!-- HR备案 → 发送邮件 --><sequenceFlowid="flow6"sourceRef="hr-record"targetRef="send-email"/><!-- 发送邮件 → 结束 --><sequenceFlowid="flow7"sourceRef="send-email"targetRef="end"/></process></definitions>关键点说明:
isExecutable="true":告诉引擎这个流程是可以执行的,不是只画来看的<conditionExpression>:网关走哪条线的判断条件,用${}写表达式assignee="${managerId}":任务分配给哪个用户,启动流程时传入变量
五、BPMN图 vs 普通流程图
有人可能会问:“我用Visio画流程图不也挺好的吗,为啥非要学BPMN?”
| 对比项 | 普通流程图 | BPMN图 |
|---|---|---|
| 标准化 | 各画各的,没有统一规范 | OMG国际标准,全球通用 |
| 可执行性 | 只能看,不能跑 | 可以直接被引擎解析执行 |
| 元素语义 | 随意发挥,理解靠猜 | 每个元素都有明确定义 |
| 工具生态 | 画图工具各自为政 | Modeler、引擎、监控一套打通 |
说白了:普通流程图是"给人看的",BPMN图是"既能给人看,又能给机器执行"。
六、常用元素速查表
最后送大家一张速查表,建议收藏:
| 分类 | 图形 | 元素 | 用途 |
|---|---|---|---|
| 事件 | ○细圈 | 开始事件 | 流程起点 |
| 事件 | ◎粗圈 | 结束事件 | 流程终点 |
| 事件 | ○+时钟 | 定时事件 | 定时触发 |
| 活动 | ▭圆角 | 用户任务 | 人工审批/处理 |
| 活动 | ▭圆角+齿轮 | 服务任务 | 系统自动执行 |
| 活动 | ▭圆角+加号 | 子流程 | 嵌套另一个流程 |
| 网关 | ◇空心 | 排他网关 | 多选一 |
| 网关 | ◇+加号 | 并行网关 | 多路同时执行 |
| 网关 | ◇+叉号 | 包容网关 | 满足条件的都执行 |
| 数据 | 📄 | 数据对象 | 流程中的文档/数据 |
| 泳道 | 横条/竖条 | 泳道 | 按角色/部门划分职责 |
七、小结
这篇咱们聊了:
- 为什么需要BPMN——没有标准,业务和技术各说各话
- BPMN三大件——事件(圆圈)、活动(圆角矩形)、网关(菱形)
- 画了一个完整的请假流程——从BPMN图到XML,一一对应
- BPMN vs 普通流程图——能执行是最大区别
下一篇预告:有了BPMN基础,咱们开始折腾第一个引擎——Activiti。这个老牌引擎现在还能打吗?Spring Boot怎么集成?代码怎么写?
参考资料
- BPMN 2.0 Specification
- Activiti 官方文档
- Flowable 官方文档
- Camunda BPMN 教程
你在项目中用过BPMN吗?是用什么工具画图的?欢迎在评论区交流!
