SpringBoot整合Activiti7——全局监听器(八)

news/2024/5/19 0:28:27 标签: spring boot, java, 流程图

文章目录

  • 一、全局监听器
    • 事件类型
    • 配置方式(选)
    • 日志监听器
    • 代码实现
      • xml文件
      • 创建全局监听器
      • 全局配置类
      • 测试流程
        • 部署流程
        • 启动流程


一、全局监听器

它是引擎范围的事件监听器,可以捕获所有的Activiti事件。

事件类型

ActivitiEventType 枚举类中包含全部事件类型

配置方式(选)

  1. spring bean配置

  2. 全局配置类设置(config.setEventListeners())

    java">config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));
    
  3. 启动流程动态添加并且可以指定要监听的事件类型(推荐)

    java">runtimeService.addEventListener(new MyGlobalEventListener(), ActivitiEventType.TASK_CREATED, ActivitiEventType.TASK_ASSIGNED, ActivitiEventType.TASK_COMPLETED);
    
  4. class

  5. expression

  6. delegateExpression

日志监听器

全局配置类开启:config.setEnableDatabaseEventLogging(true);

开启后可以在 act_evt_log表中看到相关的日志记录。

代码实现

在这里插入图片描述

xml文件

<?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">
  <process id="global-listener" name="全局事件监听器" isExecutable="true">
    <documentation>测试全局事件监听器</documentation>
    <extensionElements>
      <!-- 需要高版本的插件才能不爆红 支持class expression delegateExpression 配置方式 -->
<!--      <activiti:eventListener entityType="task" delegateExpression="${myGlobalEventListener}"/>-->
    </extensionElements>
    <startEvent id="sid-30244641-2a1c-43e5-af5b-e77db43488bf" name="开始">
      <documentation>开始了</documentation>
    </startEvent>
    <userTask id="sid-9e62413f-e04f-4c81-8d0c-e73f17e125ec" name="节点1"
              activiti:assignee="${applyUserId}" activiti:candidateUsers="${candidateUsers}" activiti:candidateGroups="${candidateGroups}">
      <documentation>任务节点1</documentation>
    </userTask>
    <sequenceFlow id="sid-1af5e647-b03c-4b12-807d-4171dfdf7ae9" sourceRef="sid-30244641-2a1c-43e5-af5b-e77db43488bf" targetRef="sid-9e62413f-e04f-4c81-8d0c-e73f17e125ec" name="顺序流1">
      <documentation>顺序流1了</documentation>
    </sequenceFlow>
    <userTask id="sid-d903cb09-56c2-4cfe-bd05-5ba0699539d0" name="节点2">
      <documentation>任务节点2</documentation>
    </userTask>
    <sequenceFlow id="sid-300ac02e-dc56-4988-bdd4-fd94a5bb71f7" sourceRef="sid-9e62413f-e04f-4c81-8d0c-e73f17e125ec" targetRef="sid-d903cb09-56c2-4cfe-bd05-5ba0699539d0" name="顺序流2">
      <documentation>顺序流2了</documentation>
    </sequenceFlow>
    <endEvent id="sid-ace3a923-023c-4226-875c-2a0a30cc1c50" name="结束">
      <documentation>结束了</documentation>
    </endEvent>
    <sequenceFlow id="sid-dbf73610-a8b4-4149-828e-4f5bc252c80d" sourceRef="sid-d903cb09-56c2-4cfe-bd05-5ba0699539d0" targetRef="sid-ace3a923-023c-4226-875c-2a0a30cc1c50" name="顺序流3">
      <documentation>顺序流3了</documentation>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_execution-listener">
    <bpmndi:BPMNPlane bpmnElement="global-listener" id="BPMNPlane_execution-listener">
      <bpmndi:BPMNShape id="shape-d4dd6424-1316-4c10-a8f9-f3c501cd4073" bpmnElement="sid-30244641-2a1c-43e5-af5b-e77db43488bf">
        <omgdc:Bounds x="-442.5" y="-6.75" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-bcd8743b-6857-42d1-bc71-bd3bb6eed795" bpmnElement="sid-9e62413f-e04f-4c81-8d0c-e73f17e125ec">
        <omgdc:Bounds x="-388.0" y="-31.75" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-d562b253-050f-4617-bbad-2e16950c15e4" bpmnElement="sid-1af5e647-b03c-4b12-807d-4171dfdf7ae9">
        <omgdi:waypoint x="-412.5" y="8.25"/>
        <omgdi:waypoint x="-388.0" y="8.25"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="shape-cd7c00d6-f5f0-4afe-867c-6f576efc286d" bpmnElement="sid-d903cb09-56c2-4cfe-bd05-5ba0699539d0">
        <omgdc:Bounds x="-259.0" y="-31.75" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-44a5c4d2-2ab7-48f1-adc7-c7a7a099800c" bpmnElement="sid-300ac02e-dc56-4988-bdd4-fd94a5bb71f7">
        <omgdi:waypoint x="-288.0" y="8.25"/>
        <omgdi:waypoint x="-259.0" y="8.25"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="shape-05cc9b19-8019-471d-b31c-bb41c42e3529" bpmnElement="sid-ace3a923-023c-4226-875c-2a0a30cc1c50">
        <omgdc:Bounds x="-123.0" y="-6.75" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-923723d0-33e3-4a62-bed9-bb16d4c9b175" bpmnElement="sid-dbf73610-a8b4-4149-828e-4f5bc252c80d">
        <omgdi:waypoint x="-159.0" y="8.25"/>
        <omgdi:waypoint x="-123.0" y="8.25"/>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

