2023最新版本Activiti7系列-监听器讲解

news2024/10/1 1:26:36

在这里插入图片描述

监听器

1.执行监听器

  在流程实例执行过程中触发某个事件时,Activiti提供的执行监听器可以捕获该事件并执行相应的外部的Java代码,或者对指定的表达式求值。在流程实例执行过程中触发某个事件时,Activiti提供的执行监听器可以捕获该事件并执行相应的外部的Java代码,或者对指定的表达式求值。

  • start:开始事件
  • take:执行事件,只能在顺序流中
  • end:结束事件

具体通过案例来介绍

在这里插入图片描述

对应的执行监听器完成的生命周期:
在这里插入图片描述

然后在这个过程中我们可以配置监听器的方式:

  1. 直接配置class:需要配置实现了ExecutionListener接口的实现类型
  2. DelegateExpression:需要从Spring容器中获取实现了ExecutionListener接口的实现类
  3. Expression:需要从Spring中获取对应的bean对象及要调用的相关的方法

上面案例中完整的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="execution-listener1" name="execution-listener1" isExecutable="true">
    <documentation>execution-listener1</documentation>
    <startEvent id="start-el1" name="开始节点">
      <extensionElements>
        <activiti:executionListener event="start" class="com.boge.activiti.execution.ExecutionListener1">
          <activiti:field name="msg1">
            <activiti:string><![CDATA[boge666]]></activiti:string>
          </activiti:field>
          <activiti:field name="msg2">
            <activiti:expression><![CDATA[${msg2}]]></activiti:expression>
          </activiti:field>
        </activiti:executionListener>
        <activiti:executionListener event="end" class="com.boge.activiti.execution.ExecutionListener1">
          <activiti:field name="msg1">
            <activiti:string><![CDATA[boge-end]]></activiti:string>
          </activiti:field>
          <activiti:field name="msg2">
            <activiti:string><![CDATA[boge-msg2-end]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
      </extensionElements>
    </startEvent>
    <userTask id="sid-065D83B9-2D5A-4770-A1E8-A1D0A154DD86" name="用户节点1" activiti:assignee="s1">
      <extensionElements>
        <activiti:executionListener event="start" expression="${executionListener2.test1(execution)}"></activiti:executionListener>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <endEvent id="sid-C8D80560-62C9-44CE-AE7A-65235F11B7F6"></endEvent>
    <sequenceFlow id="sid-FF78808D-D503-4B50-9CB8-14079609F480" sourceRef="sid-C1F4513F-24AD-44A3-8596-B51E2815D604" targetRef="sid-C8D80560-62C9-44CE-AE7A-65235F11B7F6"></sequenceFlow>
    <userTask id="sid-C1F4513F-24AD-44A3-8596-B51E2815D604" name="用户节点2"></userTask>
    <sequenceFlow id="sid-157E09A5-8D4C-4D96-B938-EFC3863CE682" name="顺序流1" sourceRef="start-el1" targetRef="sid-065D83B9-2D5A-4770-A1E8-A1D0A154DD86"></sequenceFlow>
    <sequenceFlow id="sid-372284A1-CE05-4FCA-97C3-3DFB49B55CE6" name="顺序流2" sourceRef="sid-065D83B9-2D5A-4770-A1E8-A1D0A154DD86" targetRef="sid-C1F4513F-24AD-44A3-8596-B51E2815D604">
      <extensionElements>
        <activiti:executionListener event="take" delegateExpression="${executionListener3}"></activiti:executionListener>
      </extensionElements>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_execution-listener1">
    <bpmndi:BPMNPlane bpmnElement="execution-listener1" id="BPMNPlane_execution-listener1">
      <bpmndi:BPMNShape bpmnElement="start-el1" id="BPMNShape_start-el1">
        <omgdc:Bounds height="30.0" width="30.0" x="195.0" y="210.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-065D83B9-2D5A-4770-A1E8-A1D0A154DD86" id="BPMNShape_sid-065D83B9-2D5A-4770-A1E8-A1D0A154DD86">
        <omgdc:Bounds height="80.0" width="100.0" x="330.0" y="185.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-C8D80560-62C9-44CE-AE7A-65235F11B7F6" id="BPMNShape_sid-C8D80560-62C9-44CE-AE7A-65235F11B7F6">
        <omgdc:Bounds height="28.0" width="28.0" x="690.0" y="211.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-C1F4513F-24AD-44A3-8596-B51E2815D604" id="BPMNShape_sid-C1F4513F-24AD-44A3-8596-B51E2815D604">
        <omgdc:Bounds height="80.0" width="100.0" x="510.0" y="185.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-FF78808D-D503-4B50-9CB8-14079609F480" id="BPMNEdge_sid-FF78808D-D503-4B50-9CB8-14079609F480">
        <omgdi:waypoint x="610.0" y="225.0"></omgdi:waypoint>
        <omgdi:waypoint x="690.0" y="225.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-157E09A5-8D4C-4D96-B938-EFC3863CE682" id="BPMNEdge_sid-157E09A5-8D4C-4D96-B938-EFC3863CE682">
        <omgdi:waypoint x="225.0" y="225.0"></omgdi:waypoint>
        <omgdi:waypoint x="330.0" y="225.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-372284A1-CE05-4FCA-97C3-3DFB49B55CE6" id="BPMNEdge_sid-372284A1-CE05-4FCA-97C3-3DFB49B55CE6">
        <omgdi:waypoint x="430.0" y="225.0"></omgdi:waypoint>
        <omgdi:waypoint x="510.0" y="225.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

对应的监听器的处理类:

/**
 * 执行监听器
 *   需要实现 ExecutionListener 接口
 */
public class ExecutionListener1 implements ExecutionListener {

    @Setter
    private Expression msg1;
    @Setter
    private Expression msg2;

    @Override
    public void notify(DelegateExecution execution) {
        System.out.println("------ExecutionListener1  开始-------------");
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement.getName() = " + currentFlowElement.getName());
        String currentActivityId = execution.getCurrentActivityId();
        System.out.println("currentActivityId = " + currentActivityId);
        String eventName = execution.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println(msg1.getValue(execution));
        System.out.println(msg2.getValue(execution));
        System.out.println("------ExecutionListener1  结束-------------");
    }
}
@Component
public class ExecutionListener2 {



    public void test1(DelegateExecution execution){
        System.out.println("------ExecutionListener2  开始-------------");
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement.getName() = " + currentFlowElement.getName());
        String currentActivityId = execution.getCurrentActivityId();
        System.out.println("currentActivityId = " + currentActivityId);
        String eventName = execution.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println("------ExecutionListener2  结束-------------");
    }
}
@Component
public class ExecutionListener3 implements ExecutionListener {

    @Override
    public void notify(DelegateExecution execution) {
        System.out.println("------ExecutionListener3  开始-------------");
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        System.out.println("currentFlowElement.getName() = " + currentFlowElement.getName());
        String currentActivityId = execution.getCurrentActivityId();
        System.out.println("currentActivityId = " + currentActivityId);
        String eventName = execution.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println("------ExecutionListener3  结束-------------");
    }
}

2.任务监听器

  任务监听器(Task Listener)是Activiti7中的一个重要概念,用于在任务生命周期中执行特定的操作。任务监听器可以在任务创建任务分配任务完成等事件发生时触发,从而执行相应的逻辑。

 任务监听器可以用于执行各种操作,例如记录任务日志发送通知更新任务状态等。通过在任务监听器中编写逻辑,可以实现对任务生命周期的全面控制和管理。

  任务监听器只能在用户任务节点上配置。可被任务监听器捕获的任务相关事件类型包括以下几种。

  • create:任务创建事件,发生在任务创建后,所有属性被设置时。
  • assignment:任务指派事件,发生在将任务指派给某人时。需要注意的是,该事件在任务创建事件前执行。
  • complete:任务完成事件,发生在任务完成时,即任务数据从执行数据表删除之前。
  • delete:任务删除事件,发生在任务完成时,即任务数据从执行数据表删除之前。

具体的案例讲解:

在这里插入图片描述

我们可以通过3中方式来配置任务监听器:

在这里插入图片描述

分别是:

  • class属性配置
  • expression属性配置
  • delegateExpression属性配置

我们分别定义这三种类型的Class,分别如下:

public class MyTaskListener1 implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("MyTaskListener1-----------开始了");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        System.out.println("taskDefinitionKey = " + taskDefinitionKey);
        String eventName = delegateTask.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println("MyTaskListener1-----------结束了");
    }
}

