
activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,比如一个简单的采购流程:流程如下:
供应商上新商品的时候,提交商务审核,商务审核通过提交运营审核,审核失败退回供应商。
运营审核成功提交合同签订。交运营审核审核失败退回商务审核或者直接退回供应商。
合同签订审核通过结束,合同签订审核不通过返回运营审核或者退回商务审核,或者退回供应商。
上面的流程就出现了一个问题,什么问题呢?
我们来观察一下退回线的问题。
1.商务审核退回供应商上新。
2.运营审核可能退回商务审核,运营审核可能退回供应商上新。
3.合同签订可能退回运营审核,合同签订可能退回商务审核,合同签订可能退回供应商上新。
4....
假如以后我们的流程在添加新的部门审核,是不是我们的退回线更加的多了。其实就是n!的问题,难道我们没添加一个节点,就要画很多的退回线吗?这显然是一个糟糕的设计。oh my god.
存在的问题就是,我们要是想让我们的流程更加的通用,我们可能在设计的时候,需要添加很多的退回线控制,防止业务变化,流程跟起来变化,这就是应对了变化,同时在增加了冗余设计。
那有没有一种更好的方式,能解决上面的问题呢?很显然这就是我们本章要解决的问题。
1.1.1. activiti节点跳转实现
实现之前,我们考虑几个问题。
1.当前流程在哪一个节点。
2.流程需要跳转的目标节点。
3.跳转到目标节点之后,需要添加变量吗?有可能需要把,总不能无缘无故的跳转到了目标节点。痕迹肯定要记录。
4.跳转到目标节点,那当前节点配置的任务监听需要触发吗?(可参考 activiti监听器使用).当前节点跳转到目标节点的时候,如果当前节点配置了任务监听业务,调转到目标节点之前,这些当前的任务节点的是否触发任务监听业务必须能支持灵活配置。
上面的思考点,也是我们接下来需要重点讲解的内容。那下面就开始我们的设计吧。
1.1.1.1. 流程图
下面我们先定义一个流程如下图所示:
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表任务的记录信息,方便我们的 *** 作,数据库记录如下图所示:
可以看到当前的节点在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)); 执行上面的代码之后,我们看一下数据库中的记录。
节点确实跳转到了usertask5。ok了这个方法确实可以没问题,下面说一下第二种方式执行executeCommand命令。
1.1.1.4.2. 第二种方式
Map<String,Arrays.asList(v)); //分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) CommandExecutor commandExecutor = taskServiceImpl .getCommandExecutor(); commandExecutor.execute(new JDJumpTaskCmd(executionID,currentActivity));
上面的两种方式都可以执行自定义的Command子类。读者选择自己喜欢使用的方式即可。
1.1.2. 小结
1.任意节点的跳转,前提是节点必须在模板定义中。
2.任意节点的跳转暂时不能跨流程跳转。
3.任意节点的跳转不需要连线即可、
4.任意节点的跳转可以实现回退、转办、转阅、越级上报、一步到底等等功能,关于这些更多的实战,我们将在最后的工作流实战项目中一步步封装。使用。
以上所述是小编给大家介绍的activiti节点跳转的相关知识,希望对大家有所帮助!
总结以上是内存溢出为你收集整理的Android开发之activiti节点跳转全部内容,希望文章能够帮你解决Android开发之activiti节点跳转所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)