Activiti之任务监听器与执行监听器详解

关于任务监听器与执行监听器

在 Activiti 工作流引擎中,任务监听器(Task Listener)和执行监听器(Execution Listener)是两种常用的监听器类型,用于在流程的不同阶段添加自定义逻辑。它们可以在流程定义中配置,以便在特定事件发生时触发预定义的操作。比如,动态分配节点处理人。通过前一个节点设置的变量,在运行到下一个节点时设置对应的处理人; 当流程运行到某个节点时,发送邮件或短信给待办用户;统计流程处理时长,是否超时等;业务层面数据处理。

任务监听器

任务监听器是一种允许你在任务生命周期内的不同事件上执行操作的机制。每当一个与任务相关的事件发生时,任务监听器可以被触发,以便在任务开始、分配、完成等阶段执行特定的逻辑。

activiti的源码中,任务监听器事件包括:

  • create:在任务被创建时触发。
  • assignment:在任务被分配给用户或组时触发。
  • complete:在任务完成时触发。
  • delete:经测试会在任务完成时触发。

可以通过配置任务监听器来执行以下类型的操作:

  • 分配任务给特定用户或用户组。
  • 更新任务属性,如优先级、截止日期等。
  • 发送邮件,短信,OA消息通知等。

在 Activiti 中,可以通过以下方式配置任务监听器:

xml 复制代码
<userTask id="testListener" name="办理节点" activiti:assignee="zhangsan" activiti:candidateUsers="lisi">
      <extensionElements>
        <activiti:taskListener event="create" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>
        <activiti:taskListener event="assignment" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>
        <activiti:taskListener event="complete" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>
        <activiti:taskListener event="delete" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>
      </extensionElements>
    </userTask>

实现自定义任务监听的代码如下:

java 复制代码
package com.test.activiti.activiti.listener;

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateTask;
import org.springframework.stereotype.Service;

/**
 * 测试任务监听器
 * @Author dzf62
 * @Description TODO
 * @Date 2023/8/11 18:30
 * @Version 1.0
 */
@Slf4j
@Service
public class TaskListener implements org.activiti.engine.delegate.TaskListener {



    @Override
    public void notify(DelegateTask delegateTask) {
        String eventName = delegateTask.getEventName();
        switch (eventName){
            case EVENTNAME_CREATE:
                create(delegateTask);
                break;
            case EVENTNAME_ASSIGNMENT:
                assigment(delegateTask);
                break;
            case EVENTNAME_COMPLETE:
                complete(delegateTask);
                break;
            case EVENTNAME_DELETE:
                delete(delegateTask);
                break;
            default:
                break;
        }
    }


    public void create(DelegateTask delegateTask){
        System.out.println("============TaskListener start============");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        String eventName = delegateTask.getEventName();
        System.out.println("事件名称:" + eventName);
        System.out.println("taskDefinitionKey:" + taskDefinitionKey);
        System.out.println("============TaskListener end============");

    }

    public void assigment(DelegateTask delegateTask){
        System.out.println("============TaskListener start============");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        String eventName = delegateTask.getEventName();
        System.out.println("事件名称:" + eventName);
        System.out.println("taskDefinitionKey:" + taskDefinitionKey);
        System.out.println("============TaskListener end============");
    }

    public void complete(DelegateTask delegateTask){
        System.out.println("============TaskListener start============");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        String eventName = delegateTask.getEventName();
        System.out.println("事件名称:" + eventName);
        System.out.println("taskDefinitionKey:" + taskDefinitionKey);
        System.out.println("============TaskListener end============");
    }


    public void delete(DelegateTask delegateTask){
        System.out.println("============TaskListener start============");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        String eventName = delegateTask.getEventName();
        System.out.println("事件名称:" + eventName);
        System.out.println("taskDefinitionKey:" + taskDefinitionKey);
        System.out.println("============TaskListener end============");
    }
}

执行监听器

执行监听器是一种允许你在流程实例的不同生命周期事件上执行操作的机制。与任务监听器类似,执行监听器在流程实例创建、开始、结束等事件发生时可以被触发。