创建全局监听器

java">@Component("myGlobalEventListener")
public class MyGlobalEventListener implements ActivitiEventListener {

    @Override
    public void onEvent(ActivitiEvent event) {
        System.out.println("========================MyGlobalEventListener========================");

        switch (event.getType()) {
            case TASK_CREATED:
                this.taskCreate(event);
                break;
            case TASK_ASSIGNED:
                this.taskAssigned(event);
                break;
            case TASK_COMPLETED:
                this.taskComplete(event);
                break;
            default:
                System.out.println("Event received: " + event.getType());
        }
    }

    /**
     * 上面的 onEvent 方法抛出异常的后续处理动作
     * false :表示忽略onEvent()方法方法中抛出的异常
     * true :表示onEvent()方法中抛出的异常继续向上传播,导致当前操作失败
     */
    @Override
    public boolean isFailOnException() {
        return false;
    }

    private void taskCreate(ActivitiEvent event) {
        System.out.println("===================任务创建事件===================");
        ActivitiEntityEventImpl activitiEntityEvent = (ActivitiEntityEventImpl) event;
        TaskEntity taskEntity = (TaskEntity) activitiEntityEvent.getEntity();
        System.out.println("taskEntity.getId() = " + taskEntity.getId());
        System.out.println("taskEntity.getName() = " + taskEntity.getName());
        System.out.println("taskEntity.getAssignee() = " + taskEntity.getAssignee());
        System.out.println("taskEntity.getIdentityLinks() = " + taskEntity.getIdentityLinks());
        System.out.println("taskEntity.getVariables() = " + taskEntity.getVariables());
    }

    private void taskAssigned(ActivitiEvent event) {
        System.out.println("===================任务分配事件===================");
        ActivitiEntityEventImpl activitiEntityEvent = (ActivitiEntityEventImpl) event;
        TaskEntity taskEntity = (TaskEntity) activitiEntityEvent.getEntity();
        System.out.println("taskEntity.getId() = " + taskEntity.getId());
        System.out.println("taskEntity.getName() = " + taskEntity.getName());
        System.out.println("taskEntity.getAssignee() = " + taskEntity.getAssignee());
        System.out.println("taskEntity.getIdentityLinks() = " + taskEntity.getIdentityLinks());
        System.out.println("taskEntity.getVariables() = " + taskEntity.getVariables());
    }

    private void taskComplete(ActivitiEvent event) {
        System.out.println("===================任务完成事件===================");
        ActivitiEntityEventImpl activitiEntityEvent = (ActivitiEntityEventImpl) event;
        TaskEntity taskEntity = (TaskEntity) activitiEntityEvent.getEntity();
        System.out.println("taskEntity.getId() = " + taskEntity.getId());
        System.out.println("taskEntity.getName() = " + taskEntity.getName());
        System.out.println("taskEntity.getAssignee() = " + taskEntity.getAssignee());
        System.out.println("taskEntity.getIdentityLinks() = " + taskEntity.getIdentityLinks());
        System.out.println("taskEntity.getVariables() = " + taskEntity.getVariables());
    }
}

全局配置类

java">@Configuration
public class Activiti7Config {

    @Autowired
    private SpringProcessEngineConfiguration config;

    @PostConstruct
    public void springProcessEngineConfiguration() {
        // 设置自定义的全局事件监听器,其他配置方式就不需要配置了。
//        config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));
        // 开启日志监听,开启后对性能有影响 act_evt_log
        config.setEnableDatabaseEventLogging(true);
    }
}

测试流程

