文末提供 activiti学习视频下载
文章目录
Activiti引擎中的事件机制使您可以 在引擎中发生各种事件时得到通知,这是高级应用部分,可以让我们扩展一些我们的自定义逻辑,下面章节会有所有受支持的事件类型及其描述。
- 可以为某些类型的事件注册侦听器,而不是在分派任何类型的事件时得到通知。
- 可以通过配置添加引擎范围的事件监听器。
- 可以在运行期间用API添加范围的事件侦听器。
- 可以在BPMN XML中添加事件侦听器。
所有分发的事件,都是org.activiti.engine.delegate.event.ActivitiEvent的子类。事件包含type,executionId,processInstanceId和processDefinitionId`。 对应的事件会包含事件发生时对应上下文的额外信息。
1. 事件监听器实现
实现事件监听器的唯一要求是实现org.activiti.engine.delegate.event.ActivitiEventListener。 下面是一个实现监听器的例子,它会把所有监听到的事件打印到标准输出中,包括job执行的事件异常:
@Component
public class MyEventListener implements ActivitiEventListener {
@Override
public void onEvent(ActivitiEvent event) {
switch (event.getType()) {
case JOB_EXECUTION_SUCCESS:
System.out.println("A job well done!");
break;
case JOB_EXECUTION_FAILURE:
System.out.println("A job has failed...");
break;
default:
System.out.println("Event received: " + event.getType());
}
}
@Override
public boolean isFailOnException() {
// false 代表吞异常onEvent方法的异常,不往外抛出
return false;
}
}
isFailOnException()方法决定了当事件分发时,onEvent(..)方法抛出异常时的行为。
- 返回的是
false,会忽略异常。 - 当返回
true时,异常不会忽略,继续向上传播,迅速导致当前命令失败。 当事件是一个API调用的一部分时(或其他事务性操作,比如job执行), 事务就会回滚。当事件监听器中的行为不是业务性时,建议返回false。
activiti提供了一些基础的实现,实现了事件监听器的常用场景。可以用来作为基类或监听器实现的样例:
- org.activiti.engine.delegate.event.BaseEntityEventListener: 这个事件监听器的基类可以用来监听实体相关的事件,可以针对某一类型实体,也可以是全部实体。 它隐藏了类型检测,并提供了三个需要重写的方法:
onCreate(..),onUpdate(..)和onDelete(..),当实体创建,更新,或删除时调用。对于其他实体相关的事件,会调用onEntityEvent(..)。
2. 配置与安装
如果在流程引擎配置中配置了事件侦听器,则事件引擎在流程引擎启动时将处于活动状态,并在后续引擎重新启动后保持活动状态。
eventListeners属性需要org.activiti.engine.delegate.event.ActivitiEventListener的实例列表。 通常,我们可以声明一个内部的bean定义,或使用ref引用已定义的bean。 下面的代码,向配置添加了一个事件监听器,任何事件触发时都会提醒它,无论事件是什么类型:
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="eventListeners">
<list>
<bean class="org.activiti.engine.example.MyEventListener" />
</list>
</property>
</bean>
为了监听特定类型的事件,可以使用typedEventListeners属性,它需要一个map参数。 map的key是逗号分隔的事件名(或单独的事件名)。 map的value是org.activiti.engine.delegate.event.ActivitiEventListener列表。 下面的代码演示了向配置中添加一个事件监听器,可以监听job执行成功或失败:
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="typedEventListeners">
<map>
<entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
<list>
<bean class="org.activiti.engine.example.MyJobEventListener" />
</list>
</entry>
</map>
</property>
</bean>
分发事件的顺序是由监听器添加时的顺序决定的。首先,会调用所有普通的事件监听器(eventListeners属性),按照它们在list中的次序。 然后,会调用所有对应类型的监听器(typedEventListeners属性),如果对应类型的事件被触发了。
对应Spring Boot配置如下:
/**
* 自定义扩展配置
*/
@Configuration
public class ActivitiConfig implements ProcessEngineConfigurationConfigurer {
/**
*
* @param processEngineConfiguration processEngineConfiguration
*/
@Override
public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
// 生成流程图的字体 解決工作流生成图片乱码问题
processEngineConfiguration.setActivityFontName("宋体");
processEngineConfiguration.setAnnotationFontName("宋体");
processEngineConfiguration.setLabelFontName("宋体");
processEngineConfiguration.setEventListeners()//
processEngineConfiguration.setTypedEventListeners()//
}
}
3. 在运行阶段添加监听器
可以通过API(RuntimeService)在运行阶段添加或删除额外的事件监听器:
/**
* Adds an event-listener which will be notified of ALL events by the dispatcher.
* @param listenerToAdd the listener to add
*/
void addEventListener(ActivitiEventListener listenerToAdd);
/**
* Adds an event-listener which will only be notified when an event occurs, which type is in the given types.
* @param listenerToAdd the listener to add
* @param types types of events the listener should be notified for
*/
void addEventListener(ActivitiEventListener listenerToAdd, ActivitiEventType... types);
/**
* Removes the given listener from this dispatcher. The listener will no longer be notified,
* regardless of the type(s) it was registered for in the first place.
* @param listenerToRemove listener to remove
*/
void removeEventListener(ActivitiEventListener listenerToRemove);
请注意,重新启动引擎时不会保留在运行时添加的侦听器。
3.1 自定义事件监听和发布
runtimeService.addEventListener(new ProcessEventListener());
runtimeService.dispatchEvent(new ActivitiEventImpl(ActivitiEventType.CUSTOM));
4. 为流程定义添加监听器
可以为特定流程定义添加监听器。监听器只会监听与这个流程定义相关的事件,以及这个流程定义上发起的所有流程实例的事件。 监听器实现可以使用,全类名定义,引用实现了监听器接口的表达式,或配置为抛出一个message/signal/error的BPMN事件。
4.1 让监听器执行用户定义的逻辑
下面代码为一个流程定义添加了两个监听器。
- 第一个监听器会接收所有类型的事件,它是通过全类名定义的。
- 第二个监听器只接收作业成功或失败的事件,它使用了定义在流程引擎配置中的
beans属性中的一个bean。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener class="org.activiti.engine.test.MyEventListener" />
<activiti:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
</extensionElements>
...
</process>
对于实体相关的事件,也可以设置为针对某个流程定义的监听器,实现只监听发生在某个流程定义上的某个类型实体事件。 下面的代码演示了如何实现这种功能。可以用于所有实体事件(第一个例子),也可以只监听特定类型的事件(第二个例子)。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener class="org.activiti.engine.test.MyEventListener" entityType="task" />
<activiti:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
</extensionElements>
...
</process>
entityType支持的值有:attachment, comment, execution,identity-link, job, process-instance, process-definition, task。
4.2 监听抛出BPMN事件
试验阶段
另一种处理事件的方法是抛出一个BPMN事件。请注意它只针对与抛出一个activiti事件类型的BPMN事件。 比如,抛出一个BPMN事件,在流程实例删除时,会导致一个错误。 下面的代码演示了如何在流程实例中抛出一个signal,把signal抛出到外部流程(全局),在流程实例中抛出一个消息事件, 在流程实例中抛出一个错误事件。除了使用class或delegateExpression, 还使用了throwEvent属性,通过额外属性,指定了抛出事件的类型。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="globalSignal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
</extensionElements>
</process>
如果需要声明额外的逻辑,是否抛出BPMN事件,可以扩展activiti提供的监听器类。在子类中重写isValidEvent(ActivitiEvent event), 可以防止抛出BPMN事件。对应的类是org.activiti.engine.test.api.event.SignalThrowingEventListenerTest, org.activiti.engine.impl.bpmn.helper.MessageThrowingEventListener 和 org.activiti.engine.impl.bpmn.helper.ErrorThrowingEventListener.
4.3 流程定义中监听器的注意事项
- 事件监听器只能声明在
process元素中,作为extensionElements的子元素。 监听器不能定义在流程的单个activity下。 delegateExpression中的表达式无法访问execution上下文,这与其他表达式不同(比如gateway)。 它只能引用定义在流程引擎配置的beans属性中声明的bean,或者使用spring(未使用beans属性)中所有实现了监听器接口的spring-bean。- 在使用监听器的
class属性时,只会创建一个实例。记住监听器实现不会依赖成员变量, 确认是多线程安全的。 - 当一个非法的事件类型用在
events属性或throwEvent中时,流程定义发布时就会抛出异常。(会导致部署失败)。如果class或delegateExecution由问题(类不存在,不存在的bean引用,或代理类没有实现监听器接口),会在流程启动时抛出异常(或在第一个有效的流程定义事件被监听器接收时)。所以要保证引用的类正确的放在classpath下,表达式也要引用一个有效的实例。
5. 通过API分发事件
我们提供了通过API使用事件机制的方法,允许大家触发定义在引擎中的任何自定义事件。 建议(不强制)只触发类型为CUSTOM的ActivitiEvents。可以通过RuntimeService触发事件:
/**
* Dispatches the given event to any listeners that are registered.
* @param event event to dispatch.
*
* @throws ActivitiException if an exception occurs when dispatching the event or when the {@link ActivitiEventDispatcher}
* is disabled.
* @throws ActivitiIllegalArgumentException when the given event is not suitable for dispatching.
*/
void dispatchEvent(ActivitiEvent event);
6. 支持的事件类型
下面是引擎中可能出现的所有事件类型。每个类型都对应org.activiti.engine.delegate.event.ActivitiEventType中的一个枚举值。
| 事件名称 | 描述 | 事件类型 |
|---|---|---|
| ENGINE_CREATED | 监听器监听的流程引擎已经创建完毕,并准备好接受API调用。 | org.activiti...ActivitiEvent |
| ENGINE_CLOSED | 监听器监听的流程引擎已经关闭,不再接受API调用。 | org.activiti...ActivitiEvent |
| ENTITY_CREATED | 创建了一个新实体。实体包含在事件中。 | org.activiti...ActivitiEntityEvent |
| ENTITY_INITIALIZED | 创建了一个新实体,初始化也完成了。如果这个实体的创建会包含子实体的创建,这个事件会在子实体都创建/初始化完成后被触发,这是与ENTITY_CREATED的区别。 | org.activiti...ActivitiEntityEvent |
| ENTITY_UPDATED | 更新了已存在的实体。实体包含在事件中。 | org.activiti...ActivitiEntityEvent |
| ENTITY_DELETED | 删除了已存在的实体。实体包含在事件中。 | org.activiti...ActivitiEntityEvent |
| ENTITY_SUSPENDED | 暂停了已存在的实体。实体包含在事件中。会被ProcessDefinitions, ProcessInstances 和 Tasks抛出。 | org.activiti...ActivitiEntityEvent |
| ENTITY_ACTIVATED | 激活了已存在的实体,实体包含在事件中。会被ProcessDefinitions, ProcessInstances 和 Tasks抛出。 | org.activiti...ActivitiEntityEvent |
| JOB_EXECUTION_SUCCESS | 作业执行成功。job包含在事件中。 | org.activiti...ActivitiEntityEvent |
| JOB_EXECUTION_FAILURE | 作业执行失败。作业和异常信息包含在事件中。 | org.activiti...ActivitiEntityEvent and org.activiti...ActivitiExceptionEvent |
| JOB_RETRIES_DECREMENTED | 因为作业执行失败,导致重试次数减少。作业包含在事件中。 | org.activiti...ActivitiEntityEvent |
| TIMER_FIRED | 触发了定时器。job包含在事件中。 | org.activiti...ActivitiEntityEvent |
| JOB_CANCELED | 取消了一个作业。事件包含取消的作业。作业可以通过API调用取消, 任务完成后对应的边界定时器也会取消,在新流程定义发布时也会取消。 | org.activiti...ActivitiEntityEvent |
| ACTIVITY_STARTED | 一个节点开始执行 | org.activiti...ActivitiActivityEvent |
| ACTIVITY_COMPLETED | 一个节点成功结束 | org.activiti...ActivitiActivityEvent |
| ACTIVITY_SIGNALED | 一个节点收到了一个信号 | org.activiti...ActivitiSignalEvent |
| ACTIVITY_MESSAGE_RECEIVED | 一个节点收到了一个消息。在节点收到消息之前触发。收到后,会触发ACTIVITY_SIGNAL或ACTIVITY_STARTED,这会根据节点的类型(边界事件,事件子流程开始事件) | org.activiti...ActivitiMessageEvent |
| ACTIVITY_ERROR_RECEIVED | 一个节点收到了一个错误事件。在节点实际处理错误之前触发。 事件的activityId对应着处理错误的节点。 这个事件后续会是ACTIVITY_SIGNALLED或ACTIVITY_COMPLETE, 如果错误发送成功的话。 | org.activiti...ActivitiErrorEvent |
| UNCAUGHT_BPMN_ERROR | 抛出了未捕获的BPMN错误。流程没有提供针对这个错误的处理器。 事件的activityId为空。 | org.activiti...ActivitiErrorEvent |
| ACTIVITY_COMPENSATE | 一个节点将要被补偿。事件包含了将要执行补偿的节点id。 | org.activiti...ActivitiActivityEvent |
| VARIABLE_CREATED | 创建了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。 | org.activiti...ActivitiVariableEvent |
| VARIABLE_UPDATED | 更新了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。 | org.activiti...ActivitiVariableEvent |
| VARIABLE_DELETED | 删除了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。 | org.activiti...ActivitiVariableEvent |
| TASK_ASSIGNED | 任务被分配给了一个人员。事件包含任务。 | org.activiti...ActivitiEntityEvent |
| TASK_CREATED | 创建了新任务。它位于ENTITY_CREATE事件之后。当任务是由流程创建时, 这个事件会在TaskListener执行之前被执行。 | org.activiti...ActivitiEntityEvent |
| TASK_COMPLETED | 任务被完成了。它会在ENTITY_DELETE事件之前触发。当任务是流程一部分时,事件会在流程继续运行之前, 后续事件将是ACTIVITY_COMPLETE,对应着完成任务的节点。 | org.activiti...ActivitiEntityEvent |
| TASK_TIMEOUT | 任务已超时,在TIMER_FIRED事件之后,会触发用户任务的超时事件, 当这个任务分配了一个定时器的时候。 | org.activiti...ActivitiEntityEvent |
| PROCESS_COMPLETED | 流程已结束。在最后一个节点的ACTIVITY_COMPLETED事件之后触发。 当流程到达的状态,没有任何后续连线时, 流程就会结束。 | org.activiti...ActivitiEntityEvent |
| PROCESS_CANCELLED | 进程已被取消。在从运行时删除流程实例之前调度。流程实例被API调用取消RuntimeService.deleteProcessInstance | org.activiti…ActivitiCancelledEvent |
| MEMBERSHIP_CREATED | 用户被添加到一个组里。事件包含了用户和组的id。 | org.activiti...ActivitiMembershipEvent |
| MEMBERSHIP_DELETED | 用户被从一个组中删除。事件包含了用户和组的id。 | org.activiti...ActivitiMembershipEvent |
| MEMBERSHIPS_DELETED | 所有成员被从一个组中删除。在成员删除之前触发这个事件,所以他们都是可以访问的。 因为性能方面的考虑,不会为每个成员触发单独的MEMBERSHIP_DELETED事件。 | org.activiti...ActivitiMembershipEvent |
引擎内部所有ENTITY_*事件都是与实体相关的。下面的列表展示了实体事件与实体的对应关系:
-
ENTITY_CREATED, ENTITY_INITIALIZED, ENTITY_DELETED:- Attachment, Comment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.
- 附件,注释,部署,执行,组,IdentityLink,作业,模型,ProcessDefinition,ProcessInstance,任务,用户。
-
ENTITY_UPDATED:- Attachment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.
- 附件,部署,执行,组,IdentityLink,作业,模型,ProcessDefinition,ProcessInstance,任务,用户。
-
ENTITY_SUSPENDED, ENTITY_ACTIVATED:- ProcessDefinition, ProcessInstance/Execution, Task.
- ProcessDefinition,ProcessInstance /执行,任务。
7. 附加信息
只有同一个流程引擎中的事件会发送给对应的监听器。因此,如果您有不同的引擎(在同一个数据库上运行),则仅将源于监听器注册的引擎中的事件调度到该监听器。在另一个引擎中发生的事件不会分派给侦听器,无论它们是否在同一JVM中运行。
某些事件类型(与实体相关)公开了目标实体。根据类型或事件,这些实体无法再进行更新(例如,删除实体时)。如果可能,请使用EngineServices事件暴露的方式以安全的方式与引擎进行交互。即使这样,您仍需谨慎对待已调度事件中涉及的实体的更新/操作。
没有对应历史的实体事件,因为它们都有运行阶段的对应实体。
分享 Activiti工作流高级视频教程 全套视频
关注公众号【Java大厂面试官】,回复 :工作流
即可免费下载
QQ群【837324215】
关注我的公众号【Java大厂面试官】,回复:架构、资源等关键词(更多关键词,关注后注意提示信息)获取更多免费资料。
公众号也会持续输出高质量文章,和大家共同进步。