虽说本文的题目是流程回退和终止,但是其实抽象出来就是流程跳转,可以从某个节点跳转到另一个节点(顺序流下)。
流程
<?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" exporter="Flowable Open Source Modeler" exporterVersion="6.7.2">
<process id="back" name="任务回退" isExecutable="true">
<startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-8AC1482C-4FCE-463D-A53D-6217AF3A1470" name="任务1" flowable:assignee="晴子" flowable:formFieldValidation="true">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-3C0468ED-3273-4AA6-8CDE-E829CA26C949" sourceRef="startEvent1" targetRef="sid-8AC1482C-4FCE-463D-A53D-6217AF3A1470"></sequenceFlow>
<userTask id="sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161" name="任务2" flowable:assignee="樱木" flowable:formFieldValidation="true">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-1D6E7275-BB21-408D-81E3-54F2BEA1B232" sourceRef="sid-8AC1482C-4FCE-463D-A53D-6217AF3A1470" targetRef="sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161"></sequenceFlow>
<userTask id="sid-E6554C0D-CAB2-44BD-9A9C-AB52C7E1155D" name="任务3" flowable:assignee="三井寿" flowable:formFieldValidation="true">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-C561FA4D-323F-48F8-834D-262A8DE4B065" sourceRef="sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161" targetRef="sid-E6554C0D-CAB2-44BD-9A9C-AB52C7E1155D"></sequenceFlow>
<endEvent id="sid-801ADA46-08B6-4508-9C63-D6CD76677CF2"></endEvent>
<sequenceFlow id="sid-D8445911-CE2A-4BDD-9237-EC02A4109C20" sourceRef="sid-E6554C0D-CAB2-44BD-9A9C-AB52C7E1155D" targetRef="sid-801ADA46-08B6-4508-9C63-D6CD76677CF2"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_back">
<bpmndi:BPMNPlane bpmnElement="back" id="BPMNPlane_back">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-8AC1482C-4FCE-463D-A53D-6217AF3A1470" id="BPMNShape_sid-8AC1482C-4FCE-463D-A53D-6217AF3A1470">
<omgdc:Bounds height="80.0" width="100.0" x="175.0" y="138.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161" id="BPMNShape_sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161">
<omgdc:Bounds height="80.0" width="100.0" x="320.0" y="138.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-E6554C0D-CAB2-44BD-9A9C-AB52C7E1155D" id="BPMNShape_sid-E6554C0D-CAB2-44BD-9A9C-AB52C7E1155D">
<omgdc:Bounds height="80.0" width="100.0" x="465.0" y="138.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-801ADA46-08B6-4508-9C63-D6CD76677CF2" id="BPMNShape_sid-801ADA46-08B6-4508-9C63-D6CD76677CF2">
<omgdc:Bounds height="28.0" width="28.0" x="610.0" y="164.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-D8445911-CE2A-4BDD-9237-EC02A4109C20" id="BPMNEdge_sid-D8445911-CE2A-4BDD-9237-EC02A4109C20" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="14.0" flowable:targetDockerY="14.0">
<omgdi:waypoint x="564.95" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="610.0" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-C561FA4D-323F-48F8-834D-262A8DE4B065" id="BPMNEdge_sid-C561FA4D-323F-48F8-834D-262A8DE4B065" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="419.94999999999067" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="464.9999999999807" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-1D6E7275-BB21-408D-81E3-54F2BEA1B232" id="BPMNEdge_sid-1D6E7275-BB21-408D-81E3-54F2BEA1B232" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="274.9499999999907" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="319.9999999999807" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-3C0468ED-3273-4AA6-8CDE-E829CA26C949" id="BPMNEdge_sid-3C0468ED-3273-4AA6-8CDE-E829CA26C949" flowable:sourceDockerX="15.0" flowable:sourceDockerY="15.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="129.9499984899576" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="174.9999999999917" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
核心代码
特别注意repositoryService.getBpmnModel这附近的代码,是获取流程定义的详细内容的代码,特别是获取act的详细信息。
实际场景中是这样的,当前用户查询当前所处的节点,为用户展示流程的其他节点,让用户可以选择回退到哪个节点
// 流程回退
@Transactional
public void back() {
// 实际场景中是这样的,当前用户查询当前所处的节点,为用户展示流程的其他节点,让用户可以选择回退到哪个节点
Task currentActivity = taskService.createTaskQuery().processInstanceId("921b0707-b626-11ec-8e37-3c9c0f202230").taskAssignee("三井寿").singleResult();
// 找到每个元素,包括节点和顺序流
Process mainProcess = repositoryService.getBpmnModel("back:1:dd16163a-b625-11ec-9161-3c9c0f202230").getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
for (FlowElement flowElement:
flowElements) {
System.out.println(flowElement.getId());
}
String endNodeId = flowElements.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList()).get(0).getId();
//注意这里传入的参数是节点定义id,不是对应的那条记录的id
//我这里测试就写死了,实际中是从flowElements中取出来的,FlowElement.getId()
runtimeService.createChangeActivityStateBuilder().processInstanceId("921b0707-b626-11ec-8e37-3c9c0f202230").moveActivityIdTo(currentActivity.getTaskDefinitionKey(),"sid-C2F5C4B5-7635-4F28-8869-DDF42FF56161").changeState();
}
// 流程终止
@Transactional
public void end() {
// 在当前节点直接终止
Task currentActivity = taskService.createTaskQuery().processInstanceId("921b0707-b626-11ec-8e37-3c9c0f202230").taskAssignee("樱木").singleResult();
// 找到每个元素,包括节点和顺序流
Process mainProcess = repositoryService.getBpmnModel("back:1:dd16163a-b625-11ec-9161-3c9c0f202230").getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
for (FlowElement flowElement:
flowElements) {
System.out.println(flowElement.getId());
}
String endNodeId = flowElements.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList()).get(0).getId();
runtimeService.createChangeActivityStateBuilder().processInstanceId("921b0707-b626-11ec-8e37-3c9c0f202230").moveActivityIdTo(currentActivity.getTaskDefinitionKey(),endNodeId).changeState();
}
机制思考
流程回退或者终止后act_ru_task表会改变为最新的状态,这个不用多解释。
看下act_hi_taskinst表:
可以看出,有多个任务2,多个任务3,这些都是我操作过回退和终止造成的,在DELETE_REASON_字段中有解释,to ----,就是表明节点跳转到哪里而结束的。
这些“半吊子”股民以为自己变聪明了,喜欢在股价下跌时买进。他们总是等待下跌,根据股价从顶部下跌的点数来衡量自己捡到了多大便宜。在大牛市中,那些纯粹的菜鸟股民完全无视交易规则和先例,盲目买进,做着“一夜暴富”的美梦。他们可以赚到很多钱,但一次正常的回调就可以扫光他们所有的利润。
赚大钱不能靠个股的波动,而要靠大盘走势;不能靠解读盘面,而要靠预判整个市场和市场趋势。