事件等简介摘抄自官方文档
*后台服务基于Springboot2 + Activiti6,整合文章请参考:blog.csdn.net/yy756127197… 不需要流程设计器就排除3,4步骤 *
1. 简介
1.1 信号事件定义
信号事件会引用一个已命名的信号。信号全局范围的事件(广播语义)。 会发送给所有激活的处理器。
1.2 触发信号事件
既可以通过bpmn节点由流程实例触发一个信号,也可以通过API触发。
手工触发信号:
// 把信号发送给全局所有订阅的处理器
RuntimeService.signalEventReceived(String signalName);
// 把信号发送给指定执行流
RuntimeService.signalEventReceived(String signalName, String executionId);
1.3 查询信号事件的订阅
List<Execution> executions = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("alert")
.list();
1.4 信号事件范围
默认,信号会在流程引擎范围内进行广播。就是说, 你可以在一个流程实例中抛出一个信号事件,其他不同流程定义的流程实例 都可以监听到这个事件。然而,有时只希望在同一个流程实例中响应这个信号事件。 比如一个场景是,流程实例中的同步机制,如果两个或更多活动是互斥的。
如果想要限制信号事件的范围,可以使用信号事件定义的scope 属性 (不是BPMN2.0的标准属性):
<signal id="alertSignal" name="alert" activiti:scope"processInstance"/>
2. 信号边界事件
2.1 简介
信号边界事件的触发条件是接收信号,它具有全局性,可以捕获全局范围的信号。他也可以通过Cancel activity设置中不中断当前流程。
2.2 流程设计
例如有如下场景,系统提交工单后到达审批节点,在审批过程中,如果用户要修改工单,那么发送一个信号,使流程走到更改工单节点。
定义信号
定义信号
** 信号边界事件设置 **
流程图
流程文件bpmn
<?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:activiti="http://activiti.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.activiti.org/processdef">
<signal id="changeSignal" name="changeSignal" activiti:scope="processInstance"></signal>
<signal id="changeSignal1" name="changeSignal1" activiti:scope="global"></signal>
<process id="signalBoundary" name="signalBoundary" isExecutable="true">
<documentation>signalBoundary</documentation>
<startEvent id="startEvent1"></startEvent>
<userTask id="sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E" name="填写工单" activiti:assignee="signalUser1">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-FBFB7B2D-2C9A-4E35-90AD-A799CB8D1367" sourceRef="startEvent1" targetRef="sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E"></sequenceFlow>
<userTask id="sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217" name="审批" activiti:assignee="signalUser2">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-D46B53F4-C0A7-4126-9A0C-462A1D265CD0" sourceRef="sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E" targetRef="sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217"></sequenceFlow>
<endEvent id="sid-64EB510C-655F-45CD-9CEA-992C3E710F3B"></endEvent>
<sequenceFlow id="sid-89298A87-4C35-4862-AF21-7968B1C06E0B" sourceRef="sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217" targetRef="sid-64EB510C-655F-45CD-9CEA-992C3E710F3B"></sequenceFlow>
<userTask id="sid-96C89574-6419-4425-8B8D-50B5E5A7E3AE" name="更改工单" activiti:assignee="signalUser3">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<boundaryEvent id="sid-FBF733A4-A0F1-488F-94B7-5358259B28AA" attachedToRef="sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217" cancelActivity="true">
<signalEventDefinition signalRef="changeSignal1"></signalEventDefinition>
</boundaryEvent>
<sequenceFlow id="sid-2A186268-075E-4A2E-B29C-DB9CD6838F1B" sourceRef="sid-FBF733A4-A0F1-488F-94B7-5358259B28AA" targetRef="sid-96C89574-6419-4425-8B8D-50B5E5A7E3AE"></sequenceFlow>
<sequenceFlow id="sid-95E46AE3-7189-4E7E-B343-4C228FE1FA04" sourceRef="sid-96C89574-6419-4425-8B8D-50B5E5A7E3AE" targetRef="sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_signalBoundary">
<bpmndi:BPMNPlane bpmnElement="signalBoundary" id="BPMNPlane_signalBoundary">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="105.0" y="97.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E" id="BPMNShape_sid-C6207224-2E9B-49BF-A0EB-DED271F22E8E">
<omgdc:Bounds height="80.0" width="100.0" x="245.0" y="72.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217" id="BPMNShape_sid-2CABBC48-3032-47FD-B0C7-0A5EC44CF217">
<omgdc:Bounds height="80.0" width="100.0" x="472.36389780320144" y="72.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-64EB510C-655F-45CD-9CEA-992C3E710F3B" id="BPMNShape_sid-64EB510C-655F-45CD-9CEA-992C3E710F3B">
<omgdc:Bounds height="28.0" width="28.0" x="665.0" y="98.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-96C89574-6419-4425-8B8D-50B5E5A7E3AE" id="BPMNShape_sid-96C89574-6419-4425-8B8D-50B5E5A7E3AE">
<omgdc:Bounds height="80.0" width="100.0" x="360.0" y="240.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-FBF733A4-A0F1-488F-94B7-5358259B28AA" id="BPMNShape_sid-FBF733A4-A0F1-488F-94B7-5358259B28AA">
<omgdc:Bounds height="30.0" width="30.0" x="509.727795606403" y="137.186262654425"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-95E46AE3-7189-4E7E-B343-4C228FE1FA04" id="BPMNEdge_sid-95E46AE3-7189-4E7E-B343-4C228FE1FA04">
<omgdi:waypoint x="360.0" y="280.0"></omgdi:waypoint>
<omgdi:waypoint x="295.0" y="280.0"></omgdi:waypoint>
<omgdi:waypoint x="295.0" y="152.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-D46B53F4-C0A7-4126-9A0C-462A1D265CD0" id="BPMNEdge_sid-D46B53F4-C0A7-4126-9A0C-462A1D265CD0">
<omgdi:waypoint x="345.0" y="112.0"></omgdi:waypoint>
<omgdi:waypoint x="472.36389780320144" y="112.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-FBFB7B2D-2C9A-4E35-90AD-A799CB8D1367" id="BPMNEdge_sid-FBFB7B2D-2C9A-4E35-90AD-A799CB8D1367">
<omgdi:waypoint x="135.0" y="112.0"></omgdi:waypoint>
<omgdi:waypoint x="245.0" y="112.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-89298A87-4C35-4862-AF21-7968B1C06E0B" id="BPMNEdge_sid-89298A87-4C35-4862-AF21-7968B1C06E0B">
<omgdi:waypoint x="572.3638978032014" y="112.0"></omgdi:waypoint>
<omgdi:waypoint x="665.0" y="112.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-2A186268-075E-4A2E-B29C-DB9CD6838F1B" id="BPMNEdge_sid-2A186268-075E-4A2E-B29C-DB9CD6838F1B">
<omgdi:waypoint x="524.727795606403" y="167.186262654425"></omgdi:waypoint>
<omgdi:waypoint x="524.727795606403" y="280.0"></omgdi:waypoint>
<omgdi:waypoint x="460.0" y="280.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
2.3 测试类
SignalBoundaryTest.java
import com.it.cloud.modules.activiti.service.IActReModelService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 信号边界事件
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class SignalBoundaryTest {
@Autowired
private IActReModelService actReModelService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
/**
* 部署流程定义
*/
@Test
public void deploy() {
Deployment deployment = repositoryService.createDeployment() // 创建部署
.addClasspathResource("diagrams/signalBoundary.bpmn20.xml") // 加载流程资源文件
.name("signalBoundary流程") // 流程名称
.deploy(); // 部署
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署Name:" + deployment.getName());
}
/**
* 启动流程实例
*/
@Test
public void start() throws InterruptedException {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("signalBoundary"); // 流程定义表的KEY字段值
System.out.println("流程实例ID:" + pi.getId());
System.out.println("流程定义ID:" + pi.getProcessDefinitionId());
// 睡一会
Thread.sleep(1000 * 10);
System.out.println("--------------------------------------------");
// 查询任务
List<Task> taskList = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("signalUser1") // 指定某个人
.list();
for (Task task : taskList) {
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
// 完成任务
taskService.complete(task.getId());
}
// 查询任务
List<Task> taskList1 = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("signalUser2") // 指定某个人
.list();
for (Task task : taskList1) {
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
}
// 睡一会
Thread.sleep(1000 * 10);
System.out.println("--------------------------------------------");
// 发送信号
runtimeService.signalEventReceived("changeSignal1");
// 睡一会
Thread.sleep(1000 * 10);
// 查询任务
List<Task> taskList2 = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("signalUser3") // 指定某个人
.list();
for (Task task : taskList2) {
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
}
}
/**
* 查看任务
*/
@Test
public void queryTask() {
List<Task> taskList = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("signalUser3") // 指定某个人
.list();
for (Task task : taskList) {
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
}
}
/**
* 完成任务
*/
@Test
public void completeTask() {
taskService.complete("275005");
}
/**
* 发送信号
*/
@Test
public void eventReceived() {
// 可以查询所有订阅了特定信号事件的执行流
List<Execution> executions = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("changeSignal1")
.list();
// 把信号发送给全局所有订阅的处理器(广播语义)
runtimeService.signalEventReceived("changeSignal1");
// 只把信息发送给指定流程的执行
runtimeService.signalEventReceived("changeSignal1", executions.get(0).getId());
}
}
2.4 运行
运行deploy()
2.4.1 启动任务
运行start()
效果:
完成填写工单任务后,到达审批任务节点,发送信号后到达更改工单节点