第1章:流程定义语言:BPMN 2.0 简介
做工作流引擎开发,第一个绕不开的东西就是BPMN。说实话,我刚接触这个概念时也觉得挺唬人的——又是XML又是图形符号的。但用久了你会发现,它其实就是一套约定好的「画图规则」。
BPMN的全称是Business Process Model and Notation,也就是业务流程建模与符号。2.0版本是目前最通用的标准。我最早接触它是在一个OA审批系统的项目里,当时领导扔给我一个流程图,说「照着这个做」。我盯着那些圆圈、方框、菱形看了半天...嗯,后来才知道那就是BPMN。
为什么选BPMN 2.0?
市面上流程定义语言不少,但BPMN 2.0几乎是事实标准。原因很简单:
- 图形化——业务人员看得懂,开发人员也能直接解析
- 标准化——OMG组织维护,各大厂商都支持
- 可执行——定义好的流程可以直接跑起来
我个人习惯是:先用BPMN画图跟业务方确认逻辑,再导出XML做二次开发。这样沟通成本低很多。
BPMN的核心元素
BPMN 2.0的元素其实就三大类:事件、活动、网关。你想想看,任何一个业务流程,无非就是「开始→做事情→判断→结束」这个套路。
1. 事件(Event)
事件用圆圈表示。它代表流程中「发生了一件事」。分为三种:
| 类型 | 图标 | 说明 |
|---|---|---|
| 开始事件 | 单圆圈 | 流程的起点。每个流程至少有一个 |
| 中间事件 | 双圆圈 | 流程执行过程中发生的事,比如超时、消息到达 |
| 结束事件 | 粗边框圆圈 | 流程的终点。可以有多个 |
2. 活动(Activity)
活动用圆角矩形表示。说白了就是「要做的事」。BPMN里分两种:
- 任务(Task)——原子操作,不可再分。比如「填写请假单」
- 子流程(Sub-Process)——可以展开成更细的流程。比如「审批流程」内部可能还有「部门审批→HR审批→总经理审批」
我记得有一次,业务方说「这个审批很简单」,结果画出来子流程嵌套了三层。所以我的建议是:能用任务就别用子流程,除非逻辑真的复杂到必须拆分。
3. 网关(Gateway)
网关用菱形表示。它控制流程的分支和合并。常见的有:
| 类型 | 说明 |
|---|---|
| 排他网关 | 只有一个分支能走。类似if-else |
| 并行网关 | 所有分支同时走。类似多线程 |
| 包容网关 | 满足条件的分支都可以走 |
流程定义文件结构
BPMN 2.0的流程定义文件本质上是XML。我直接给你看一个最简的例子:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
targetNamespace="http://example.com/process">
<process id="leaveProcess" name="请假流程">
<startEvent id="start" />
<userTask id="apply" name="填写请假单" />
<exclusiveGateway id="gateway" />
<userTask id="approve" name="部门审批" />
<endEvent id="end" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="apply" />
<sequenceFlow id="flow2" sourceRef="apply" targetRef="gateway" />
<sequenceFlow id="flow3" sourceRef="gateway" targetRef="approve" />
<sequenceFlow id="flow4" sourceRef="approve" targetRef="end" />
</process>
</definitions>
结构其实很清晰:
- definitions——根节点,声明命名空间
- process——具体的流程定义,id和name是必须的
- sequenceFlow——连线,把各个元素串起来
你想想看,这个XML本质上就是一个有向图。节点是事件、活动、网关,边就是sequenceFlow。解析的时候,从startEvent开始,沿着连线往下走就行了。
自定义流程定义格式
BPMN 2.0虽然强大,但有时候太重了。我在实际项目中遇到过这种情况:业务方只需要简单的审批流,用BPMN反而显得杀鸡用牛刀。
这时候我会选择自定义格式。比如用JSON:
{
"processId": "leaveProcess",
"name": "请假流程",
"nodes": [
{"id": "start", "type": "start", "name": "开始"},
{"id": "apply", "type": "userTask", "name": "填写请假单"},
{"id": "gateway", "type": "exclusiveGateway", "name": "判断"},
{"id": "approve", "type": "userTask", "name": "部门审批"},
{"id": "end", "type": "end", "name": "结束"}
],
"edges": [
{"from": "start", "to": "apply"},
{"from": "apply", "to": "gateway"},
{"from": "gateway", "to": "approve"},
{"from": "approve", "to": "end"}
]
}
嗯,这里要注意一点:自定义格式虽然方便,但失去了BPMN的图形化能力。如果你需要跟业务方沟通流程图,还是得转成BPMN或者自己实现一个画图工具。
好了,这一章就到这里。下一章我们会深入解析BPMN的XML结构,手把手教你解析一个完整的流程定义文件。