文章目录
- 一、背景
- 二、定义
- 三、流程准备
- 四、流程文件
- 五、控制器
- 六、流程通过验证
- 6.1. 创建新流程
- 6.2. 启动流程
- 6.3. 控制台查看任务ID
- 6.4. 通过流程
- 6.5. 查看流程图
- 七、流程拒绝验证
- 7.1. 创建新流程
- 7.2. 启动流程
- 7.3. 控制台查看任务ID
- 7.4. 拒绝流程
- 7.5. 查看流程图
一、背景
- 流程在审批的过程中需要进行一些判断然后再看下一步怎么走,完成判断逻辑的是网关,排他网关就是其中的一种。
二、定义
排他网关(也叫异或(XOR)网关,或更技术性的叫法 基于数据的排他网关), 用来在流程中实现决策。 当流程执行到这个网关,所有外出顺序流都会被处理一遍。 其中条件解析为true的顺序流(或者没有设置条件,概念上在顺序流上定义了一个’true’) 会被选中,让流程继续运行。简单理解条件为True继续执行,False将不执行。
三、流程准备
我们在Modeler中给我们的流程配置一个排他网关,添加后流程如下:
在排他网关的到结束的连接线上配置好网关是否通过的条件,比如审核通过我们设置为${outcome==‘通过’},当走到这里流程变量outcome为通过的时候将会走审核通过这个流程,等于拒绝的时候走下面的流程,参数配置如下图所示:
四、流程文件
流程文件内容如下:
<?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="test_bpmn" name="测试BPMN模型" isExecutable="true">
<documentation>测试BPMN模型</documentation>
<startEvent id="start" name="开始"></startEvent>
<endEvent id="end" name="通过结束"></endEvent>
<userTask id="testUser" name="用户任务测试" flowable:assignee="admin">
<extensionElements>
<flowable:taskListener event="create" class="com.hyj.flowlistener.CommonUserStartListener"></flowable:taskListener>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002" sourceRef="start" targetRef="testUser"></sequenceFlow>
<exclusiveGateway id="ex_gateway_check" name="审核结果"></exclusiveGateway>
<sequenceFlow id="sid-50731902-EF37-4E07-9DED-2E83F7EB54B7" sourceRef="testUser" targetRef="ex_gateway_check"></sequenceFlow>
<endEvent id="end_fail" name="失败结束"></endEvent>
<sequenceFlow id="check_fail" name="审核拒绝" sourceRef="ex_gateway_check" targetRef="end_fail">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='拒绝'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="check_ok" name="审核通过" sourceRef="ex_gateway_check" targetRef="end">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_test_bpmn">
<bpmndi:BPMNPlane bpmnElement="test_bpmn" id="BPMNPlane_test_bpmn">
<bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
<omgdc:Bounds height="30.0" width="30.0" x="210.0" y="120.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
<omgdc:Bounds height="28.0" width="28.0" x="630.0" y="60.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="testUser" id="BPMNShape_testUser">
<omgdc:Bounds height="80.0" width="100.0" x="315.0" y="95.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="ex_gateway_check" id="BPMNShape_ex_gateway_check">
<omgdc:Bounds height="40.0" width="40.0" x="480.0" y="115.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="end_fail" id="BPMNShape_end_fail">
<omgdc:Bounds height="28.0" width="28.0" x="630.0" y="180.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="check_fail" id="BPMNEdge_check_fail">
<omgdi:waypoint x="500.5" y="154.4338310580205"></omgdi:waypoint>
<omgdi:waypoint x="500.5" y="194.0"></omgdi:waypoint>
<omgdi:waypoint x="630.0" y="194.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002" id="BPMNEdge_sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002">
<omgdi:waypoint x="239.94999779398907" y="135.0"></omgdi:waypoint>
<omgdi:waypoint x="315.0" y="135.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-50731902-EF37-4E07-9DED-2E83F7EB54B7" id="BPMNEdge_sid-50731902-EF37-4E07-9DED-2E83F7EB54B7">
<omgdi:waypoint x="414.95000000000005" y="135.0"></omgdi:waypoint>
<omgdi:waypoint x="480.0" y="135.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="check_ok" id="BPMNEdge_check_ok">
<omgdi:waypoint x="500.5" y="115.5"></omgdi:waypoint>
<omgdi:waypoint x="500.5" y="74.0"></omgdi:waypoint>
<omgdi:waypoint x="630.0" y="74.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
五、控制器
- 控制器原来直接是个完成任务现在,我们方便起见拆分为2个一个是通过任务,一个是拒绝任务,如果你的排他网关使用的都是该参数那么就可以通用。
@RequestMapping("/accept")
@ResponseBody
public Map<String,Object> acceptTask(@RequestBody @RequestParam(required = false) Map<String,String> paras){
Map<String,Object> res =new HashMap<>();
Map<String,String> data = new HashMap<>();
if (MapUtils.isEmpty(paras)){
res.put("msg","请输入任务参数");
res.put("res","0");
res.put("data",data);
return res;
}
String taskId = paras.get("taskId");
if (StringUtils.isEmpty(taskId)){
res.put("msg","请输入任务ID");
res.put("res","0");
res.put("data",data);
return res;
}
Map<String,Object> flowParas=new HashMap<>();
flowParas.putAll(paras);
flowParas.put("outcome","通过");
boolean bok = flowService.completeTask(taskId,flowParas);
if (bok){
data.put("taskId",taskId);
res.put("msg","通过任务成功");
res.put("res","1");
}
else {
data.put("taskId",taskId);
res.put("msg","通过任务失败");
res.put("res","0");
}
res.put("data",data);
return res;
}
@RequestMapping("/reject")
@ResponseBody
public Map<String,Object> rejectTask(@RequestBody @RequestParam(required = false) Map<String,String> paras){
Map<String,Object> res =new HashMap<>();
Map<String,String> data = new HashMap<>();
if (MapUtils.isEmpty(paras)){
res.put("msg","请输入任务参数");
res.put("res","0");
res.put("data",data);
return res;
}
String taskId = paras.get("taskId");
if (StringUtils.isEmpty(taskId)){
res.put("msg","请输入任务ID");
res.put("res","0");
res.put("data",data);
return res;
}
Map<String,Object> flowParas=new HashMap<>();
flowParas.putAll(paras);
flowParas.put("outcome","拒绝");
boolean bok = flowService.completeTask(taskId,flowParas);
if (bok){
data.put("taskId",taskId);
res.put("msg","拒绝任务成功");
res.put("res","1");
}
else {
data.put("taskId",taskId);
res.put("msg","拒绝任务失败");
res.put("res","0");
}
res.put("data",data);
return res;
}
六、流程通过验证
6.1. 创建新流程
使用测试BPMN模型4.bpmn20.xml
的流程配置文件,输入创建地址完成创建。
http://localhost:8989/flow/create
6.2. 启动流程
http://localhost:8989/flow/start?processKey=test_bpmn 输入改地址完成流程启动
6.3. 控制台查看任务ID
- 此时查看流程后台,会打印当前的任务ID
6.4. 通过流程
输入新增的通过地址完成流程审批
http://localhost:8989/flow/accept?taskId=99bb7920-0082-11ea-8f3c-f8a2d6bfea5a
6.5. 查看流程图
进入流程查看地址:
http://localhost:8989/flow/processDiagram?processId=8f9bf5e7-0083-11ea-9dbd-f8a2d6bfea5a 查看我们的审批流程走到了最后,而拒绝没有发生变化,说明排他网关成功的区分了两个流程,流程进展如下图所示:
七、流程拒绝验证
7.1. 创建新流程
替换罪行的流程配置文件,输入创建地址完成创建。
http://localhost:8989/flow/create
7.2. 启动流程
http://localhost:8989/flow/start?processKey=test_bpmn ,输入改地址完成流程启动
processId:976c4c43-0106-11ea-85ad-f8a2d6bfea5a
7.3. 控制台查看任务ID
- 此时查看流程后台,会打印当前的任务ID
7.4. 拒绝流程
输入新增的通过地址完成流程审批
http://localhost:8989/flow/reject?taskId=9774b0b9-0106-11ea-85ad-f8a2d6bfea5a
7.5. 查看流程图
进入流程查看地址:
http://localhost:8989/flow/processDiagram?processId=976c4c43-0106-11ea-85ad-f8a2d6bfea5a ,查看我们的审批流程走到了最后,而拒绝没有发生变化,说明排他网关成功的区分了两个流程,流程进展如下图所示:
代码下载:
gitlab链接:https://gitlab.com/gb-heima/flowablestudy/tree/master/flowablelech15
码云链接:https://gitee.com/gb_90/flowable-study/tree/master/flowablelech15