@Component
public class MyTaskListener2 {

    public void test1(DelegateTask delegateTask){
        System.out.println("MyTaskListener2-----------开始了");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        System.out.println("taskDefinitionKey = " + taskDefinitionKey);
        String eventName = delegateTask.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println("MyTaskListener2-----------结束了");
    }
}

@Component
public class MyTaskListener3 implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("MyTaskListener3-----------开始了");
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        System.out.println("taskDefinitionKey = " + taskDefinitionKey);
        String eventName = delegateTask.getEventName();
        System.out.println("eventName = " + eventName);
        System.out.println("MyTaskListener3-----------结束了");
    }
}

然后再做相关的配置了

在这里插入图片描述

我们在一个用户任务上配置了4个TaskListener.然后部署运行看看具体的效果,启动流程的时候触发了assignmentcreate事件,而且审批人指派是在前面执行的

MyTaskListener2-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = assignment
MyTaskListener2-----------结束了
MyTaskListener1-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = create
MyTaskListener1-----------结束了

然后做用户节点的审批操作,completedelete事件执行了。

MyTaskListener3-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = complete
MyTaskListener3-----------结束了
MyTaskListener1-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = delete
MyTaskListener1-----------结束了

完整的流程图信息:

<?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="test111" name="test111" isExecutable="true">
    <documentation>test111</documentation>
    <startEvent id="startEvent1"></startEvent>
    <userTask id="sid-4449755D-AC66-41B5-AC4E-68012BE95880" name="用户任务" activiti:assignee="${user1}">
      <extensionElements>
        <activiti:taskListener event="create" class="com.boge.activiti.listener.MyTaskListener1"></activiti:taskListener>
        <activiti:taskListener event="assignment" expression="${myTaskListener2.test1(task)}"></activiti:taskListener>
        <activiti:taskListener event="complete" delegateExpression="${myTaskListener3}"></activiti:taskListener>
        <activiti:taskListener event="delete" class="com.boge.activiti.listener.MyTaskListener1"></activiti:taskListener>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-07C5D7FE-48DA-4A7E-9F96-A716EB4DC825" sourceRef="startEvent1" targetRef="sid-4449755D-AC66-41B5-AC4E-68012BE95880"></sequenceFlow>
    <endEvent id="sid-3DB05158-BBE1-44FC-902B-368FBD3C5E71"></endEvent>
    <sequenceFlow id="sid-257B3F54-79C6-41A3-9CE3-103A33697253" sourceRef="sid-4449755D-AC66-41B5-AC4E-68012BE95880" targetRef="sid-3DB05158-BBE1-44FC-902B-368FBD3C5E71"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_test111">
    <bpmndi:BPMNPlane bpmnElement="test111" id="BPMNPlane_test111">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="300.0" y="160.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-4449755D-AC66-41B5-AC4E-68012BE95880" id="BPMNShape_sid-4449755D-AC66-41B5-AC4E-68012BE95880">
        <omgdc:Bounds height="80.0" width="100.0" x="375.0" y="135.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-3DB05158-BBE1-44FC-902B-368FBD3C5E71" id="BPMNShape_sid-3DB05158-BBE1-44FC-902B-368FBD3C5E71">
        <omgdc:Bounds height="28.0" width="28.0" x="520.0" y="161.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-257B3F54-79C6-41A3-9CE3-103A33697253" id="BPMNEdge_sid-257B3F54-79C6-41A3-9CE3-103A33697253">
        <omgdi:waypoint x="475.0" y="175.0"></omgdi:waypoint>
        <omgdi:waypoint x="520.0" y="175.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-07C5D7FE-48DA-4A7E-9F96-A716EB4DC825" id="BPMNEdge_sid-07C5D7FE-48DA-4A7E-9F96-A716EB4DC825">
        <omgdi:waypoint x="330.0" y="175.0"></omgdi:waypoint>
        <omgdi:waypoint x="375.0" y="175.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