activiti的源码中,执行监听器事件包括:

  • start:在流程实例启动时触发。
  • end:在流程实例结束时触发。
  • take:流程连线被执行时触发。

可以通过配置执行监听器来执行以下类型的操作:

  • 在流程实例启动时初始化数据或执行特定操作。
  • 在流程实例结束时进行清理操作或生成报告。

在 Activiti 中,可以通过以下方式配置执行监听器:

xml 复制代码
<userTask id="testListener" name="办理节点" activiti:assignee="zhangsan" activiti:candidateUsers="lisi">
      <extensionElements>
        <activiti:executionListener event="start" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>
        <activiti:executionListener event="end" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>
        <activiti:executionListener event="take" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>
      </extensionElements>
    </userTask>

实现自定义执行监听器代码如下:

java 复制代码
package com.test.activiti.activiti.listener;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;

/**
 * @Author dzf62
 * @Description TODO
 * @Date 2023/8/12 21:17
 * @Version 1.0
 */
public class ExecuteListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) throws Exception {
        String eventName = execution.getEventName();
        switch (eventName){
            case EVENTNAME_START:
                start(execution);
                break;
            case EVENTNAME_END:
                end(execution);
                break;
            case EVENTNAME_TAKE:
                take(execution);
                break;
            default:
                break;
        }
    }


    public void start(DelegateExecution execution){
        System.out.println("============executionListener start============");
        String eventName = execution.getEventName();
        String currentActivitiId = execution.getCurrentActivityId();
        System.out.println("事件名称:" + eventName);
        System.out.println("ActivitiId:" + currentActivitiId);
        System.out.println("============executionListener  end============");
    }

    public void end(DelegateExecution execution){
        System.out.println("============executionListener start============");
        String eventName = execution.getEventName();
        String currentActivitiId = execution.getCurrentActivityId();
        System.out.println("事件名称:" + eventName);
        System.out.println("ActivitiId:" + currentActivitiId);
        System.out.println("============executionListener  end============");
    }

    public void take(DelegateExecution execution){
        System.out.println("============executionListener start============");
        String eventName = execution.getEventName();
        String currentActivitiId = execution.getCurrentActivityId();
        System.out.println("事件名称:" + eventName);
        System.out.println("ActivitiId:" + currentActivitiId);
        System.out.println("============executionListener  end============");
    }
}

验证任务监听器与执行监听器的事件监听顺序

首先设计一个最简单的流程图,设计如下,使用原生的activiti的modeler,重点是添加任务监听器和执行监听器:

