Activiti7 监听器支持程度

这是我参与更文挑战的第5天,活动详情查看: 更文挑战

监听器

Activiti7监听器

服务任务

  • 概述

    为了实现一个可以在流程执行过程中调用的类,这个类需要实现org.activiti.engine.delegate.JavaDelegate接口,并在execute方法中提供所需的逻辑。当流程执行到达此特定步骤时,它将执行该方法中定义的此逻辑,并以默认的 BPMN 2.0 方式保留活动。

  • 举例

    我们创建一个 Java 类,该类可用于将流程变量 String 更改为大写。这个类需要实现org.activiti.engine.delegate.JavaDelegate接口,这需要我们实现*execute(DelegateExecution)*方法。引擎会调用这个操作,它需要包含业务逻辑。流程实例信息,如流程变量等,可以通过DelegateExecution接口访问和操作。

public class ToUppercase implements JavaDelegate {

  public void execute(DelegateExecution execution) throws Exception {
    String var = (String) execution.getVariable("input");
    var = var.toUpperCase();
    execution.setVariable("input", var);
  }
}
复制代码

注意只有一个 Java 类的实例是为它在 上定义的 serviceTask 创建的。所有流程实例共享将用于调用execute(DelegateExecution)的相同类实例。这意味着该类不能使用任何成员变量并且必须是线程安全的,因为它可以从不同的线程同时执行。这也会影响字段注入的处理方式。在流程定义中引用的类(即通过使用activiti:class在部署期间不会被实例化。只有当流程执行第一次到达流程中使用该类的点时,才会创建该类的实例。如果找不到该类,ActivitiException则会抛出一个。这样做的原因是您部署时的环境(更具体地说是classpath)通常与实际的运行时环境不同。例如在Activiti Explorer中使用ant或业务归档上传部署流程时,classpath不包含引用的类。

  • 在xml中具体展示

    要指定在流程执行期间调用的类,需要由activiti:class属性提供完全限定的类名。

<serviceTask id="javaService"
             name="My Java Service Task"
             activiti:class="org.bci.ToUppercase" />
复制代码
中断流程任务

org.activiti.engine.impl.pvm.delegate.ActivityBehavior

  • 描述

    实现org.activiti.engine.impl.pvm.delegate.ActivityBehavior接口可以访问更强大的ActivityExecution,比如有特殊的业务在执行当前任务后停顿在当前位置,等待您一个事物的触发。

    • 任务模型Java代码

      public class MyActivitiBehavior implements ActivityBehavior {
          private static final Logger LOGGER = LoggerFactory.getLogger(MyActivitiBehavior.class);
          @Override
          public void execute(DelegateExecution execution) {
              LOGGER.info("run my java ActivityBehavior {}", this);
          }
      }
      复制代码
    • 在xml中表达式

       <serviceTask id="someTask" name="User Task"
                        activiti:class="com.imooc.activiti.example.MyActivitiBehavior"/>
      复制代码

事件监听器

  • 概述

    事件侦听器的唯一要求是实现org.activiti.engine.delegate.event.ActivitiEventListener

  • 举例

    下面是一个监听器的示例实现,它将接收到的所有事件输出到标准输出,与作业执行相关的事件除外:

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() {
     // 此监听器的 onEvent 方法中的逻辑并不重要
     //  能过滤失败日志
    return false;
  }
}
复制代码
  • isFailOnException方法解释

    isFailOnException()方法确定在onEvent(..)调度事件时该方法抛出异常时的行为。如果false返回,则忽略异常。当true返回,异常不会被忽略,前进行执行命令失败。如果事件是 API 调用(或任何其他事务性操作,例如作业执行)的一部分,则事务将被回滚。如果事件监听器中的行为不是关键业务,建议返回false

    Activiti 提供了一些基本实现来促进事件监听器的常见用例。这些可以用作基类或作为示例侦听器实现;

    • org.activiti.engine.delegate.event.BaseEntityEventListener:事件监听器基类,可用于监听特定类型实体或所有实体的实体相关事件。它隐藏了类型检查并提供了 4 种应该被覆盖的方法:onCreate(..),onUpdate(..)以及onDelete(..)何时创建、更新或删除实体。对于所有其他实体相关事件,onEntityEvent(..) 调用 。