3.全局事件监听器

  咱们上面详细介绍了执行监听器任务监听器,他们可以捕获流程在运转过程中产生的相关事件,但是是需要给特定的流程和对应的节点来绑定相关的监听器,有特殊性在这里。在Activiti中还给我们提供了全局事件监听器,它是引擎范围的事件监听器,可以捕获所有的Activiti事件。

3.1 事件监听器的实现

  首先我们来看下针对事件监听器的实现类如何来定义。具体的定义如下,只需实现ActivitiEventListener的接口即可。

public class MyGlobalEventListener implements ActivitiEventListener {

    /**
     * 事件触发执行的方法
     * @param event
     */
    @Override
    public void onEvent(ActivitiEvent event) {
        System.out.println("---全局事件监听器---"+event.getType().toString());
        if (event instanceof TaskRuntimeEvent) {
            TaskRuntimeEvent taskEvent = (TaskRuntimeEvent) event;
            if (event instanceof TaskCreatedEventImpl) {
                // 处理任务创建事件
                System.out.println("Task created: " + taskEvent);
            } else if (event instanceof TaskAssignedEvent) {
                // 处理任务分配事件
                System.out.println("Task assigned: " + taskEvent);
            } else if (event instanceof TaskCompletedEvent) {
                // 处理任务完成事件
                System.out.println("Task completed: " + taskEvent);
            } else if (event instanceof TaskCancelledEvent) {
                // 处理任务取消事件
                System.out.println("Task cancelled: " + taskEvent);
            } else if (event instanceof TaskSuspendedEvent) {
                // 处理任务挂起事件
                System.out.println("Task suspended: " + taskEvent);
            }
        }
    }

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

在自定义的监听器实现类中我们需要重写如下的两个方法:

