Flowable的基本使用 (4常用BPMN图配置)
上面几篇博客我们已经介绍了BPMN是什么,有什么节点,节点直接的关系与作用,这一篇我们画几个标准一些的BPMN图
一字长蛇阵
流程只要审核了就到下个节点,不审核就一直卡住.节点都配置了权限信息,只要对应的负责人才可以审核
给两个审批节点都加一个审批组,一个是[“departmentLeader”],一个是[“companyLeader”]
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
<process id="一字长蛇" name="一字长蛇" isExecutable="true">
<documentation>一字长蛇</documentation>
<startEvent id="startEvent1" name="审核开始"></startEvent>
<userTask id="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" name="部门领导审批" flowable:candidateGroups="departmentLeader"></userTask>
<userTask id="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" name="公司领导审批" flowable:candidateGroups="companyLeader"></userTask>
<endEvent id="sid-4D46B174-E45F-4630-992F-518587C63AB5" name="审核结束"></endEvent>
<sequenceFlow id="sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9" sourceRef="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" targetRef="sid-4D46B174-E45F-4630-992F-518587C63AB5"></sequenceFlow>
<sequenceFlow id="sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B" sourceRef="startEvent1" targetRef="sid-038663FF-F468-4636-A8E2-21C191CDC8B3"></sequenceFlow>
<sequenceFlow id="sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF" sourceRef="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" targetRef="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_一字长蛇">
<bpmndi:BPMNPlane bpmnElement="一字长蛇" id="BPMNPlane_一字长蛇">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="410.0" y="75.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" id="BPMNShape_sid-038663FF-F468-4636-A8E2-21C191CDC8B3">
<omgdc:Bounds height="80.0" width="100.0" x="375.0" y="180.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" id="BPMNShape_sid-35F42996-FBBD-4046-A5FF-5099A6D467D0">
<omgdc:Bounds height="80.0" width="100.0" x="375.0" y="322.31403942536787"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-4D46B174-E45F-4630-992F-518587C63AB5" id="BPMNShape_sid-4D46B174-E45F-4630-992F-518587C63AB5">
<omgdc:Bounds height="28.0" width="28.0" x="411.0" y="458.6776714899466"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B" id="BPMNEdge_sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B">
<omgdi:waypoint x="425.0" y="104.94999891876283"></omgdi:waypoint>
<omgdi:waypoint x="425.0" y="180.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9" id="BPMNEdge_sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9">
<omgdi:waypoint x="425.0" y="402.26403942536786"></omgdi:waypoint>
<omgdi:waypoint x="425.0" y="458.6776714899466"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF" id="BPMNEdge_sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF">
<omgdi:waypoint x="425.0" y="259.95000000000005"></omgdi:waypoint>
<omgdi:waypoint x="425.0" y="322.31403942536787"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
演示
因为是demo,没有做登录注册,所以用最简单的方式了,公司和角色都是用静态变量代替
设置公司和角色,默认996,role为employee
<select id="setRole">
<option value="employee">普通员工</option>
<option value="departmentLeader">部门领导</option>
<option value="companyLeader">公司领导</option>
</select>
private static String role = "employee";
private static String companyName = "996";
@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("setCompanyName")
public ResultData<String> setCompanyName(String companyName) {
FlowableController.companyName = companyName;
return ResultData.ofSuccess();
}
@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("setRole")
public ResultData<String> setRole(String role) {
FlowableController.role = role;
return ResultData.ofSuccess();
}
996公司,普通员工,发起了一个一字长蛇审批流程,方法返回success,流程的id是 2b8d81ab-2ccb-11ec-b622-f26c8efdde3a
我们查看普通员工待审批的流程,可以看见是空的
换成部门领导就有东西了
传入taskId,进行审批操作,返回结果是成功
再查看待办流程,可以看见是空的,因为流程已经审核过来,下一个节点是公司领导
公司领导查看流程
领导审核略…
领导审核结束,流程结束,我们通过最早之前生成的流程图返回的processInstanceId来查询流程
条件判断
上面的流程比较简单,但是流程并不能砍掉,没人审核就卡住,也没有拒绝通过的说法,调用审核驳回和审核通过没有区别
我们看到拒绝和通过都是掉用complete方法,区别就是map的内容不一样,但是我们并没有用map的内容做一个条件过滤,所以两个接口效果一样
@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/apply")
public ResultData<String> apply(@RequestParam String id) {
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "通过");
taskService.complete(id, map);
return ResultData.ofSuccess();
}
@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/reject")
public ResultData<String> reject(@RequestParam String id) {
//拒绝审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "驳回");
taskService.complete(id, map);
return ResultData.ofSuccess();
}
接下来我们来整一个带条件分支的审批节点
如图所示的线节点添加表达式 {outcome}==‘通过’ 另一根线是驳回,为了方便展示审批节点名称,我改了一下
审批过程我跳过了,简单看一下,这个是接受996的
这个不是不接受的,通过我们不同的选择,控制了流程的走向,这是一个非常简单的是非条件判断控制
驳回
如图,假设部门领导审核和公司领导审核可以通过或者撤回
员工提交审核的时候默认就通过的,然后部门领导和公司领导的审核都可能会打回流程,直接打回到员工提交请假申请,让员工重新提交.
图就不演示了
简单的说,只要一个审核打回去,我们就一朝回到解放前,只有都通过流程才能结束,非常常见的一个请假流程.钉钉上的请假流程基本也是这种方式
复杂流程
这里我使用一个项目中最复杂的流程图
- 用户提交资料,交给财务和合规审核,可能有一个过程被打回,然后用户再重新提交
- 财务和合规审核都通过的情况下,到领导回访,领导回访后面还有总部回访,都通过流程结束
- 如果领导和总部回访打回,不会跑到梦开始的地方,而是跑到一个新的节点,用户有部分的信息可以重新提交修改,之前部分审核通过的数据就不能修改了
就给你们看看,flowable的上限可以多少高,你们也可以思考一下,项目中及其复杂的流程可以不可以用flowable来画出流程图
总结
- BPMN的图非常灵活,甚至我们可以写出类似while,for循环的操作,BPMN可以满足业务中任何的流程
- BPMN模型一般在部署的时候不会报错,只要格式不出问题都可以部署成功,但是运行的时候非常容易出问题,需要后端在前端上传流程图配置文件的时候进行足够的校验限制,避免流程部署的时候出错
- 使用流程引擎来管理业务流程的时候,我们业务状态应该以流程引擎的状态为主,不要自己再加状态了.