【弄nèng - Activiti6】入门篇(十二)—— 信号边界事件

493 阅读3分钟

事件等简介摘抄自官方文档

*后台服务基于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()

效果:
完成填写工单任务后,到达审批任务节点,发送信号后到达更改工单节点
在这里插入图片描述


源码地址

IT-CLOUD-ACTIVITI6\