Flowable工作流引擎的使用(2BPMN结构介绍)
上一篇讲到了flowable如何使用,用了一个简单的demo,演示了一下流程的创建,发起,审核,查询等功能
内容不多但是引申出很多的概念: BPMN,deployId,processId,taskId,权限,数据库60张表😱等概念.
这一章先讲讲BPMN是个啥,我们怎么写出一个人类高质量的流程配置
BPMN是什么
业务流程模型注解(Business Process Modeling Notation - BPMN)是 业务流程模型的一种标准图形注解。这个标准 是由对象管理组(Object Management Group - OMG)维护的。
基本上,BPMN规范定义了任务看起来怎样的,哪些结构可以 与其他进行连接,等等。这就意味着 意思不会被误解。
标准的早期版本(1.2版以及之前)仅仅限制在模型上, 目标是在所有的利益相关者之间形成通用的理解, 在文档,讨论和实现业务流程之上。 BPMN标准证明了它自己,现在市场上许多建模工具 都使用了BPMN标准中的元素和结构。 实际上,现在的jPDL设计器也使用了 BPMN元素。
BPMN规范的2.0版本,当前已经处于最终阶段了, 已经计划不就就会完成,允许添加精确的技术细节 在BPMN的图形和元素中, 同时制定BPMN元素的执行语法。 通过使用XML语言来指定业务流程的可执行语法, BPMN规范已经演变为业务流程的语言, 可以执行在任何兼容BPMN2的流程引擎中, 同时依然可以使用强大的图形注解。
简单的说是一种规范,只要是标准的BPMN流程模型,只要支持改规范的框架都可以运行这个流程.类似于java的Driver,各大数据库厂商只要满足javaEE的规范,JVM就可以使用和加载驱动
BPMN的组成
常用的节点有如图所示的这么几个
- startEvent 开始节点,一个流程的开始,开始节点只能有一个
- endEvent 结束节点,一个流程的结束,可以有多个,不能没有(没有结束节点的流程,程序能运行,但是肯定不合理)
- flow 线节点,连接task,event,gateway这些节点,主要是控制流程的扭转
- task节点,核心节点,表示一个审批节点,流程进度会停滞在这些task节点,需要调用API来推动流程的进行
- gateway 网关节点,其一个流程控制的作用,比如所有节点的下一个是网关节点的节点审核之后,会停在这个节点当且仅当这些节点全部审核结束,网关节点才会继续往后推动,网关节点也可以有多个出口
简单说明
-
task我们可以表示一个审批人,审批人没有审核之前,流程会一直卡在这个节点,审核通过,会根据审核人的审批结果,来决定流程怎么走,以此来控制流程
-
网关节点和task节点其实都是可有可无的,但是startEvent和endEvent都得有,最简单的BPMN模型就是 开始==>一根线==>结束,一发起直接结束
节点介绍
通用属性
所有的节点都有name,id属性
- id 节点id,单个流程图中唯一,String类型
- name 节点名称,可以重复,String类型
sequenceFlow
线节点,用于连接两个其他节点,有以下属性
SequenceFlow flow6 = new SequenceFlow("companyTask", "documentTask");
flow6.setId("flow6");
flow6.setName("flow6");
flow6.setConditionExpression("${outcome=='驳回'}");
最终要的是这个ConditionExpression,是一个ognl表达式,当我们上一个节点审核通过之后,会带上一些值(Map结构),然后节点将这些值通知给这个节点的所有出口节点,出口节点去匹配这个表达式是否符合,如果符合,就将流程推到下一个节点,我们结合一个图简单说明一下
如图,这是一个带分支结构的流程,此时我们的流程停在节点A,节点A进行审核操作,会带上一些变量,以KV的方式通知给线节点1和线节点2
这里我们通过流程,将一个含有key为outcome,value为通过的Map通知给两个线节点,线节点去匹配表达式,可见:审批节点B是通过的,节点C是不会往这边走的,这就是最简答的一种true false控制
当然这个conditionExpression也不是必填的,不填就是没有任何条件默认通行
startEvent和endEvent
除了线节点以外,大部分节点都有 incomingFlows 和 outgoingFlows 两个属性.表示一个节点的来源和一个节点的出口,看变量名字也知道,这些节点的来源就是上述sequenceFlow节点的集合,出口也是sequenceFlow节点的集合.
开始节点和结束节点比较特殊,要么只有入口,要么只有出口
除了上述的name和id属性之外,其他属性用的就不多了(高级特性我还不太会🐱)
代码
StartEvent startEvent = new StartEvent();
//一个节点在一个流程图中的id,必须唯一的
startEvent.setId("startEvent");
//节点名称,可以重复
startEvent.setName("startEvent");
//设置该节点的出口
startEvent.setOutgoingFlows(new ArrayList<>());
task节点
task节点中userTask节点是比较常用的,可以设置一个执行人和候选人,持有者等信息的.这些还是有点复杂(下一篇一定)
UserTask documentTask = new UserTask();
documentTask.setId("documentTask");
documentTask.setName("资料员提交机构注册信息");
documentTask.setAssignee("role");
documentTask.setCandidateGroups(singletonList("8080"));
之前说的flow和event节点是最基础的节点,必不可少,task节点就偏向于业务一点了,这个节点是一个审批节点
需要我们调用一个complete(Long taskId,Map<String,String> values)方法,来推动这个节点
细心的小伙伴们发现了,task节点需要传递一个Map,这个就是我们上面介绍flow时说过的,审批是可以携带变量的.
还有,一个task节点必定有inComingFlows 和 outGoingFlows,来源和结束.
task节点可以设置多个出口,上面我们介绍了一个简单的是非流程,当然我们是可以在一个task后面设置多个出口的.
假设如图的第一个task节点执行结束,只要该节点想连的两根线都没加条件,那么下面两个task都会被推动,也就是一个流程,单位时间能有两个同时在审核的流程,这个是流程引擎允许的,只需要基本语法不报错,我们的流程配置可以很自由
但是我们上述图还是不太标准的,会有一个大问题: 就是如图所示的节点一旦执行成功,流程直接结束了,可能会导致左边的那个task任务还是审核呢,这个具体看需求了,个人认为一个时间点最多只有一个审批节点待审核比较合理
gateway节点
和userTask节点有点区别,虽然都有id,name,出口,入口这些信息.但是这个节点是自动通过的,只要gateway节点的所有来源节点都扭转过来了,gateway才会推动流程.
好比公交车到了终点站,要等所有的人都下车了,才开走,一两个人下车不可能突然关门的
图中这个gateway节点是不规范的,虽然不会报错,但是左边那个task并没有机会被执行到,流程直接结束了
总结
- startEvent节点,endEvent节点必不可少
- 每个节点都有id,name属性,name属性可以理解为审批的名称,可以用中文,前端显示用,id用于连接流程图中的各个节点
- flow节点可以设置一个ognl表达式,也可以不加
- 结束节点一旦被执行到,流程就结束了,请确保流程只有执行完所有业务逻辑才执行结束流程,而不会出现同时有任务要执行,但是流程要结束的情况
关于task节点,以及审批的具体逻辑,放在下一篇内容比较多,准备好拿小本子记吧