在运行时添加侦听器

可以使用 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);
复制代码

执行监听器

  • 执行监听器位置

    org.activiti.engine.delegate.ExecutionListener

  • 概述

    执行侦听器允许您在流程执行期间发生某些事件时执行外部 Java 代码或评估表达式。

执行监听器捕获事件
  • 流程实例的开始和结束。
  • 采取过渡。
  • 活动的开始和结束。
  • 网关的开始和结束。
  • 中间事件的开始和结束。
  • 结束开始事件或开始结束事件。

以下流程定义包含 3 个执行侦听器:

<process id="executionListenersProcess">
 
    // 第一个执行监听器
  <extensionElements>
    <activiti:executionListener class="org.activiti.examples.bpmn.executionlistener.ExampleExecutionListenerOne" event="start" />
  </extensionElements>

  <startEvent id="theStart" />
  <sequenceFlow sourceRef="theStart" targetRef="firstTask" />

  <userTask id="firstTask" />
  <sequenceFlow sourceRef="firstTask" targetRef="secondTask">
    // 第二个执行监听器
      <extensionElements>
      <activiti:executionListener class="org.activiti.examples.bpmn.executionListener.ExampleExecutionListenerTwo" />
    </extensionElements>
  </sequenceFlow>

  <userTask id="secondTask" >
      // 第三个执行监听器
    <extensionElements>
      <activiti:executionListener expression="${myPojo.myMethod(execution.event)}" event="end" />
    </extensionElements>
  </userTask>
  <sequenceFlow sourceRef="secondTask" targetRef="thirdTask" />

  <userTask id="thirdTask" />
  <sequenceFlow sourceRef="thirdTask" targetRef="theEnd" />

  <endEvent id="theEnd" />

</process>
复制代码
第一个执行监听器

第一个执行监听器在进程启动时收到通知。监听器是一个外部 Java 类(如ExampleExecutionListenerOne)并且应该实现org.activiti.engine.delegate.ExecutionListener接口。当事件发生时(在本例中为start事件),该方法notify(ExecutionListenerExecution execution)被调用。

public class ExampleExecutionListenerOne implements ExecutionListener {

  public void notify(ExecutionListenerExecution execution) throws Exception {
      // 设置本地变量
    execution.setVariable("variableSetInExecutionListener", "firstValue");
    execution.setVariable("eventReceived", execution.getEventName());
  }
}
复制代码

也可以使用实现org.activiti.engine.delegate.JavaDelegate接口的委托类。然后可以在其他构造方法中重用这些委托类,例如 serviceTask 的委托

第二个执行监听器

进行转换时调用第二个执行监听器。请注意,该listener元素没有定义event,因为take在转换时只触发事件。event转换上定义侦听器时,将忽略属性中的值。

第三个执行监听器

当执行到最后一个执行监听器,在监听器上不是一个clas而是一个expression,他在触发事件被评估/调用。

<activiti:executionListener expression="${myPojo.myMethod(execution.eventName)}" event="end" />
复制代码
脚本执行侦听器
  • 概述

    在 Activiti 5.12 中,我们还引入了一种新类型的执行侦听器,org.activiti.engine.impl.bpmn.listener.ScriptExecutionListener。此脚本执行侦听器允许您为执行侦听器事件执行一段脚本逻辑。

  • 举例

    <activiti:executionListener event="start" class="org.activiti.engine.impl.bpmn.listener.ScriptExecutionListener" >
      <activiti:field name="script">
        <activiti:string>
          def bar = "BAR";  // local variable
          foo = "FOO"; // pushes variable to execution context
          execution.setVariable("var1", "test"); // test access to execution instance
          bar // implicit return value
        </activiti:string>
      </activiti:field>
      <activiti:field name="language" stringValue="groovy" />
      <activiti:field name="resultVariable" stringValue="myVar" />
    </activiti:executionListener>
    复制代码
