在很多情况下,我们需要多用户共同执行余下流程,比如开会流程

  1. 领导发起开会,选择开会人员(多个)
  2. 每个开会人员接收到通知后需要签到(一名用户签到不会影响到另一位用户的签到)
  3. 签到完成后则流程结束

  如果只使用代理(Assignee、Candidate users、Candidate groups) 将无法解决上述问题,因为即使使用 Candidate users ,但每个用户实际上还是在一个任务里面,其中一个用户完成任务,另外的用户任务也随之完成,此时,就需要用到多实例(多任务)。


以上面开会流程为例:

1. 创建模型

2. 模型相关配置

【领导发起开会】
由于具体是哪个领导发起开会有不确定性(只要是领导都可以发起),所以需要设置代理人属性:
Assignee: ${leader}  -- 此处采用变量形式

为了方便后面的【开发人员签到】流程,我们还需要在【领导发起开会】流程处设置一个流程执行监听器(此操作不是必须,此处只是为了解释动态多实例),在Activiti中,配置监听器需要在模型和JAVA中都进行相应配置:
在JAVA中我们想要创建监听器只需要创建一个类,并实现系统监听器类 ExecutionListener 即可,代码如下:

package com.kenary.activiti.listener;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener; /**
* 自定义监听器
*/
public class MyExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) throws Exception { }
}

可见此时监听器没做任何处理,我们稍安勿躁。
接下来就是模型中的配置,由于我们想在领导指派了开会人员后进行监听,所以需要如下设置

其中 Event 代表事件触发类型,作用如其名
Class 代表监听器全路径,此处为 
com.kenary.activiti.listener.MyExecutionListener,则是之前创建的 MyExecutionListener
监听器配置完成后领导发起开会流程就配置完成了!

【开会人员签到】
相对于【领导发起开会】流程,【开发人员签到】流程则需要配置更多东西

其中,集合(Collection) 设置的是存储开会人员集合的变量名,注意:此处不需要${},并且 变量的值必须是 Collection的子类,即List、Set等

多实例类型 设置的是 并行、串行 等方式

  并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响。

  串行代表工作或任务由一个人完成后,再由另一个人去处理,直至全部完成,每个任务依赖于前一个任务完成。

元素变量(Element variable) 设置的是集合(Collection)每遍历一次设置的变量值的变量名,即迭代集合时存储集合里面单个元素的变量名,集合遍历时会根据内容创建任务

代理 设置的是处理该任务的用户,由于集合每遍历一次就创建了一个任务,所以这里和领导发起开会流程无太大差异,指定代理人即可,不过代理人员需要使用元素变量(Element variable)(Item 迭代的值)

至此,流程配置基本完成

3. 部署流程

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment; ......

private RepositoryService repositoryService;
......

Deployment deployment = repositoryService.createDeployment()
.name(modelData.getName())
.addString(processName, new String(bpmnBytes, "UTF-8"))
.deploy();
modelData.setDeploymentId("99999");
repositoryService.saveModel(modelData);

其中,99999 为模型id

4. 领导发起开会

import org.activiti.engine.RuntimeService;
.......
@Autowired
private RuntimeService runtimeService;
......

// 开始-》开启领导发起开会流程(指定领导)
Map<String,Object> p1 = new HashMap<>();
p1.put("leader","jjh");
runtimeService.startProcessInstanceByKey("10001",map);

其中,"jjh" 为设置的变量值,因为我内部通过用户名来区分,所以直接设置 jjh

 runtimeService.startProcessInstanceByKey("10001",map);   为启动流程,10001 为流程id

当这步执行完成后,我们来查询 属于 jjh 的任务

5. 开会人员签到
开会人员签到需要设置多个用户

import org.activiti.engine.TaskService;

.......
@Autowired
private TaskService taskService;
....... Map<String,Object> map = new HashMap<>();
map.put("assigneeList","jjh,yxc");
// 完成任务
teskService.complete("75167", map);

可以看见,我们的用户设置了多个,并且使用逗号隔开,但是刚才也介绍了 集合(Colloection) 必须是 Collection的子类,也就是 List、Set等,而String不是

所以此时可以回到监听器,并将其改为:

public class MyExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
String assigneeList = String.valueOf(delegateExecution.getVariable("assigneeList"));
if(assigneeList != null){
// 根据逗号分割并以数组形式重新设置进去
delegateExecution.setVariable("assigneeList", Arrays.asList(assigneeList.split(",")));
}
}
}

作用是将变量中的字符串根据逗号分割成了集合,其实此步骤完全多余,在设置变量时直接设置集合即可,但是为了顺带加上监听器的作用,所以则以此种方式说明

6. 效果预览

当任务执行后,我们分别看看 jjh 和 yxc 双用户的任务

