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

Activiti 用户任务并行动态多实例(多用户执行流程)

程序员文章站 2022-08-12 09:05:52
在很多情况下,我们需要多用户共同执行余下流程,比如开会流程: 如果只使用代理(Assignee、Candidate users、Candidate groups) 将无法解决上述问题,因为即使使用 Candidate users ,但每个用户实际上还是在一个任务里面,其中一个用户完成任务,另外的用户 ......

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

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

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


以上面开会流程为例:

1. 创建模型

Activiti 用户任务并行动态多实例(多用户执行流程)

2. 模型相关配置

【领导发起开会】
由于具体是哪个领导发起开会有不确定性(只要是领导都可以发起),所以需要设置代理人属性:
assignee: ${leader}  -- 此处采用变量形式
Activiti 用户任务并行动态多实例(多用户执行流程)
Activiti 用户任务并行动态多实例(多用户执行流程)
为了方便后面的【开发人员签到】流程,我们还需要在【领导发起开会】流程处设置一个流程执行监听器(此操作不是必须,此处只是为了解释动态多实例),在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 {

    }
}

可见此时监听器没做任何处理,我们稍安勿躁。
接下来就是模型中的配置,由于我们想在领导指派了开会人员后进行监听,所以需要如下设置
Activiti 用户任务并行动态多实例(多用户执行流程)

Activiti 用户任务并行动态多实例(多用户执行流程)

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

 

【开会人员签到】
相对于【领导发起开会】流程,【开发人员签到】流程则需要配置更多东西
Activiti 用户任务并行动态多实例(多用户执行流程)

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

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

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

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

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

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

 

至此,流程配置基本完成

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 的任务

Activiti 用户任务并行动态多实例(多用户执行流程)

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 双用户的任务

Activiti 用户任务并行动态多实例(多用户执行流程)

Activiti 用户任务并行动态多实例(多用户执行流程)

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