  • onEvent:事件触发执行的方法
  • isFailOnException:上面的 onEvent 方法抛出异常的后续处理动作,false :表示忽略onEvent()方法方法中抛出的异常,true :表示onEvent()方法中抛出的异常继续向上传播,导致当前操作失败

3.2 配置事件监听器

  全局监听器的配置有三种方式在工作流引擎配置文件中配置在流程定义文件中配置在代码中调用API动态添加

在工作流引擎配置文件中配置

  我们可以在Activiti7的配置文件中来注册我们上面定义的事件监听器

<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti7?nullCatalogMeansCurrent=true" />
    <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
    <property name="jdbcUsername" value="root" />
    <property name="jdbcPassword" value="123456" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="asyncExecutorActivate" value="true" />
    <property name="mailServerHost" value="mail.my-corp.com" />
    <property name="mailServerPort" value="5025" />
    <property name="eventListeners">
        <list>
            <bean class="com.boge.activiti.listener.MyGlobalEventListener"></bean>
        </list>
    </property>
</bean>

上面我们通过eventListeners这个属性来配置全局的事件监听器,他会监听所有的事件,如果我们想要监听特定的事件,可以通过typedEventListeners这个属性来配置

<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti7?nullCatalogMeansCurrent=true" />
    <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
    <property name="jdbcUsername" value="root" />
    <property name="jdbcPassword" value="123456" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="asyncExecutorActivate" value="true" />
    <property name="mailServerHost" value="mail.my-corp.com" />
    <property name="mailServerPort" value="5025" />
    <property name="typedEventListeners">
        <map>
            <entry key="TASK_CREATED,TASK_COMPLETED">
                <list>
                    <bean class="com.boge.activiti.listener.MyGlobalEventListener"></bean>
                </list>
            </entry>
        </map>
    </property>
</bean>

上面的这个配置就只监听TASK_CREATEDTASK_COMPLETED事件,注意多个事件类型通过,连接。当然我们现在都是在SpringBoot项目中来做项目开发。这块我们的配置需要在配置类中完成。具体如下:

@Configuration
public class Activiti7Config {

    @Autowired
    SpringProcessEngineConfiguration config;

    @PostConstruct
    public void springProcessEngineConfiguration() {
        // 设置自定义的全局事件监听器
        config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));
    }
}

指派具体的事件类型

@Configuration
public class Activiti7Config {

    @Autowired
    SpringProcessEngineConfiguration config;

    @PostConstruct
    public void springProcessEngineConfiguration() {
        // 设置自定义的全局事件监听器
        Map<String, List<ActivitiEventListener>> map = new HashMap<>();
        map.put("TASK_CREATED", Arrays.asList(new MyGlobalEventListener()));
        config.setTypedEventListeners(map);
    }
}

然后我们可以启动前面案例中部署的任务监听器的流程。先看没有指定具体事件类型的日志输出

