欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发之activiti节点跳转

程序员文章站 2024-02-29 09:58:40
activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,比如一个简单的采购流程:流程如下:   供应商上新商品的时候,提交商务审核,商...

activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,比如一个简单的采购流程:流程如下:

 Android开发之activiti节点跳转

供应商上新商品的时候,提交商务审核,商务审核通过提交运营审核,审核失败退回供应商。

运营审核成功提交合同签订。交运营审核审核失败退回商务审核或者直接退回供应商。

合同签订审核通过结束,合同签订审核不通过返回运营审核或者退回商务审核,或者退回供应商。

上面的流程就出现了一个问题,什么问题呢?

我们来观察一下退回线的问题。

1.商务审核退回供应商上新。

2.运营审核可能退回商务审核,运营审核可能退回供应商上新。

3.合同签订可能退回运营审核,合同签订可能退回商务审核,合同签订可能退回供应商上新。

4....

假如以后我们的流程在添加新的部门审核,是不是我们的退回线更加的多了。其实就是n!的问题,难道我们没添加一个节点,就要画很多的退回线吗?这显然是一个糟糕的设计。oh my god.

存在的问题就是,我们要是想让我们的流程更加的通用,我们可能在设计的时候,需要添加很多的退回线控制,防止业务变化,流程跟起来变化,这就是应对了变化,同时在增加了冗余设计。

那有没有一种更好的方式,能解决上面的问题呢?很显然这就是我们本章要解决的问题。

1.1.1. activiti节点跳转实现

实现之前,我们考虑几个问题。

1.当前流程在哪一个节点。

2.流程需要跳转的目标节点。

3.跳转到目标节点之后,需要添加变量吗?有可能需要把,总不能无缘无故的跳转到了目标节点。痕迹肯定要记录。

4.跳转到目标节点,那当前节点配置的任务监听需要触发吗?(可参考 activiti监听器使用).当前节点跳转到目标节点的时候,如果当前节点配置了任务监听业务,调转到目标节点之前,这些当前的任务节点的是否触发任务监听业务必须能支持灵活配置。

上面的思考点,也是我们接下来需要重点讲解的内容。那下面就开始我们的设计吧。

1.1.1.1. 流程图

下面我们先定义一个流程如下图所示:

 Android开发之activiti节点跳转