对应bpmn如下:

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="测试监听器流程" isExecutable="true">

    <startEvent id="start" name="开始"></startEvent>

    <userTask id="testListener" name="办理节点" activiti:assignee="zhangsan" activiti:candidateUsers="lisi">

      <extensionElements>

        <activiti:formProperty id="name" name="姓名" type="string" variable="张三"></activiti:formProperty>

        <activiti:executionListener event="start" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>

        <activiti:executionListener event="end" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>

        <activiti:executionListener event="take" class="com.test.activiti.activiti.listener.ExecuteListener"></activiti:executionListener>

        <activiti:taskListener event="create" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>

        <activiti:taskListener event="assignment" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>

        <activiti:taskListener event="complete" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>

        <activiti:taskListener event="delete" class="com.test.activiti.activiti.listener.TaskListener"></activiti:taskListener>

      </extensionElements>

    </userTask>

    <sequenceFlow id="sid-6BA47516-0661-4858-AC94-F075196FC8E8" sourceRef="start" targetRef="testListener"></sequenceFlow>

    <endEvent id="sid-2BCD59DB-320E-43FC-9BB4-0ACA61CCE7F0"></endEvent>

    <sequenceFlow id="sid-A38F12AC-7AA8-4BEF-9AC5-A5442C2A979D" sourceRef="testListener" targetRef="sid-2BCD59DB-320E-43FC-9BB4-0ACA61CCE7F0"></sequenceFlow>

  </process>

  <bpmndi:BPMNDiagram id="BPMNDiagram_测试监听器流程">

    <bpmndi:BPMNPlane bpmnElement="测试监听器流程" id="BPMNPlane_测试监听器流程">

      <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">

        <omgdc:Bounds height="30.0" width="30.0" x="74.99999841054293" y="314.9999933242803"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="testListener" id="BPMNShape_testListener">

        <omgdc:Bounds height="80.0" width="100.0" x="195.00000447697187" y="270.00000619888414"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNShape bpmnElement="sid-2BCD59DB-320E-43FC-9BB4-0ACA61CCE7F0" id="BPMNShape_sid-2BCD59DB-320E-43FC-9BB4-0ACA61CCE7F0">

        <omgdc:Bounds height="28.0" width="28.0" x="470.1110768748659" y="315.9999909698969"></omgdc:Bounds>

      </bpmndi:BPMNShape>

      <bpmndi:BPMNEdge bpmnElement="sid-6BA47516-0661-4858-AC94-F075196FC8E8" id="BPMNEdge_sid-6BA47516-0661-4858-AC94-F075196FC8E8">

        <omgdi:waypoint x="104.8766665764206" y="328.0804245491744"></omgdi:waypoint>

        <omgdi:waypoint x="195.00000447697187" y="316.45161469650725"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

      <bpmndi:BPMNEdge bpmnElement="sid-A38F12AC-7AA8-4BEF-9AC5-A5442C2A979D" id="BPMNEdge_sid-A38F12AC-7AA8-4BEF-9AC5-A5442C2A979D">

        <omgdi:waypoint x="295.00000447697187" y="314.1821598253234"></omgdi:waypoint>

        <omgdi:waypoint x="470.15979454088495" y="328.8330628497661"></omgdi:waypoint>

      </bpmndi:BPMNEdge>

    </bpmndi:BPMNPlane>

  </bpmndi:BPMNDiagram>

</definitions>

在测试任务监听器与执行监听器的执行顺序时,我们对该用户任务节点的任务监听器和执行监听器都添加了所有的监听事件,接下来只需要在启动流程和办理第一个节点的任务,查看打印的内容就可以看出任务监听器和执行监听器各个事件监听的触发时机

首先,启动流程时的打印日志如下:

js 复制代码
============executionListener start============

事件名称:start

ActivitiId:testListener

============executionListener  end============

============TaskListener start============

事件名称:assignment

taskDefinitionKey:testListener

============TaskListener end============

============TaskListener start============

事件名称:create

taskDefinitionKey:testListener

============TaskListener end============

说明流程在到达用户任务节点时,任务监听器的事件监听顺序如下:assignment->create;而执行监听器只会触发start事件

然后,办理该用户任务时,打印日志如下:

js 复制代码
============TaskListener start============

事件名称:complete

taskDefinitionKey:testListener

============TaskListener end============

============TaskListener start============

事件名称:delete

taskDefinitionKey:testListener

============TaskListener end============

============executionListener start============

事件名称:end

ActivitiId:testListener

============executionListener  end============

任务监听器的事件监听顺序如下:complete->delete;执行监听器只触发了end事件

相关推荐
小白不太白9504 分钟前
设计模式之 迭代器模式
java·设计模式·迭代器模式
闲人一枚(学习中)6 分钟前
设计模式-创建型-单例模式
java·单例模式·设计模式
Coderfuu18 分钟前
Java技术复习提升 10异常
java·开发语言
愿天垂怜24 分钟前
【C++】C++11引入的新特性(1)
java·c语言·数据结构·c++·算法·rust·哈希算法
CoderJia程序员甲25 分钟前
重学SpringBoot3-Spring Retry实践
java·spring boot·spring·retry·重试机制
淡写青春20929 分钟前
计算机基础---进程间通信和线程间通信的方式
java·开发语言·数据结构
mit6.82429 分钟前
[Redis#4] string | 常用命令 | + mysql use:cache | session
数据库·redis·后端·缓存
《源码好优多》33 分钟前
基于Java Springboot未央商城管理系统
java·开发语言·spring boot
^Lim38 分钟前
esp32 JTAG 串口 bootload升级
java·linux·网络
江-小北42 分钟前
Java基础面试题04:Iterator 和 ListIterator 的区别是什么?
java·开发语言