---全局事件监听器---ENTITY_CREATED
---全局事件监听器---HISTORIC_PROCESS_INSTANCE_CREATED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---VARIABLE_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---PROCESS_STARTED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---HISTORIC_ACTIVITY_INSTANCE_CREATED
---全局事件监听器---ACTIVITY_STARTED
---全局事件监听器---HISTORIC_ACTIVITY_INSTANCE_ENDED
---全局事件监听器---ACTIVITY_COMPLETED
---全局事件监听器---SEQUENCEFLOW_TAKEN
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---HISTORIC_ACTIVITY_INSTANCE_CREATED
---全局事件监听器---ACTIVITY_STARTED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
---全局事件监听器---VARIABLE_CREATED
MyTaskListener2-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = assignment
MyTaskListener2-----------结束了
---全局事件监听器---ENTITY_CREATED
---全局事件监听器---ENTITY_INITIALIZED
MyTaskListener1-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = create
MyTaskListener1-----------结束了
---全局事件监听器---TASK_CREATED
---全局事件监听器---TASK_ASSIGNED

然后是特定事件类型的全局监听器的执行,日志输入如下:

MyTaskListener2-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = assignment
MyTaskListener2-----------结束了
MyTaskListener1-----------开始了
taskDefinitionKey = sid-4449755D-AC66-41B5-AC4E-68012BE95880
eventName = create
MyTaskListener1-----------结束了
---全局事件监听器---TASK_CREATED

通过流程定义文件配置事件监听器

  当然我们还可以在流程定义中配置事件监听器,不过这种方式配置的事件监听器只能监听于该流程相关的事件以及该流程定义上发起的所有流程实例的事件,具体如下:

在这里插入图片描述

  在设计器中点击空白地方有个Event Listeners。可以通过这个功能来设置。但是通过流程设计器在这块配置的时候不是很灵活。我们可以基于BPMN的规范直接在流程图的xml中配置,监听器的配置可以使用3中方式来处理。

  • 通过class属性进行全类名定义;
  • 通过delegateExpression属性引用实现了监听器接口的表达式;
  • 使用throwEvent属性及其额外属性指定抛出的BPMN事件类型。
<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="test111" name="test111" isExecutable="true">
    <documentation>test111</documentation>
    <extensionElements>
      <!-- 通过class属性来配置事件监听器 -->
      <activiti:eventListener class="com.boge.activiti.listener.MyGlobalEventListener" entityType="task">		
      </activiti:eventListener>
      <activiti:eventListener  delegateExpression="${myGlobalEventListener2}"
                              ></activiti:eventListener>
    </extensionElements>
      <!-- .... 省略 -->
    </process>
</definitions>

在流程运转过程中会有相关的各种信号错误消息等抛出的BPMN事件。在全局事件监听器的配置中我们可以在对应的事件触发的情况下向外抛出相关的事件动作。比如:

<extensionElements>
  <!-- 配置抛出的信号事件 -->
  <activiti:eventListener throwEvent="signal" signalName="MySignal1" events="TASK_CREATED"></activiti:eventListener>
</extensionElements>

上面xml中的相关属性的作用:

  • events: TASK_CREATED 表示监听Task的创建事件
  • throwEvent:signal 表示当触发 task的创建事件后会向外抛出信号事件
  • signalName:MySignal1 表示抛出的事件名称

具体的案例为:

在这里插入图片描述

在这里throwEvent可以抛出的类型有:

  • signal:普通信号
  • GlobalSignal:全局信号
  • error:错误
  • message:消息

当然这块也可以和我们前面配置的class 一块使用如下:

<extensionElements>
  <!-- 通过class属性来配置事件监听器 -->
  <activiti:eventListener throwEvent="signal" class="com.boge.activiti.listener.MyGlobalEventListener" signalName="signal1" events="TASK_CREATED"></activiti:eventListener>
</extensionElements>

这个流程定义表示的是即会抛出相关的信号。同时也会在events事件发生的时候触发对应的class中的监听器来处理。

在代码中调用API动态添加

  前面都是我们需要在启动服务之前就要配置好,非常的不灵活。在流程部署和运行后如果需要添加相关的事件监听器。这时可以通过RuntimeService中提供的addEventListener()方法来实现监听器的注册操作。

在这里插入图片描述

注意:流程引擎重启后相关的监听器会消失!!!

3.3 日志监听器

  如果我们需要把全局事件监听器的信息持久化到数据库中。也就是保存在act_evt_log表中。那么我们可以通过设置enableDatabaseEventLogging属性来开启。

@Configuration
public class Activiti7Config {

    @Autowired
    SpringProcessEngineConfiguration config;

    @PostConstruct
    public void springProcessEngineConfiguration() {
        // 设置自定义的全局事件监听器
        config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));
        // 开启日志监听
        config.setEnableDatabaseEventLogging(true);
    }
}

