返回介绍

3.18. 事件处理器

发布于 2023-09-17 23:40:35 字数 15643 浏览 0 评论 0 收藏 0

Flowable引擎中的事件机制可以让你在引擎中发生多种事件的时候得到通知。查看所有支持的事件类型了解可用的事件。

可以只为特定种类的事件注册监听器,而不是在任何类型的事件发送时都被通知。可以通过配置添加引擎全局的事件监听器,在运行时通过API添加引擎全局的事件监听器,也可以在BPMN XML文件为个别流程定义添加事件监听器。

所有被分发的事件都是org.flowable.engine.common.api.delegate.event.FlowableEvent的子类。事件(在可用时)提供type, executionId, processInstanceIdprocessDefinitionId。部分事件含有关于发生事件的上下文信息。关于事件包含的附加信息,请参阅所有支持的事件类型。

3.18.1. 实现事件监听器

对事件监听器的唯一要求,是要实现org.flowable.engine.delegate.event.FlowableEventListener接口。下面是一个监听器实现的例子,它将接收的所有事件打印至标准输出,并对作业执行相关的事件特别处理:

public class MyEventListener implements FlowableEventListener {

  @Override
  public void onEvent(FlowableEvent 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() {
  // onEvent方法中的逻辑并不重要,可以忽略日志失败异常……

  return false;
  }
}

isFailOnException()方法决定了当事件分发后,onEvent(..)方法抛出异常时的行为。若返回false,忽略异常;若返回true,异常不会被忽略而会被上抛,使当前执行的命令失败。如果事件是API调用(或其他事务操作,例如作业执行)的一部分,事务将被回滚。如果事件监听器中并不是重要的业务操作,建议返回false

Flowable提供了少量基础实现,以简化常用的事件监听器使用场景。它们可以被用作监听器的示例或基类:

  • org.flowable.engine.delegate.event.BaseEntityEventListener: 事件监听器基类,可用来监听实体(entity)相关事件,特定或所有实体的事件都可以。它隐藏了类型检测,提供了4个需要覆盖的方法:onCreate(..), onUpdate(..)onDelete(..)在实体创建、更新及删除时调用;对所有其他实体相关事件,onEntityEvent(..)会被调用。

3.18.2. 配置与使用

在流程引擎中配置的事件监听器会在流程引擎启动时生效,引擎重启后也会保持有效。

eventListeners参数为org.flowable.engine.delegate.event.FlowableEventListener类实例的列表(list)。与其他地方一样,你可以声明内联bean定义,也可以用ref指向已有的bean。下面的代码片段在配置中添加了一个事件监听器,无论任何类型的事件分发时,都会得到通知:

<bean
  class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  ...
  <property name="eventListeners">
    <list>
     <bean class="org.flowable.engine.example.MyEventListener" />
    </list>
  </property>
</bean>

要在特定类型的事件分发时得到通知,使用typedEventListeners参数,值为map。map的key为逗号分隔的事件名字列表(或者一个事件的名字),取值为org.flowable.engine.delegate.event.FlowableEventListener实例的列表。下面的代码片段在配置中添加了一个事件监听器,它会在作业执行成功或失败时得到通知:

<bean
  class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  ...
  <property name="typedEventListeners">
    <map>
    <entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
      <list>
      <bean class="org.flowable.engine.example.MyJobEventListener" />
      </list>
    </entry>
    </map>
  </property>
</bean>

事件分发的顺序由加入监听器的顺序决定。首先,所有普通(eventListeners参数定义的)事件监听器按照在list里的顺序被调用;之后,如果分发的是某类型的事件,则(typedEventListeners 参数定义的)该类型监听器被调用。

3.18.3. 在运行时添加监听器

可以使用API(RuntimeService)为引擎添加或删除事件监听器:


/**
 * 新增一个监听器,会在所有事件发生时被通知。
 * @param listenerToAdd 要新增的监听器
 */
void addEventListener(FlowableEventListener listenerToAdd);

/**
 * 新增一个监听器,在给定类型的事件发生时被通知。
 * @param listenerToAdd 要新增的监听器
 * @param types 监听器需要监听的事件类型
 */
void addEventListener(FlowableEventListener listenerToAdd, FlowableEventType... types);

/**
 * 从分发器中移除指定监听器。该监听器将不再被通知,无论该监听器注册为监听何种类型。
 * @param listenerToRemove 要移除的监听器
 */
 void removeEventListener(FlowableEventListener listenerToRemove);

请注意,运行时新增的监听器在引擎重启后不会保持。

3.18.4. 为流程定义增加监听器

可以为某一流程定义增加监听器。只有与该流程定义相关,或使用该流程定义启动的流程实例相关的事件,才会调用这个监听器。监听器实现可以用完全限定类名(fully qualified classname)定义;也可以定义为表达式,该表达式需要能被解析为实现监听器接口的bean;也可以配置为抛出消息(message)/信号(signal)/错误(error)的BPMN事件。

执行用户定义逻辑的监听器

下面的代码片段为流程定义增加了2个监听器。第一个监听器接收任何类型的事件,使用完全限定类名定义。第二个监听器只在作业成功执行或失败时被通知,使用流程引擎配置中beans参数定义的bean作为监听器。

<process>
  <extensionElements>
  <flowable:eventListener class="org.flowable.engine.test.MyEventListener" />
  <flowable:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
  </extensionElements>

