activiti节点跳转
分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519)
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, 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.任意节点的跳转可以实现回退、转办、转阅、越级上报、一步到底等等功能,关于这些更多的实战,我们将在最后的工作流实战项目中一步步封装。使用。
分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519)
分享牛,分享、我们是快乐的。
activiti节点跳转相关推荐
- Flowable节点跳转
关键词:Flowable任务节点跳转,Flowable节点跳转,Flowable任意节点跳转. 在使用Flowable或者Activiti的时候,有时候我们并不期望他按照模板的定义进行运转,比如如下的 ...
- activitiy学习 (动态加签,动态流程图,指定节点跳转,指定多人节点跳转)
activitiy学习 动态加签,动态流程图,指定节点跳转,指定多人节点跳转 POM.XML 部署流程 启动流程 查询待执行任务 查询任务历史 完成任务 多人会签节点的退回指定节点 退回到指定多人会签 ...
- flowable 并行节点跳转以及驳回
bpmn流程图 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns=" ...
- activity任意节点跳转
前言 在实际业务中,总会碰到一些特殊的需求,比如要实现任意两个审批节点之间的跳转,举例来说,某个审批流程有3级审批,来了这么个需求,一级审批完结之后在满足特定的条件下,可以直接进入到3级审批,即跳过中 ...
- activiti实现跳转节点的方法
1.通过代码实现,即获取到当前节点,然后退回到已走过的指定节点.代码如下: @RequestMapping("/returnNode")public String returnNo ...
- ue4缓存位置怎么改_怎么从蓝图节点跳转到C++源码?
在以前的虚幻编辑器版本上,通常是这样打开C++代码的:双击蓝图节点,或者在蓝图节点上右键,再点击Goto Definition,这样就自动打开VS,跳出C++代码来了. 但是,从某个版本开始,这样忽然 ...
- 全亮半亮爆闪三功能LED车灯驱动IC方案 H7230无电流节点跳变 惠海半导体
车灯远近光切换的原理: 远近光灯的切换原理,首先要分这个远近光灯的类型,其有两种情况:一是远近光灯一体(也就是远近光灯被集合在一个模组中),它的远近光灯切换又分为两种.1是控制光源数量,2是控制遮光板 ...
- php中 br什么意思,HTML_html中br和br/的区别介绍,answer from stackflow: Simply br - phpStudy...
html中br和br/的区别介绍 answer from stackflow: Simply is sufficient. The other forms are there for compatib ...
- SpringBoot + Activiti6简单教程包含任意跳转节点
SpringBoot + Activiti6 一.Activiti6简述 1.简述 2.接口 3.库表 二.创建BPMN业务流程模型 二.整合 1.POM依赖 2. bpmn20.xml部署 3.ap ...
最新文章
- myeclipse 6.0 弹出 Multiple Errors have Occurred 错误
- 5g宣传方案_5G时代来了,VR如何玩转线上营销新模式
- Android-去除Button默认边框
- 多线程:线程池里的队列BlockingQueue
- linux中_在 Linux 桌面中开始使用 Lumina | Linux 中国
- 开发自上而下的Web服务项目
- java 类似xamarin_xamarin android如何将Java.Lang.Object类型转成C#类型
- Alley Bird 跳跳鸟源码
- 大数据之-Hadoop伪分布式_配置历史服务器---大数据之hadoop工作笔记0027
- scala 连接符_Scala标识符示例教程
- navicat导入sql语句
- http的ssl证书保姆级配置安装-多域名 免费ssl证书 解析 nginx配置
- 我对“心即理,致良知,知行合一”和《王阳明四句教》的的理解。
- malloc(): smallbin double linked list corrupted:
- XP系统开机显示“NTDETECT失败”
- (https专业版)2018年1月5日高仿互站仿友价T5虚拟交易+实物交易商城-站长交易源码送手机版程序10套模版+首页微信登陆+头部下拉导航...
- 新特性:TabLayout动态添加条目
- myeclipse 2015 stable2.0破解安装教程
- redis配置RDB、AOF以及RDB、AOF同时开启
- R语言使用caret包的train函数构建adaboost模型、模型调优、自定义设置trainControl函数和tuneLength参数
热门文章
- Extended WPF Toolkit 新控件介绍
- datatable如何生成级联数据_UE4 C++结合DataTable批量快速创建DataAsset
- +[NSTimer scheduledTimerWithTimeInterval:repeats:block:]: unrecognized selector sent to xxx
- python2.7 升级到 python3.6
- html5开发桌面界面设计,HTML5触摸界面设计与开发
- mysql逻辑运算符的优先顺序_PL/SQL运算符优先级
- ARP监控工具ARPalert常用命令集合大学霸IT达人
- 服务认证暴力破解工具Crowbar
- android surfaceview动画,怎么让android的surfaceview中的动画更加平滑流畅
- python6翻_洗礼灵魂,修炼python(6)--活起来的代码+列表