然后在act_evt_log中会记录相关的信息

在这里插入图片描述

当然我们也可以禁用掉全局事件监听器。毕竟这块对性能的影响还是比较大的。

@Configuration
public class Activiti7Config {

    @Autowired
    SpringProcessEngineConfiguration config;

    @PostConstruct
    public void springProcessEngineConfiguration() {
        // 设置自定义的全局事件监听器
        config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));
        // 禁用 全局事件监听器
        config.setEnableEventDispatcher(false);
    }
}

这块的禁用仅仅是禁用了全局事件监听器,对执行监听器任务监听器是没有影响的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/836858.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《动手学深度学习》-67自注意力

沐神版《动手学深度学习》学习笔记&#xff0c;记录学习过程&#xff0c;详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 自注意力 在深度学习中&#xff0c;经常使用卷积神经网络&#xff08;CNN&#xff09;或循环神经网络&#xff08;RNN&#xff09;对序列进行…

【暑期每日一练】 day14

目录 选择题 &#xff08;1&#xff09; 解析&#xff1a; &#xff08;2&#xff09; 解析&#xff1a; &#xff08;3&#xff09; 解析&#xff1a; &#xff08;4&#xff09; 解析&#xff1a; &#xff08;5&#xff09; 解析&#xff1a; 编程题 题一 …

全球十大知名看黄金即时行情的软件名单(综合榜单)

在当今的数字化时代&#xff0c;黄金投资已成为一种受欢迎的投资方式。为了获取即时的黄金行情信息&#xff0c;许多投资者开始使用黄金即时行情软件。然而&#xff0c;选择一款合适的软件并不是一件容易的事情。那么&#xff0c;如何选适合自己需求的软件呢&#xff1f;首先&a…

Hyper实现git bash在windows环境下多tab窗口显示

1.电脑上安装有git bash 下载链接&#xff1a;https://gitforwindows.org/ 安装Hyper 下载链接:官网 https://hyper.is/ 或者在百度云盘下载&#xff1a; https://pan.baidu.com/s/1BVjzlK0s4SgAbQgsiK1Eow 提取码&#xff1a;0r1f 设置 打开Hyper&#xff0c;依次点左上角-&g…

Arduino驱动MQ5模拟煤气气体传感器(气体传感器篇)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 MQ5气体传感器,可以很灵敏的检测到空气中的液化气、天然气、煤气等气体,与Arduino结合使用,可以制作火灾液化气、天然气、煤气泄露报警等相关的作品。 1、传感器特性 MQ5用于消费和工业行业中气体泄漏检测设备,该传感器适…

【网络】DNS、ICMP、NAT