  ...

</process>

实体相关的事件也可以在流程定义中增加监听器,只有在特定实体类型的事件发生时得到通知。下面的代码片段展示了如何设置。可以响应实体的所有事件(第一个例子),或只响应实体的特定类型事件(第二个例子)。

<process>
  <extensionElements>
  <flowable:eventListener class="org.flowable.engine.test.MyEventListener" entityType="task" />
  <flowable:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
  </extensionElements>

  ...

</process>

entityType可用的值有:attachment(附件), comment(备注), execution(执行), identity-link(身份关联), job(作业), process-instance(流程实例), process-definition(流程定义), task(任务)。

抛出BPMN事件的监听器

处理分发的事件的另一个方法,是抛出BPMN事件。请牢记在心,只有特定种类的Flowable事件类型,抛出BPMN事件才合理。例如,在流程实例被删除时抛出BPMN事件,会导致错误。下面的代码片段展示了如何在流程实例中抛出信号,向外部流程(全局)抛出信号,在流程实例中抛出消息事件,以及在流程实例中抛出错误事件。这里不使用classdelegateExpression,而要使用throwEvent属性,以及一个附加属性,用于指定需要抛出的事件类型。

<process>
  <extensionElements>
  <flowable:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
  </extensionElements>
</process>
<process>
  <extensionElements>
  <flowable:eventListener throwEvent="globalSignal" signalName="My signal" events="TASK_ASSIGNED" />
  </extensionElements>
</process>
<process>
  <extensionElements>
  <flowable:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
  </extensionElements>
</process>
<process>
  <extensionElements>
  <flowable:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
  </extensionElements>
</process>

如果需要使用额外的逻辑判断是否需要抛出BPMN事件,可以扩展Flowable提供的监听器类。通过在你的子类中覆盖isValidEvent(FlowableEvent event),可以阻止抛出BPMN事件。相关的类为org.flowable.engine.test.api.event.SignalThrowingEventListenerTest, org.flowable.engine.impl.bpmn.helper.MessageThrowingEventListenerorg.flowable.engine.impl.bpmn.helper.ErrorThrowingEventListener.

关于流程定义监听器的说明

  • 事件监听器只能作为extensionElements的子元素,声明在process元素上。不能在个别节点(activity)上定义(事件)监听器。

  • delegateExpression中的表达式,与其他表达式(例如在网关中的)不一样,不可以访问执行上下文。只能够引用在流程引擎配置中beans参数定义的bean;或是在使用spring(且没有定义beans参数)时,引用任何实现了监听器接口的spring bean。

  • 使用监听器的class属性时,只会创建唯一一个该类的实例。请确保监听器实现不依赖于成员变量,或确保多线程/上下文的使用安全。

