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

在这里插入图片描述

监听器

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 {@Setterprivate Expression msg1;@Setterprivate Expression msg2;@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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*/@Overridepublic 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()方法中抛出的异常继续向上传播,导致当前操作失败*/@Overridepublic 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 {@AutowiredSpringProcessEngineConfiguration config;@PostConstructpublic void springProcessEngineConfiguration() {// 设置自定义的全局事件监听器config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));}
}

指派具体的事件类型

@Configuration
public class Activiti7Config {@AutowiredSpringProcessEngineConfiguration config;@PostConstructpublic 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 {@AutowiredSpringProcessEngineConfiguration config;@PostConstructpublic void springProcessEngineConfiguration() {// 设置自定义的全局事件监听器config.setEventListeners(Collections.singletonList(new MyGlobalEventListener()));// 开启日志监听config.setEnableDatabaseEventLogging(true);}
}

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

在这里插入图片描述

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

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

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

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

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

相关文章

8.4作业

用信号量的方式实现打印1234567后打印7654321循环交替打印。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<head.h> char buf[]"1234567"; sem_t sem; void *callBack1(void *arg) {int i0;int sstrlen(buf)-1;while…

el-cascader级联选择器加载远程数据、默认开始加载固定条、可以根据搜索加载远程数据。

加载用户列表分页请求、默认请求20条数据。想添加远程搜索用户功能。原有的方法filter-method不能监听到输入清空数据的时候。这样搜索完无法返回默认的20条数据。直接监听级联选择的v-model绑定的值是无法检测到用户自己输入的。 解决思路&#xff1a; el-cascader 没有提供…

list交并补差集合

list交并补差集合 工具类依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version> </dependency><dependency><groupId>commons-collections&…

二叉树的遍历(先序遍历,中序遍历,后序遍历)递归与非递归算法

目录 一、先序遍历题目链接1.递归2.非递归 二、中序遍历题目链接1.递归2.非递归 三、后序遍历题目链接1.递归2.非递归 一、先序遍历 先序遍历&#xff1a;先遍历一颗树的根节点&#xff0c;后遍历左子树&#xff0c;最后遍历右子树 先序遍历序列&#xff1a; 1 -> 2 -> 4…

Linux常用命令

1 查找命令 grep命令 命令是一种强大的文本搜索工具 格式&#xff1a; grep [option] pattern [file] 可使用 —help 查看更多参数。 使用实例&#xff1a; ps -ef | grep sshd 查找指定 ssh 服务进程 ps -ef | grep sshd | grep -v grep 查找指定服务进程&#xff0c;排除…

采用 SpringDoc、javadoc 无注解零入侵基于java注释

今天在gitee上学习到一个&#xff0c;个人觉得非常使用的功能。就是采用 SpringDoc、javadoc 无注解零入侵基于java注释&#xff0c;只需把注释写好 无需再写一大堆的文档注解了。 下面是源码的地址 RuoYi-Vue-Plus: 后台管理系统 重写RuoYi-Vue所有功能 集成 Sa-TokenMybati…

LeetCode 27题:移除元素

题目 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长…

攻防世界-reverse-logmein

题目描述&#xff1a;菜鸡开始接触一些基本的算法逆向了 下载附件&#xff0c;是一个可执行程序 1. 思路分析 逆向出来看看代码 从代码中来看&#xff0c;密码长度需要和V8相等&#xff0c;并且每一个字符的运算结果需要满足 s[i] (char)(v8[i % v6 - 8] ^ v8[i]) 但是这…

libtorch::Tensor与Eigen::Tensor互相转换

1. Eigen::Tensor转libtorch::Tensor Eigen::Tensor<float, 3> a{2,4,3};a.setRandom();a(1,2,1) 11.0;/*核心*/torch::Tensor b torch::from_blob(a.data(), {1, a.dimension(2), a.dimension(1), a.dimension(0)});/*核心*/b b.permute({0, 3, 2, 1});std::cout <…

vue2、vue3生命周期详解以及对比

文章目录 对比vue2-vue3vue3生命周期生命周期的主要阶段详情 vue2 生命周期生命周期钩子函数 总共11个 常用的8个按照这四个阶段我们对应有八个生命周期钩子函数vue生命周期使用场景 对比vue2-vue3 如果熟悉vue2的话&#xff0c;vue3信手拈来&#xff0c;看图 vue3生命周期 on…

impala使用md5(3条命令搞定)

文章目录 前言1、 找到当前使用的hive版本的hive-exec.jar文件2、上传到HDFS上。改权限3、impala加载function总结 前言 impala没有md5函数。 1、 找到当前使用的hive版本的hive-exec.jar文件 我们用的CDH&#xff0c;所以hive-exec.jar在每台服务器上都准备好的。 我装了loca…

解决多线程环境下单例模式同时访问生成多个实例

如何满足单例&#xff1a;1.构造方法是private、static方法、if语句判断 ①、单线程 Single类 //Single类&#xff0c;定义一个GetInstance操作&#xff0c;允许客户访问它的唯一实例。GetInstance是一个静态方法&#xff0c;主要负责创建自己的唯一实例 public class LazySi…

HCIP BGP选路规则总结

选路前提条件 多条BGP路由目标相同&#xff0c;且均可优(下一跳可达、同步关闭)&#xff0c;具有相同的优先级&#xff08;管理距离&#xff09;。 1、优选Preference_Value值最高的路由&#xff08;私有属性&#xff0c;仅本地有效&#xff09;。 不传递 权限最高属性 可…

【IDEA+Spark Streaming 3.4.1+Dstream监控套接字流统计WordCount保存至MySQL8】

【IDEASpark Streaming 3.4.1Dstream监控套接字流统计WordCount保存至MySQL8】 把DStream写入到MySQL数据库中 Spark 3.4.1MySQL 8.0.30sbt 1.9.2 文章目录 【IDEASpark Streaming 3.4.1Dstream监控套接字流统计WordCount保存至MySQL8】前言一、背景说明二、使用步骤1.引入库2…

【数字IC基础】低功耗设计

低功耗技术 功耗构成静态功耗(漏电功耗)动态功耗翻转功耗(Switch Power)短路功耗(Internal Power) 不同类型的标准单元的功耗 低功耗设计方法降低芯片工作电压多阈值工艺方法电源门控&#xff08;Power Gating&#xff09;多电压域(Multi-Voltage Domain)体偏置门控时钟一个简单…

IDEA SpringBoot项目引入外部jar并打包

1、首先&#xff0c;我们再pom.xml中导入依赖包时&#xff0c;打包可以正常进行。 但如果我们引入了第三方的外部jar包&#xff08;这里需要先把jar包添加到该项目依赖库中&#xff0c;这里不做演示&#xff09;&#xff0c;如图 2、导致打包时报错&#xff0c;程序包不存在或…

SpringBoot 配置文件

一、配置文件作用 整个项目中所有重要的数据都是在配置文件中配置的&#xff0c;比如&#xff1a; 数据库的连接信息&#xff08;包含用户名和密码的设置&#xff09;&#xff1b; 项目的启动端口&#xff1b; 第三方系统的调用秘钥等信息&#xff1b; 用于发现和定位问题的…

android app控制ros机器人四(调整界面布局)

半吊子改安卓&#xff0c;记录页面布局调整&#xff1a; 在ros-mobile基础上顶端增加一行&#xff0c;用于显示app名称和logo图像&#xff1b;修改标签页。 添加文字简单&#xff0c;但是替换图标长知识了&#xff0c;开始只是简单的把mipmap各个文件夹下的图片进行替换&…

MFC第二十六天 CRgn类简介与开发、封装CMemoryDC类并应用开发

文章目录 CRgn类简介与开发CRgn类简介CRgn类区域管理开发CRgn类区域管理与不规则形状的选取 封装CMemoryDC类并应用开发CMemoryDC.h封装CMemoryDC开发游戏透明动画CFlashDlg.hCFlashDlg.cpp 封装CMemoryDC开发游戏动画 附录四大窗口CDC派生类 CRgn类简介与开发 CRgn类简介 CR…

Qt 6. 其他类调用Ui中的控件

1. 把主类指针this传给其他类&#xff0c;tcpClientSocket new TcpClient(this); //ex2.cpp #include "ex2.h" #include "ui_ex2.h"Ex2::Ex2(QWidget *parent): QDialog(parent), ui(new Ui::Ex2) {ui->setupUi(this);tcpClientSocket new TcpClient…