1.1.1.2. 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"> 
  <usertask id="usertask2" name="usertask2" activiti:assignee="c"></usertask> 
  <usertask id="usertask3" name="usertask3"></usertask> 
  <sequenceflow id="flow4" sourceref="usertask2" targetref="usertask3"></sequenceflow> 
  <usertask id="usertask4" name="usertask4"></usertask> 
  <sequenceflow id="flow5" sourceref="usertask3" targetref="usertask4"></sequenceflow> 
  <usertask id="usertask5" name="usertask5"></usertask> 
  <sequenceflow id="flow6" sourceref="usertask4" targetref="usertask5"></sequenceflow> 
  <endevent id="endevent1" name="end"></endevent> 
  <sequenceflow id="flow7" sourceref="usertask5" targetref="endevent1"></sequenceflow> 
  <startevent id="startevent1" name="start"></startevent> 
  <sequenceflow id="flow8" sourceref="startevent1" targetref="usertask2"></sequenceflow> 
 </process> 
 <bpmndi:bpmndiagram id="bpmndiagram_daling"> 
  <bpmndi:bpmnplane bpmnelement="daling" id="bpmnplane_daling"> 
   <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:bpmnshape bpmnelement="usertask3" id="bpmnshape_usertask3"> 
    <omgdc:bounds height="55.0" width="105.0" x="450.0" y="90.0"></omgdc:bounds> 
   </bpmndi:bpmnshape> 
   <bpmndi:bpmnshape bpmnelement="usertask4" id="bpmnshape_usertask4"> 
    <omgdc:bounds height="55.0" width="105.0" x="600.0" y="90.0"></omgdc:bounds> 
   </bpmndi:bpmnshape> 
   <bpmndi:bpmnshape bpmnelement="usertask5" id="bpmnshape_usertask5"> 
    <omgdc:bounds height="55.0" width="105.0" x="750.0" y="90.0"></omgdc:bounds> 
   </bpmndi:bpmnshape> 
   <bpmndi:bpmnshape bpmnelement="endevent1" id="bpmnshape_endevent1"> 
    <omgdc:bounds height="35.0" width="35.0" x="900.0" y="100.0"></omgdc:bounds> 
   </bpmndi:bpmnshape> 
   <bpmndi:bpmnshape bpmnelement="startevent1" id="bpmnshape_startevent1"> 
    <omgdc:bounds height="35.0" width="35.0" x="140.0" y="90.0"></omgdc:bounds> 
   </bpmndi:bpmnshape> 
   <bpmndi:bpmnedge bpmnelement="flow4" id="bpmnedge_flow4"> 
    <omgdi:waypoint x="405.0" y="117.0"></omgdi:waypoint> 
    <omgdi:waypoint x="450.0" y="117.0"></omgdi:waypoint> 
   </bpmndi:bpmnedge> 
   <bpmndi:bpmnedge bpmnelement="flow5" id="bpmnedge_flow5"> 
    <omgdi:waypoint x="555.0" y="117.0"></omgdi:waypoint> 
    <omgdi:waypoint x="600.0" y="117.0"></omgdi:waypoint> 
   </bpmndi:bpmnedge> 
   <bpmndi:bpmnedge bpmnelement="flow6" id="bpmnedge_flow6"> 
    <omgdi:waypoint x="705.0" y="117.0"></omgdi:waypoint> 
    <omgdi:waypoint x="750.0" y="117.0"></omgdi:waypoint> 
   </bpmndi:bpmnedge> 
   <bpmndi:bpmnedge bpmnelement="flow7" id="bpmnedge_flow7"> 
    <omgdi:waypoint x="855.0" y="117.0"></omgdi:waypoint> 
    <omgdi:waypoint x="900.0" y="117.0"></omgdi:waypoint> 
   </bpmndi:bpmnedge> 
   <bpmndi:bpmnedge bpmnelement="flow8" id="bpmnedge_flow8"> 
    <omgdi:waypoint x="175.0" y="107.0"></omgdi:waypoint> 
    <omgdi:waypoint x="300.0" y="117.0"></omgdi:waypoint> 
   </bpmndi:bpmnedge> 
  </bpmndi:bpmnplane> 
 </bpmndi:bpmndiagram> 
</definitions>

1.1.1.3. 代码实现

package com.daling.ch1.jd; 
import java.util.iterator; 
import java.util.map; 
import org.activiti.engine.impl.context.context; 
import org.activiti.engine.impl.interceptor.command; 
import org.activiti.engine.impl.interceptor.commandcontext; 
import org.activiti.engine.impl.persistence.entity.executionentity; 
import org.activiti.engine.impl.persistence.entity.executionentitymanager; 
import org.activiti.engine.impl.persistence.entity.taskentity; 
import org.activiti.engine.impl.pvm.process.activityimpl; 
/** 
 * 
 * jd节点的跳转 
 * 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 
 */ 