可以看到,两个不同的用户的任务id是不相同的,所以他们不会互不干扰,Activiti动态多实例完成。

Activiti 用户任务并行动态多实例(多用户执行流程)的更多相关文章

  1. Activiti工作流学习(二)流程实例、执行对象、任务

    一.前言 前面说明了基本的流程部署.定义,启动流程实例等基本操作,下面我们继续来学习流程实例.执行对象.任务. 二.流程实例.执行对象说明 整个Activiti的生命周期经过了如下的几个步骤: 1.流 ...

  2. Slickflow.NET 开源工作流引擎基础介绍(七) -- 并行分支多实例模式实现

    前言:并行审批是比较常见的流程模式,在工作流模式介绍中,通常是多个分支通过网关(Gateway)来控制实现.默认的分支类型是静态定义好的.本文扩展了并行网关的控制方式,实现了动态多实例的并行分支网关, ...

  3. Activiti网关--并行网关

    1.什么是并行网关 并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进 入和外出顺序流的: fork 分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支. ...

  4. js的并行加载与顺序执行

    javaScript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能问 ...

  5. js并行加载,顺序执行

    js并行加载,顺序执行 <script>运行脚本或加载外部文件时,会阻塞页面渲染,阻塞其他资源的加载.如果页面中需要加载多个js文件,在古老浏览器中性能会比较糟糕. 因此有了最原始的优化原 ...

  6. JS 动态加载脚本 执行回调

    JS 动态加载脚本  执行回调 关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件 ...

  7. LAMP动态网站实例

    Zend Optimizer: 用优化代码的方法来提高PHP应用程序的执行速度.实现的原理是对那些在被最终执行之前由运行编译器(Run-Time Compiler)产生的代码进行优化.一般情况下,执行 ...

  8. Vue中通过Vue.extend动态创建实例

    Vue中通过Vue.extend动态创建实例 在Vue中,如果我们想要动态地来控制一个组件的显示和隐藏,比如通过点击按钮显示一个对话框或者弹出一条信息.我们通常会提前写好这个组件,然后通过v-if = ...

  9. C#反射动态创建实例并调用方法

    在.Net 中,程序集(Assembly)中保存了元数据(MetaData)信息,因此就可以通过分析元数据来获取程序集中的内容,比如类,方法,属性等,这大大方便了在运行时去动态创建实例. MSDN解释 ...

随机推荐

  1. SpringBoot笔记

    官网: http://springboot.fun/ 收集到一个比较全的: https://blog.csdn.net/xiaoyu411502/article/details/52474037 Id ...

  2. GlusterFS分布式存储数据的恢复机制(AFR)的说明

    GlusterFSFS恢复数据都是基于副本卷来说的,GlusterFSFS复制卷是采用镜像的方式做的,并且是同步事务性操作.简单来说就是,某一个客户要写文件时,先把这个文件锁住,然后同时写两个或多个副 ...

  3. Jenkins新建项目中源码管理Repository URL使用Git报错:Failed to connect to repository : Command "git ls-remote -h......

    之前部署了Gitlab+Gerrit+Jenkins持续集成环境,但在Jenkins中新建项目的源码管理"Repository URL"中添加git地址环节出现了问题,信息为&qu ...

  4. mysql外键关联

    主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的.所以说,如果谈到了外键,一定是至少涉及到两张表 ...

  5. how-is-docker-different-from-a-normal-virtual-machine[Docker与VirtualMachine的区别]

    https://stackoverflow.com/questions/16047306/how-is-docker-different-from-a-normal-virtual-machine 被 ...

  6. 携程Apollo配置中心架构深度剖析

    转自:http://www.uml.org.cn/wfw/201808153.asp 一.介绍 Apollo(阿波罗)[参考附录]是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在 ...

  7. number (1)eclipse 连接数据库报错 数据库信息不对导致的出错

  8. Fantacy团队周二站立会议

    词频分析模型 1.这次站会是周二开的,但是由于我个人的疏忽,哎,不说了. 2.会议时间:2016年3月29日12:03~12:30. 持续时长:27分钟 会议参加成员:组长:杨若鹏 http://ww ...

  9. TensorFlow中的优化算法

    搭建好网络后,常使用梯度下降类优化算法进行模型参数求解,模型越复杂我们在训练神经网络的过程上花的时间就越多,为了解决这一问题,我们就需要找一些优化算法来提高训练速度,TF的tf.train模块中提供了 ...

  10. SQL ROUND函数的使用

    SQL ROUND函数的使用   SQL ROUND函数是对数据进行制定精度的取值. 第一个参数是取值的数据,第二个参数是精度,第三个参数是数据取值模式(四舍五入还是截断),其中第三个参数是可选参数, ...