activiti监听器使用

来源:互联网 发布:数据精灵官网 编辑:程序博客网 时间:2024/06/03 10:18

分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519)

activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,通常有如下一些场景:

1.activiti人员动态的分配。

2.当前任务节点完成的时候,指定需要指定下一个节点的处理人(比如,一个请假流程,a员工请假,需要指定下一步需要处理请假流程的领导。)

3.任务节点完成的时候,需要一些复杂业务,(比如当前节点完成的时候,需要调用我们的jms消息系统发送消息)

4.任务流转到当前的节点的时候,需要监控当前任务节点的一些信息或者其他的业务信息。

5.当前的任务节点分配处理人的时候,需要触发自定义的一些业务。

6.流程开始结束的时候,需要处理业务信息。

7.经过任务节点的出线,也就是连线的时候,需要触发自定义的业务。

那我们怎么实现以上的这些需求呢?这个时候,我们就需要使用activiti监听器,activiti提供的监听器怎么实现,以及如何触发,这些都需要我们一步步了解。下面就详细的介绍activiti监听器。

从 activiti监听器的使用范围来看,大致分为三种:

1.全局的监听器。

2.连线的监听器。

3.节点的监听器。

下面我们一个个的来看如何使用这些监听器。

1.1.1. 全局的监听器

全局监听器主要使用的场景就是监控这个流程的启动和结束。流程开始的时候可以监控,流程结束的时候可以监控,这里说的是流程实例启动结束的监控,并非是流程引擎的启动结束监控。流程引擎的启动结束监控可以参考http://blog.csdn.net/qq_30739519/article/details/51217614 不要混淆了这些概念。

下面我们先定义一个简单的bpmn xml文件看一下如何使用全局的监听器。

全局监听器实现的接口是org.activiti.engine.delegate.ExecutionListener,org.activiti.engine.impl.pvm.delegate.ExecutionListener这个接口新版本已经废弃。

1.1.1.1. ExecutionListener定义

ExecutionListener定义如下:流程实例startendtake的时候调用。take是监控连线的时候使用的。

public interface ExecutionListener extends Serializable {  String EVENTNAME_START = "start";  String EVENTNAME_END = "end";  String EVENTNAME_TAKE = "take";  void notify(DelegateExecution execution) throws Exception;}


下面定义一个类监控流程实例的启动监控,看如何使用。

1.1.1.2. 流程图

 

1.1.1.3. 流程定义xml

流程的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="daling">  <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">    <extensionElements>      <activiti:executionListener event="start" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>      <activiti:executionListener event="end" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>    </extensionElements>    <startEvent id="startevent1" name="Start"></startEvent>    <endEvent id="endevent1" name="End"></endEvent>    <userTask id="usertask2" name="User Task"></userTask>    <sequenceFlow id="flow3" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>    <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>  </process>  <bpmndi:BPMNDiagram id="BPMNDiagram_daling">    <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">        <omgdc:Bounds height="35.0" width="35.0" x="120.0" y="110.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">        <omgdc:Bounds height="35.0" width="35.0" x="640.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">        <omgdc:Bounds height="55.0" width="105.0" x="300.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">        <omgdi:waypoint x="155.0" y="127.0"></omgdi:waypoint>        <omgdi:waypoint x="300.0" y="117.0"></omgdi:waypoint>      </bpmndi:BPMNEdge>      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">        <omgdi:waypoint x="405.0" y="117.0"></omgdi:waypoint>        <omgdi:waypoint x="640.0" y="107.0"></omgdi:waypoint>      </bpmndi:BPMNEdge>    </bpmndi:BPMNPlane>  </bpmndi:BPMNDiagram></definitions>


1.1.1.4. 监听类

上面我们定义了两个监听器分别指向同一个类com.daling.ch1.listener.MyExecutionListener我们在类中监控事件。

com.daling.ch1.listener.MyExecutionListener类的实现如下所示:

package com.daling.ch1.listener;import org.activiti.engine.delegate.DelegateExecution;import org.activiti.engine.delegate.ExecutionListener;public class MyExecutionListener implements ExecutionListener {public void notify(DelegateExecution execution) throws Exception {String eventName = execution.getEventName();//startif ("start".equals(eventName)) {System.out.println("start=========");}else if ("end".equals(eventName)) {System.out.println("end=========");}}}

1.1.1.5. 开始监控

下面我们部署启动流程看一下效果,部署流程可参考之前的章节,启动流程如下所示:

ProcessInstance processInstance = runtimeService

.startProcessInstanceByKey(key,vars);

我们看一下程序的部分输出如下:

08:34:07.050 [main] DEBUG o.a.e.i.h.DefaultHistoryManager - Current history level: AUDIT, level required: ACTIVITY

08:34:07.056 [main] DEBUG o.a.e.i.h.DefaultHistoryManager - Current history level: AUDIT, level required: ACTIVITY

08:34:07.057 [main] DEBUG o.a.e.i.h.DefaultHistoryManager - Current history level: AUDIT, level required: FULL

start=========

08:34:07.064 [main] DEBUG o.a.e.i.p.r.AtomicOperationActivityExecute - ProcessInstance[107509] executes Activity(startevent1): org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior

08:34:07.064 [main] DEBUG o.a.e.i.p.e.J.selectJobsByExecutionId - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@eeb514]

08:34:07.064 [main] DEBUG o.a.e.i.p.e.J.selectJobsByExecutionId - ==>  Preparing: select * from ACT_RU_JOB J where J.EXECUTION_ID_ = ?

可以看出流程实例启动的时候,触发了我们自定义的类中的函数。

1.1.1.6. 结束监控

下面我们把usertask的任务结束,然后流程实例结束,看看触发了我们自定义的类中的end没有。

String taskId="107515";

demo.getTaskService().complete(taskId);

我们看一下程序的部分输出如下:

08:39:22.016 [main] DEBUG o.a.e.i.p.r.AtomicOperationActivityExecute - ProcessInstance[107509] executes Activity(endevent1): org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior

08:39:22.016 [main] DEBUG o.a.e.i.h.DefaultHistoryManager - Current history level: AUDIT, level required: ACTIVITY

end=========

1.1.1.7. DelegateExecution类

在上面的全局监听器中我们可以拿到DelegateExecution对象,这个对象可以让我们操作activiti引擎中的一些东西,下面看一下DelegateExecution类中的定义。

DelegateExecution类图如下:

 

启动最常用的方法如下:

/** execution Id */  String getId();   /**  流程实例id*/  String getProcessInstanceId();   /** 这个比较有用 主要就是start、end、take  */  String getEventName();    /**   *  业务id已经废弃   */  String getBusinessKey();    /**   * 业务id   */  String getProcessBusinessKey();    /**   * 流程定义id   */  String getProcessDefinitionId();    /**   * 获取父id,并发的时候有用   */  String getParentId();    /**   * 获取当前的.Activityid   */  String getCurrentActivityId();    /**   * 获取当前的.Activity name   */  String getCurrentActivityName();    /**   * 获取TenantId 当有多个TenantId 有用   */  String getTenantId();    /**   * 这个非常有用吧。当拿到EngineServices 对象所有的xxxService都可以拿到。   */  EngineServices getEngineServices();


 

1.1.2. 连线监听器

当节点结束的时候,经过连线的时候,我们可以在线上定义类,实现自己的业务逻辑。连线监听器怎么实现呢?

这里为了方便测试,我们还是采用上面全局监听器中的流程图,下面我们自定义一个连线监听器类,看看如何使用,可以拿到什么对象。

1.1.2.1. 流程图

 

1.1.2.2. 流程定义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="daling">  <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">    <extensionElements>      <activiti:executionListener event="start" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>      <activiti:executionListener event="end" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>    </extensionElements>    <startEvent id="startevent1" name="Start"></startEvent>    <endEvent id="endevent1" name="End"></endEvent>    <userTask id="usertask2" name="User Task"></userTask>    <sequenceFlow id="flow3" name="flow3" sourceRef="startevent1" targetRef="usertask2">      <extensionElements>        <activiti:executionListener event="take" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>      </extensionElements>    </sequenceFlow>    <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>  </process>  <bpmndi:BPMNDiagram id="BPMNDiagram_daling">    <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">        <omgdc:Bounds height="35.0" width="35.0" x="120.0" y="110.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">        <omgdc:Bounds height="35.0" width="35.0" x="640.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">        <omgdc:Bounds height="55.0" width="105.0" x="300.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">        <omgdi:waypoint x="155.0" y="127.0"></omgdi:waypoint>        <omgdi:waypoint x="300.0" y="117.0"></omgdi:waypoint>        <bpmndi:BPMNLabel>          <omgdc:Bounds height="14.0" width="100.0" x="155.0" y="127.0"></omgdc:Bounds>        </bpmndi:BPMNLabel>      </bpmndi:BPMNEdge>ss      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">        <omgdi:waypoint x="405.0" y="117.0"></omgdi:waypoint>        <omgdi:waypoint x="640.0" y="107.0"></omgdi:waypoint>      </bpmndi:BPMNEdge>    </bpmndi:BPMNPlane>  </bpmndi:BPMNDiagram></definitions>


1.1.2.3. 监听类

上面我们定义了一个监听器com.daling.ch1.listener.MyExecutionListener类中监控事件。

public class MyExecutionListener implements ExecutionListener {/** * */private static final long serialVersionUID = 7960387497099642910L;//ExecutionListener类的实现public void notify(DelegateExecution execution) throws Exception {String eventName = execution.getEventName();//startif ("start".equals(eventName)) {System.out.println("start=========");}else if ("end".equals(eventName)) {System.out.println("end=========");}else if ("take".equals(eventName)) {System.out.println("take=========");}}}


因为我们在flow3中定义的监听类,所以流程经过flow3的时候触发定义的take中的自定义事件。

 

1.1.3. 节点监听器

1.1.3.1. 节点监听器定义

在实际项目开发中,任务节点是经常用到的,所以我们必须要会使用节点监听器。

节点监听器的定义接口org.activiti.engine.delegate.TaskListener,org.activiti.engine.impl.pvm.delegate.TaskListener已经废弃不用。

TaskListener类的定义如下所示:

  String EVENTNAME_CREATE = "create";  String EVENTNAME_ASSIGNMENT = "assignment";  String EVENTNAME_COMPLETE = "complete";  String EVENTNAME_DELETE = "delete";  /**   * Not an actual event, used as a marker-value for {@link TaskListener}s that should be called for all events,   * including {@link #EVENTNAME_CREATE}, {@link #EVENTNAME_ASSIGNMENT} and {@link #EVENTNAME_COMPLETE} and {@link #EVENTNAME_DELETE}.   */  String EVENTNAME_ALL_EVENTS = "all";    void notify(DelegateTask delegateTask);

1.1.3.2. 节点监听器类图

节点监听器的子类如下图所示:

 

 

下面开始我们详细的使用吧。首先还是定义一个xmlxml流程还是上面所示的,只是多了一些任务节点的监听。

1.1.3.3. 流程图

 

 

1.1.3.4. 流程定义xml

流程的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="daling">  <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">    <extensionElements>      <activiti:executionListener event="start" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>      <activiti:executionListener event="end" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>    </extensionElements>    <startEvent id="startevent1" name="Start"></startEvent>    <endEvent id="endevent1" name="End"></endEvent>    <userTask id="usertask2" name="User Task" activiti:assignee="c">      <extensionElements>        <activiti:taskListener event="all" class="com.daling.ch1.listener.MyExecutionListener"></activiti:taskListener>      </extensionElements>    </userTask>    <sequenceFlow id="flow3" name="flow3" sourceRef="startevent1" targetRef="usertask2">      <extensionElements>        <activiti:executionListener event="take" class="com.daling.ch1.listener.MyExecutionListener"></activiti:executionListener>      </extensionElements>    </sequenceFlow>    <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>  </process>  <bpmndi:BPMNDiagram id="BPMNDiagram_daling">    <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">        <omgdc:Bounds height="35.0" width="35.0" x="120.0" y="110.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">        <omgdc:Bounds height="35.0" width="35.0" x="640.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">        <omgdc:Bounds height="55.0" width="105.0" x="300.0" y="90.0"></omgdc:Bounds>      </bpmndi:BPMNShape>      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">        <omgdi:waypoint x="155.0" y="127.0"></omgdi:waypoint>        <omgdi:waypoint x="300.0" y="117.0"></omgdi:waypoint>        <bpmndi:BPMNLabel>          <omgdc:Bounds height="14.0" width="100.0" x="155.0" y="127.0"></omgdc:Bounds>        </bpmndi:BPMNLabel>      </bpmndi:BPMNEdge>      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">        <omgdi:waypoint x="405.0" y="117.0"></omgdi:waypoint>        <omgdi:waypoint x="640.0" y="107.0"></omgdi:waypoint>      </bpmndi:BPMNEdge>    </bpmndi:BPMNPlane>  </bpmndi:BPMNDiagram></definitions>

1.1.3.5. 监听类

任务节点的监听只要实现TaskListener接口即可。下面是任务监听的实现类,如下所示:

public class MyExecutionListener implements ExecutionListener,TaskListener {/** * */private static final long serialVersionUID = 7960387497099642910L;//ExecutionListener类的实现public void notify(DelegateExecution execution) throws Exception {String eventName = execution.getEventName();//startif ("start".equals(eventName)) {System.out.println("start=========");}else if ("end".equals(eventName)) {System.out.println("end=========");}else if ("take".equals(eventName)) {System.out.println("take=========");}}//实现TaskListener中的方法public void notify(DelegateTask delegateTask) {String eventName = delegateTask.getEventName();if ("create".endsWith(eventName)) {System.out.println("create=========");}else if ("assignment".endsWith(eventName)) {System.out.println("assignment========");}else if ("complete".endsWith(eventName)) {System.out.println("complete===========");}else if ("delete".endsWith(eventName)) {System.out.println("delete=============");}}}

当流程运转到usertask2我们看一下程序的输出:

assignment========

create=========

因为usertask2节点配置了处理人所以触发assignment事件监听,当任务运转到usertask2的时候触发了create事件。

这里我们也可以得出一个结论:assignment事件比create先执行。

使用代码结束任务,代码如下:

String taskId="127515";

demo.getTaskService().complete(taskId);

当我们结束usertask2我们看一下程序的输出:

complete===========

delete=============

在这里我们可以得出结论:

任务完成的时候,触发complete事件,因为任务完成之后,要从ACT_RU_TASK中删除这条记录,所以触发delete事件。

1.1.3.6. DelegateTask类

在上面的任务监听器中我们可以拿到DelegateTask对象,这个对象可以让我们操作activiti引擎中的一些东西,下面看一下DelegateTask类中的定义主要访法。

public interface DelegateTask extends VariableScope {  /** 数据库中的taskId主键*/  String getId();    /** 任务名称 */  String getName();    /** 修改任务名称 */  void setName(String name);   /** 获取任务的描述信息 */  String getDescription();    /** 修改任务的描述信息 */  void setDescription(String description);    /**   * lower priority: [0..19] lowest, [20..39] low, [40..59] normal, [60..79] high   * [80..100] highest任务处理的优先级范围是0-100*/  int getPriority();    /** 修改优先级*/  void setPriority(int priority);    /** 获取流程实例id */  String getProcessInstanceId();    /**获取执行id*/  String getExecutionId();    /** 获取流程定义id*/  String getProcessDefinitionId();  /** Adds the given user as a candidate user to this task. */  void addCandidateUser(String userId);    /** 添加候选人 */  void addCandidateUsers(Collection<String> candidateUsers);    /** 添加候选组 */  void addCandidateGroup(String groupId);}


上面我们总结了,全局监听器、连线、任务节点的使用,下面我们看一下共性的东西再做一次总结。

 

1.1.4. 其他的使用方式

1.1.4.1. spring整合

上面我们在定义类的的时候,我们直接使用的类定义的方式,当然我们还可以跟sring整合使用,因为在实际项目中类的管理可能交给spring容器。使用也很简单如下图所示:

 

需要填写的表达书,只需要使用spring方式注入即可,${}里面的值为需要使用的beanspring中的id.可以xml定义或者在注解中定义。注解中定义需要开启spring包扫描机制。比如我的@Service("myExecutionListener")。

 

1.1.5. 小结

1.activiti监听方式分为三大类,节点监听、全局监听、连线监听。

2.activiti监听主要实现的类是两个 节点监听、全局监听实现org.activiti.engine.delegate.ExecutionListener

节点的监听实现org.activiti.engine.delegate.TaskListener接口即可。

3.监听器其实就是一个观察者模式。(关于观察者模式,我们后续章节讲解,限于篇幅有限)

4.监听器获取spring对象,如何获取spring中的bean呢?

1.1.6. 遗留点

5.监听器关于观察者模式,我们后续章节讲解。

6.监听器获取spring对象,如何获取spring中的bean呢?留到下一个章节讲解吧。

11 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 纹身结痂蹭掉了怎么办 药流20天同房了怎么办 药流23天同房了怎么办 小产后不来月经怎么办 人流12天同房了怎么办 人流20天同房了怎么办 人流后5天同房了怎么办 人流后3天同房了怎么办 人流20后同房了怎么办 上环后月经量多怎么办 上环后喝啤酒了怎么办 取环当天同房了怎么办 生完孩子有外痔怎么办 怀孕了宫腔积液怎么办 做完爱4天怕怀孕怎么办 半永久眉失败了怎么办 取环前2天同房了怎么办 怀孕了发现有子宫肌瘤怎么办 宫腔中央性粘连怎么办 孕妇宫腔粘连带怎么办 内膜厚怎么办吃什么好 功血引起的贫血怎么办 吃宫血宁后月经不来了怎么办 孕晚期胎心不好怎么办 胎心不好怎么办让住院 39 5胎心不好怎么办 肺长了一个肿瘤怎么办 血糖高伤口不愈合怎么办 有轻微的狐臭该怎么办 嘴上汗毛太重怎么办 风把裙子吹起怎么办 每天三四点醒来就睡不着怎么办 打游戏手汗太多怎么办 老年人胸闷气短呼吸困难怎么办 冒险岛宠物饿了怎么办 不小心喝了黑墨怎么办 压的双眼皮开了怎么办 割了双眼皮显老怎么办 心脏供血不足怎么办呢 怀孕了哮喘犯了怎么办 喝了电解质不拉怎么办