public class jdjumptaskcmd implements command<void> { 
protected string executionid; 
protected activityimpl desactivity; 
protected map<string, object> paramvar; 
protected activityimpl currentactivity; 
/** 
 * 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 
 */ 
public void execute(commandcontext commandcontext) { 
executionentitymanager executionentitymanager = context 
.getcommandcontext().getexecutionentitymanager(); 
// 获取当前流程的executionid,因为在并发的情况下executionid是唯一的。 
executionentity executionentity = executionentitymanager 
.findexecutionbyid(executionid); 
executionentity.setvariables(paramvar); 
executionentity.seteventsource(this.currentactivity); 
executionentity.setactivity(this.currentactivity); 
// 根据executionid 获取task 
iterator<taskentity> localiterator = context.getcommandcontext() 
.gettaskentitymanager() 
.findtasksbyexecutionid(this.executionid).iterator(); 
while (localiterator.hasnext()) { 
taskentity taskentity = (taskentity) localiterator.next(); 
// 触发任务监听 
taskentity.fireevent("complete"); 
// 删除任务的原因 
context.getcommandcontext().gettaskentitymanager() 
.deletetask(taskentity, "completed", false); 
} 
executionentity.executeactivity(this.desactivity); 
return null; 
} 
/** 
 * 构造参数 可以根据自己的业务需要添加更多的字段 
 * 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 
 * @param executionid 
 * @param desactivity 
 * @param paramvar 
 * @param currentactivity 
 */ 
public jdjumptaskcmd(string executionid, activityimpl desactivity, 
map<string, object> paramvar, activityimpl currentactivity) { 
this.executionid = executionid; 
this.desactivity = desactivity; 
this.paramvar = paramvar; 
this.currentactivity = currentactivity; 
} 
} 

1.1.1.4. 使用

我们先让流程运转到usertask3节点的时候开始测试跳转。

怎么使用上面的jdjumptaskcmd类呢,直接new jdjumptaskcmd()调用,肯定不行了,因为activiti引擎程序没有获取,肯定报错,正确的的使用方式如下:

1.1.1.4.1. 第一种方式

我们先来观察一下数据库act_ru_task表任务的记录信息,方便我们的操作,数据库记录如下图所示:

 Android开发之activiti节点跳转

可以看到当前的节点在usertask3,我们现在把usertask3跳转到usertask5节点,看是否能成功,因为usertask3到usertask5没有连线,如果成功了,就说明我们这个方法正确。

执行下面的代码,根据自己的数据库信息修改相对应的值即可。

map<string, object> vars = new hashmap<string, object>(); 
string[] v = { "shareniu1", "shareniu2", "shareniu3", "shareniu4" }; 
vars.put("assigneelist", arrays.aslist(v)); 
//分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 
repositoryservice repositoryservice = demo.getrepositoryservice(); 
readonlyprocessdefinition processdefinitionentity = (readonlyprocessdefinition) repositoryservice 
.getprocessdefinition("daling:29:137504"); 
// 目标节点 
activityimpl destinationactivity = (activityimpl) processdefinitionentity 
.findactivity("usertask5"); 
string executionid = "137509"; 
// 当前节点 
  activityimpl currentactivity = (activityimpl)processdefinitionentity 
   .findactivity("usertask3"); 
demo.getmanagementservice().executecommand( 
new jdjumptaskcmd(executionid, destinationactivity, vars, 
currentactivity)); 

执行上面的代码之后,我们看一下数据库中的记录。

 Android开发之activiti节点跳转

节点确实跳转到了usertask5。ok了这个方法确实可以没问题,下面说一下第二种方式执行executecommand命令。

1.1.1.4.2. 第二种方式

map<string, object> vars = new hashmap<string, object>(); 
string[] v = { "shareniu1", "shareniu2", "shareniu3", "shareniu4" }; 
vars.put("assigneelist", arrays.aslist(v)); 
//分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 
  commandexecutor commandexecutor = taskserviceimpl 
   .getcommandexecutor(); 
  commandexecutor.execute(new jdjumptaskcmd(executionid, 
   destinationactivity, vars, currentactivity)); 

上面的两种方式都可以执行自定义的command子类。读者选择自己喜欢使用的方式即可。

1.1.2. 小结

1.任意节点的跳转,前提是节点必须在模板定义中。

2.任意节点的跳转暂时不能跨流程跳转。

3.任意节点的跳转不需要连线即可、

4.任意节点的跳转可以实现回退、转办、转阅、越级上报、一步到底等等功能,关于这些更多的实战,我们将在最后的工作流实战项目中一步步封装。使用。

以上所述是小编给大家介绍的activiti节点跳转的相关知识,希望对大家有所帮助!