目录 一、DNS(Domain Name System) 1、DNS背景 2、域名简介 二、ICMP协议 1、ICMP功能 2、ICMP的报文格式 3、ping命令 4、traceroute命令 三、NAT技术 1、NAT技术背景 2、NAT IP转换过程 3、NAPT 4、NAT技术的缺陷 5、NAT和代理服务器 一、DNS(Domain Name Syste…

分布式应用:Zookeeper 集群与kafka 集群部署

目录 一、理论 1.Zookeeper 2.部署 Zookeeper 集群 3.消息队列 4.Kafka 5.部署 kafka 集群 6.FilebeatKafkaELK 二、实验 1.Zookeeper 集群部署​​​​​​​ 2.kafka集群部署 3.FilebeatKafkaELK 三、问题 1.解压文件异常 2.kafka集群建立失败 3.启动 filebeat报…

中国信通院发布《高质量数字化转型产品及服务全景图(2023)》

2023年7月27日&#xff0c;由中国信息通信研究院主办的2023数字生态发展大会暨中国信通院铸基计划年中会议在北京成功召开。 本次大会发布了中国信通院《高质量数字化转型产品及服务全景图&#xff08;2023&#xff09;》&#xff0c;中新赛克海睿思受邀出席本次大会并成功入选…

HarmonyOS应用开发者基础与高级认证题库——中级篇

系列文章目录 HarmonyOS应用开发者基础与高级认证题库——基础篇 HarmonyOS应用开发者基础与高级认证题库——中级篇 文章目录 系列文章目录前言一、判断二、单选三、多选 前言 今天刚换了台果子手机就收到了华子鸿蒙开发认证邀请&#xff08;认证链接&#xff09;&#xff0…

2020年江西省职业院校技能大赛高职组“信息安全管理与评估”赛项任务书

2020年江西省职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书 赛项时间 9:00-12:00&#xff0c;共计3小时。 赛项信息 赛项内容 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 任务1 网络平台搭建 9:00-12:00 100 任务…

2023下半年软考初级程序员报名入口-报名流程-备考方法

软考初级程序员2023下半年考试时间&#xff1a; 2023年下半年软考初级程序员的考试时间为11月4日、5日。考试时间在全国各地一致&#xff0c;建议考生提前备考。共分两科&#xff0c;第一科基础知识考试具体时间为9:00到11:30&#xff1b;第二科应用技术考试具体时间为2:00到4…

【C++刷题集】-- day5

目录 选择题 单选 编程题 统计回文⭐ 【题目解析】 【解题思路 - 穷举】 【优化】 连续最大和⭐ 【题目解析】 【解题思路】 【空间优化】 选择题 单选 1、 在上下文和头文件均正常情况下&#xff0c;以下程序的输出结果是 ( ) int x 1; do {printf("%2d\n&q…

Python批量查字典和双语例句

最近&#xff0c;有网友反映&#xff0c;我的批量查字典工具换到其它的网站就不好用了。对此&#xff0c;我想说的是&#xff0c;互联网包罗万象&#xff0c;网站的各种设置也有所不同&#xff0c;并不是所有的在线字典都可以用Python爬取的。事实上&#xff0c;很多网站为了防…

Python入门自学进阶-Web框架——38、redis、rabbitmq、git

缓存数据库redis&#xff1a; NoSQL&#xff08;Not only SQL&#xff09;泛指非关系型的数据库。为了解决大规模数据集合多重数据类的挑战。 NoSQL数据库的四大分类&#xff1a; 键值&#xff08;Key-Value&#xff09;存储数据库列存储数据库文档型数据库图形&#xff08;…

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字

一、&#x1f49b;并发基本概念 并发的基本意思&#xff1a; 什么是并发呢&#xff1f;简单的理解就是同一时间执行 服务器同一时刻&#xff0c;给多个客户端提供服务&#xff5e;&#xff5e;&#xff0c;这两个客户端都可以给服务器提交事务。 如果提交两个事务&#xff0c;改…

召唤神龙打造自己的ChatGPT

在之前的两篇文章中&#xff0c;我介绍了GPT 1和2的模型&#xff0c;并分别用Tensorflow和Pytorch来实现了模型的训练。具体可以见以下文章链接&#xff1a; 1. 基于Tensorflow来重现GPT v1模型_gzroy的博客-CSDN博客 2. 花费7元训练自己的GPT 2模型_gzroy的博客-CSDN博客 有…

C++STL——map/multimap容器详解

纵有疾风起&#xff0c;人生不言弃。本文篇幅较长&#xff0c;如有错误请不吝赐教&#xff0c;感谢支持。 &#x1f4ac;文章目录 一.对组&#xff08;pair&#xff09;二.map/multimap基本概念三.map容器常用操作①map构造函数②map迭代器获取③map赋值操作④map大小操作⑤map…

突破视觉边界:深入探索AI图像识别的现状与挑战

图像识别作为人工智能领域的一个重要研究方向&#xff0c;取得了许多令人瞩目的成就。深入探索当前AI图像识别技术的现状以及所面临的挑战&#xff0c;讨论各种方法的优势和局限性。 目录 引言1.1 AI图像识别的背景和概述1.2 人工智能在图像识别中的应用和重要性 图像识别基础知…

RISC-V基础指令之逻辑指令 and、or、xor、not

RISC-V的逻辑指令是用于对两个寄存器或一个寄存器和一个立即数进行按位的逻辑运算&#xff0c;并将结果存放在另一个寄存器中的指令。按位的逻辑运算就是把两个操作数的每一位分别进行相应的逻辑运算&#xff0c;得到一个新的位。RISC-V的逻辑指令有以下几种&#xff1a; and&…

c++高性能多进程 cuda编程:GPU结构和通信速度+tiling的代码实现

根据c高性能多进程 cuda编程:GPU结构和通信速度tiling的分析&#xff0c;依靠pytorch的JIT进行了实现&#xff0c;所以在安装pytorch的环境中&#xff0c;直接执行test.py就能直接运行。 代码结构如下&#xff0c;地址 mm.h void function_mm(float *c,const float *a,cons…