java">@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestActivityGlobalEventListener {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    private static final String PROCESS_INSTANCE_ID = "728bb780-3be6-11ee-b0a5-18c04dcd4aee";

    @Test
    public void deployProcess() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("processes/global-listener.bpmn20.xml")
                .deploy();
        System.out.println("deploy = " + deploy);
    }

    @Test
    public void startProcess() {
        // 添加全局监听器
        runtimeService.addEventListener(new MyGlobalEventListener(), ActivitiEventType.TASK_CREATED, ActivitiEventType.TASK_ASSIGNED, ActivitiEventType.TASK_COMPLETED);

        Map<String, Object> variables = new HashMap<>();
        variables.put("applyUserId", "user123456");
        variables.put("candidateUsers", CollectionUtil.newArrayList("zhangsan", "lisi", "wangwu"));
        variables.put("candidateGroups", CollectionUtil.newArrayList("group1", "group2", "group3"));

        String processDefinitionKey = "global-listener";
        String businessKey = processDefinitionKey + ":" + "100002";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
        System.out.println("processInstance = " + processInstance);

        // 输出当前任务列表
        this.printTaskList(processInstance.getId());
    }

    @Test
    public void completeTask() {
        // 查询任务
        Task task = taskService.createTaskQuery().processInstanceId(PROCESS_INSTANCE_ID).taskAssignee("user123456").singleResult();
        taskService.complete(task.getId());
    }

    private void printTaskList(String processInstanceId) {
        // 输出当前任务列表
        taskService.createTaskQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list().forEach(k -> {
            System.out.println("===================任务列表===================");
            System.out.println("任务ID = " + k.getId());
            System.out.println("任务名称 = " + k.getName());
            System.out.println("任务负责人 = " + k.getAssignee());
            System.out.println("任务创建时间 = " + k.getCreateTime());

            System.out.println("===================身份列表===================");
            // 输出用户身份关系列表
            taskService.getIdentityLinksForTask(k.getId()).forEach(link -> {
                System.out.println("link.getType() = " + link.getType());
                System.out.println("link.getUserId() = " + link.getUserId());
                System.out.println("link.getGroupId() = " + link.getGroupId());
                System.out.println("link.getTaskId() = " + link.getTaskId());
            });
        });
    }

}
部署流程

运行 deployProcess
在这里插入图片描述

启动流程

运行 startProcess,可以看到监听到任务节点1的创建和分配事件。
在这里插入图片描述


http://www.niftyadmin.cn/n/5147727.html

相关文章

BERT:来自 Transformers 的双向编码器表示 – 释放深度上下文化词嵌入的力量

BERT是Transformers 双向编码器表示的缩写,是 2018 年推出的改变游戏规则的 NLP 模型之一。BERT 的情感分类、文本摘要和问答功能使其看起来像是一站式 NLP 模型。尽管更新和更大的语言模型已经出现,但 BERT 仍然具有相关性,并且值得学习它的架构、方法和功能。 这篇综合文…

Doris常用语句

SWITCH mysql_report; SWITCH mysql_floweda; SWITCH mysql_base; SWITCH internal;select * from mysql_floweda.flow_eda.eda_flow;select * from mysql_report.cz_report.etl_flow; select * from mysql_report.cz_report.etl_flow_log;#外部数据物化视图 create materi…

Go 如何实现并发

Go语言的并发机制是其强大和流行的一个关键特性之一。Go使用协程&#xff08;goroutines&#xff09;和通道&#xff08;channels&#xff09;来实现并发编程&#xff0c;这使得编写高效且可维护的并发代码变得相对容易。下面是Go的并发机制的详细介绍&#xff1a; 协程&#x…

SAP ABAP基础语法-增强(五)

SAP有四种基本用户出口的类型&#xff1a; 1.菜单出口-Menu Exits 定义自己的菜单 2.屏幕出口-Screen Exits 定义自己的屏幕 3.功能模块出口-Function Module Exits 在SAP应用程序中添加功能 4.关键字出口-Keyword Exits 在ABAP/4字典中的关键字数据元素添加文档。结果是你…

KaiwuDB 内核解析 - SQL 查询的生命周期

一、概述 KaiwuDB 内核解析系列共分上下两部分&#xff0c;本文是该系列的第一部分&#xff0c;主要涵盖了网络协议到 SQL 执行器&#xff0c;解释 KaiwuDB 如何执行 SQL 查询&#xff0c;包括系统各个组件的执行路径&#xff08;网络协议、SQL 会话管理、解析器、执行计划及优…

rabbitmq的confirm模式获取correlationData为null解决办法

回调函数confirm中的correlationDatanull // 实现confirm回调,发送到和没发送到exchange,都触发 Override public void confirm(CorrelationData correlationData, boolean ack, String cause) {// 参数说明:// correlationData: 相关数据,可以在发送消息时,进行设置该参数// …

前端文件上传下载

一.文件下载 1.简要&#xff1a;文件下载分为两种情况。 &#xff08;1&#xff09;第一种是后台放在服务器上面&#xff0c;然后前端直接访问就可以下载&#xff0c;此种前端不需要做额外的处理&#xff0c;可以用 type为download的a标签直接访问下载&#xff0c;也可以用wi…

mysql8.0.30 sql_model启动不了

大部分人是NO_AUTO_CREATE_USER这个参数不能用&#xff0c;但是我的情况不一样 我的是NO_ENGINE_SUBSTITUTION这个参数不能使用