执行侦听器上的字段注入
  • 概述

    使用配置了该class属性的执行侦听器时,可以应用字段注入。这与使用的Service 任务字段注入机制完全相同,其中包含对字段注入提供的可能性的概述。

下面的片段显示了一个简单的示例流程,其中包含一个注入字段的执行侦听器。

<process id="executionListenersProcess">
  <extensionElements>
      <!- 执行监听器位置-!>
    <activiti:executionListener class="org.activiti.examples.bpmn.executionListener.ExampleFieldInjectedExecutionListener" event="start">
      <activiti:field name="fixedValue" stringValue="Yes, I am " />
      <activiti:field name="dynamicValue" expression="${myVar}" />
    </activiti:executionListener>
  </extensionElements>

  <startEvent id="theStart" />
  <sequenceFlow sourceRef="theStart" targetRef="firstTask" />

  <userTask id="firstTask" />
  <sequenceFlow sourceRef="firstTask" targetRef="theEnd" />

  <endEvent id="theEnd" />
</process>
复制代码
public class ExampleFieldInjectedExecutionListener implements ExecutionListener {

  private Expression fixedValue;

  private Expression dynamicValue;

  public void notify(ExecutionListenerExecution execution) throws Exception {
    execution.setVariable("var", fixedValue.getValue(execution).toString() +         dynamicValue.getValue(execution).toString());
  }
}
复制代码

该类ExampleFieldInjectedExecutionListener连接了 2 个注入的字段(一个是固定的,另一个是动态的)并将其存储在过程变量中*var*。

// bpmn 文件位置
@Deployment(resources = {"org/activiti/examples/bpmn/executionListener/ExecutionListenersFieldInjectionProcess.bpmn20.xml"})
public void testExecutionListenerFieldInjection() {
  Map<String, Object> variables = new HashMap<String, Object>();
  variables.put("myVar", "listening!");

  ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListenersProcess", variables);

  Object varSetByListener = runtimeService.getVariable(processInstance.getId(), "var");
  assertNotNull(varSetByListener);
  assertTrue(varSetByListener instanceof String);

  // 结果是固定注入字段和注入表达式的串联
  assertEquals("Yes, I am listening!", varSetByListener);
}
复制代码

任务监听器

  • 概述

    一个任务监听器用于执行自定义Java逻辑或使用表达式执行一定的任务相关的事件。

    任务监听器只能作为用户任务的子元素添加到流程定义中。请注意,这也必须作为BPMN 2.0 extensionElementsactiviti命名空间的子项发生,因为任务监听器是 Activiti 特定的构造。

  • 任务监听器在xml中表达式

    <userTask id="myTask" name="My Task" >
      <extensionElements>
          <!- 任务监听器 ->
        <activiti:taskListener event="create" class="org.activiti.MyTaskCreateListener" />
      </extensionElements>
    </userTask>
    复制代码
任务监听器属性
  • event(必需):各种任务监听器配置如下:
    • create:在创建任务并设置所有任务属性时发生
    • assignment:当任务分配给某人时发生。注意:当流程执行到达用户任务时,首先会触发分配事件,然后再触发创建事件。这似乎是一个不自然的顺序,但原因是:当收到 create 事件时,我们通常希望检查任务的所有属性,包括受托人。
    • complete:在任务完成时和任务从运行时数据中删除之前发生。
    • delete : 发生在任务将被删除之前。请注意,它也会在通过 completeTask 正常完成任务时执行。
  • class:必须调用的委托类。这个类必须实现org.activiti.engine.delegate.TaskListener接口。
public class MyTaskCreateListener implements TaskListener {

  public void notify(DelegateTask delegateTask) {
    // Custom logic goes here
  }				
}
复制代码
  • 表达式:(不能与属性一起使用):指定事件发生时将执行的表达式。可以将DelegateTask对象和事件名称(使用task.eventName)作为参数传递给被调用对象。
<activiti:taskListener event="create" expression="${myObject.callMethod(task, task.eventName)}" />
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享