  • 如果events属性使用了不合法的事件类型,或者使用了不合法的throwEvent值,会在流程定义部署时抛出异常(导致部署失败)。如果classdelegateExecution指定了不合法的值(不存在的类,不存在的bean引用,或者代理类没有实现监听器接口),在流程启动(或该流程定义的第一个有效事件分发给这个监听器)时,会抛出异常。请确保引用的类在classpath中,并且保证表达式能够解析为有效的实例。

3.18.5. 通过API分发事件

可以通过API提供事件分发机制,向任何在引擎中注册的监听器分发自定义事件。建议(但不强制)只分发CUSTOM类型的FlowableEvents。使用RuntimeService分发事件:


/**
 * 将给定事件分发给所有注册监听器。
 * @param event 要分发的事件。
 *
 * @throws FlowableException 当分发事件发生异常,或者{@link FlowableEventDispatcher}被禁用。
 * @throws FlowableIllegalArgumentException 当给定事件不可分发
 */
 void dispatchEvent(FlowableEvent event);

3.18.6. 支持的事件类型

下表列出引擎中的所有事件类型。每种类型对应org.flowable.engine.common.api.delegate.event.FlowableEventType中的一个枚举值。

Table 1. Supported events
事件名称说明事件类
ENGINE_CREATED本监听器所属的流程引擎已经创建,并可以响应API调用。org.flowable…​FlowableEvent
ENGINE_CLOSED本监听器所属的流程引擎已经关闭,不能再对该引擎进行API调用。org.flowable…​FlowableEvent
ENTITY_CREATED新的实体已经创建。该实体包含在本事件里。org.flowable…​FlowableEntityEvent
ENTITY_INITIALIZED新的实体已经创建并完全初始化。如果任何子实体作为该实体的一部分被创建,本事件会在子实体创建/初始化后触发,与 ENTITY_CREATE 事件相反。org.flowable…​FlowableEntityEvent
ENTITY_UPDATED实体已经更新。该实体包含在本事件里。org.flowable…​FlowableEntityEvent
ENTITY_DELETED实体已经删除。该实体包含在本事件里。org.flowable…​FlowableEntityEvent
ENTITY_SUSPENDED实体已经暂停。该实体包含在本事件里。ProcessDefinitions(流程定义), ProcessInstances(流程实例)与Tasks(任务)会分发本事件。org.flowable…​FlowableEntityEvent
ENTITY_ACTIVATED实体已经激活。该实体包含在本事件里。ProcessDefinitions, ProcessInstances与Tasks会分发本事件。org.flowable…​FlowableEntityEvent
JOB_EXECUTION_SUCCESS作业已经成功执行。该作业包含在本事件里。org.flowable…​FlowableEntityEvent
JOB_EXECUTION_FAILURE作业执行失败。该作业与异常包含在本事件里。org.flowable…​FlowableEntityEventorg.flowable…​FlowableExceptionEvent
JOB_RETRIES_DECREMENTED作业重试次数已经由于执行失败而减少。该作业包含在本事件里。org.flowable…​FlowableEntityEvent
TIMER_SCHEDULED已创建一个定时作业,并预计在未来时间点执行。org.flowable…​FlowableEntityEvent
TIMER_FIRED定时器已经触发。org.flowable…​FlowableEntityEvent
JOB_CANCELED作业已经取消。该作业包含在本事件里。作业会由于API调用取消,任务完成导致关联的边界定时器取消,也会由于新流程定义的部署而取消。org.flowable…​FlowableEntityEvent
ACTIVITY_STARTED节点开始执行org.flowable…​FlowableActivityEvent
ACTIVITY_COMPLETED节点成功完成org.flowable…​FlowableActivityEvent
ACTIVITY_CANCELLED节点将要取消。节点的取消有三个原因(MessageEventSubscriptionEntity, SignalEventSubscriptionEntity, TimerEntity)。org.flowable…​FlowableActivityCancelledEvent
ACTIVITY_SIGNALED节点收到了一个信号org.flowable…​FlowableSignalEvent
ACTIVITY_MESSAGE_RECEIVED节点收到了一个消息。事件在节点接收消息前分发。节点接收消息后,会为该节点分发 ACTIVITY_SIGNALACTIVITY_STARTED 事件,取决于其类型(边界事件,或子流程启动事件)。org.flowable…​FlowableMessageEvent
ACTIVITY_MESSAGE_WAITING一个节点已经创建了一个消息事件订阅,并正在等待接收消息。org.flowable…​FlowableMessageEvent
ACTIVITY_MESSAGE_CANCELLED一个节点已经取消了一个消息事件订阅,因此接收这个消息不会再触发该节点。org.flowable…​FlowableMessageEvent
ACTIVITY_ERROR_RECEIVED节点收到了错误事件。在节点实际处理错误前分发。该事件的activityId为处理错误的节点。如果错误成功传递,后续会为节点发送 ACTIVITY_SIGNALLEDACTIVITY_COMPLETE 消息。org.flowable…​FlowableErrorEvent
UNCAUGHT_BPMN_ERROR抛出了未捕获的BPMN错误。流程没有该错误的处理器。该事件的activityId为空。org.flowable…​FlowableErrorEvent
ACTIVITY_COMPENSATE节点将要被补偿(compensate)。该事件包含将要执行补偿的节点id。org.flowable…​FlowableActivityEvent
MULTI_INSTANCE_ACTIVITY_STARTED多实例节点开始执行org.flowable…​FlowableMultiInstanceActivityEvent
MULTI_INSTANCE_ACTIVITY_COMPLETED多实例节点成功完成org.flowable…​FlowableMultiInstanceActivityEvent
MULTI_INSTANCE_ACTIVITY_CANCELLED多实例节点将要取消。多实例节点的取消有三个原因(MessageEventSubscriptionEntity, SignalEventSubscriptionEntity, TimerEntity)。org.flowable…​FlowableMultiInstanceActivityCancelledEvent
VARIABLE_CREATED流程变量已经创建。本事件包含变量名、取值,及关联的执行和任务(若有)。org.flowable…​FlowableVariableEvent
VARIABLE_UPDATED变量已经更新。本事件包含变量名、取值,及关联的执行和任务(若有)。org.flowable…​FlowableVariableEvent
VARIABLE_DELETED变量已经删除。本事件包含变量名、最后取值,及关联的执行和任务(若有)。org.flowable…​FlowableVariableEvent
TASK_ASSIGNED任务已经分派给了用户。该任务包含在本事件里。org.flowable…​FlowableEntityEvent
TASK_CREATED任务已经创建。本事件在 ENTITY_CREATE 事件之后分发。若该任务是流程的一部分,本事件会在任务监听器执行前触发。org.flowable…​FlowableEntityEvent
TASK_COMPLETED任务已经完成。本事件在 ENTITY_DELETE 事件前分发。若该任务是流程的一部分,本事件会在流程前进之前触发,并且会跟随一个 ACTIVITY_COMPLETE 事件,指向代表该任务的节点。org.flowable…​FlowableEntityEvent
PROCESS_CREATED流程实例已经创建。已经设置所有的基础参数,但还未设置变量。org.flowable…​FlowableEntityEvent
PROCESS_STARTED流程实例已经启动。在启动之前创建的流程时分发。PROCESS_STARTED事件在相关的ENTITY_INITIALIZED事件,以及设置变量之后分发。org.flowable…​FlowableEntityEvent
PROCESS_COMPLETED流程实例已经完成。在最后一个节点的 ACTIVITY_COMPLETED 事件后分发。当流程实例没有任何路径可以继续时,流程结束。org.flowable…​FlowableEntityEvent
PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT流程已经到达终止结束事件(terminate end event)并结束。org.flowable…​FlowableProcessTerminatedEvent
PROCESS_CANCELLED流程已经被取消。在流程实例从运行时中删除前分发。流程实例由API调用RuntimeService.deleteProcessInstance取消。org.flowable…​FlowableCancelledEvent
MEMBERSHIP_CREATED用户已经加入组。本事件包含了相关的用户和组的id。org.flowable…​FlowableMembershipEvent
MEMBERSHIP_DELETED用户已经从组中移出。本事件包含了相关的用户和组的id。org.flowable…​FlowableMembershipEvent
MEMBERSHIPS_DELETED组的所有用户将被移出。本事件在用户移出前抛出,因此关联关系仍然可以访问。因为性能原因,不会再为每个被移出的用户抛出 MEMBERSHIP_DELETED 事件。org.flowable…​FlowableMembershipEvent

引擎中所有的 ENTITY_\* 事件都与实体关联。下表列出每个实体分发的实体事件:

  • ENTITY_CREATED, ENTITY_INITIALIZED, ENTITY_DELETED: 附件(Attachment),备注(Comment),部署(Deployment),执行(Execution),组(Group),身份关联(IdentityLink),作业(Job),模型(Model),流程定义(ProcessDefinition),流程实例(ProcessInstance),任务(Task),用户(User)。

  • ENTITY_UPDATED: 附件,部署,执行,组,身份关联,作业,模型,流程定义,流程实例,任务,用户。

  • ENTITY_SUSPENDED, ENTITY_ACTIVATED: 流程定义,流程实例/执行,任务。

3.18.7. 附加信息

监听器只会响应其所在引擎分发的事件。因此如果在同一个数据库上运行不同的引擎,则只有该监听器注册的引擎生成的事件,才会分发给该监听器。其他引擎生成的事件不会分发给这个监听器,而不论这些引擎是否运行在同一个JVM下。

某些事件类型(与实体相关)暴露了目标实体。按照事件类型的不同,有些实体不能被更新(如实体删除事件中的实体)。如果可能的话,请使用事件暴露的EngineServices来安全地操作引擎。即使这样,更新、操作事件中暴露的实体仍然需要小心。

历史不会分发实体事件,因为它们都有对应的运行时实体分发事件。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文