文章目录

  • 1. 多实例
    • 1.1 流程设计
    • 1.2 测试类
    • 1.3 运行
      • 1.3.1 查询任务
      • 1.3.2 完成发起会议任务
      • 1.3.3 完成一个签到任务
      • 1.3.4 完成第二个签到任务
  • 2. 多实例-- 一票否决
    • 2.1 流程设计
    • 2.2 测试类
    • 2.3 运行
      • 2.3.1 查询任务
      • 2.3.2 完成发起会议任务
      • 2.3.3 完成一个签到任务
  • 源码地址
  • 项目推荐

Activiti中提供了多实例任务,多实例实在任务节点上添加额外的属性,使任务可以变成多实例,以下节点都可以添加:

  • User Task
  • Script Task
  • Java Service Task
  • Web Service Task
  • Business Rule Task
  • Email Task
  • Manual Task
  • Receive Task
  • (Embedded) Sub-Process
  • Call Activity

多实例内置变量

  • nrOfInstances:实例总数
  • nrOfActiveInstances:当前活动的实例数,对于顺序执行的多实例,值一直为1。
  • nrOfCompletedInstances:已经完成实例的数目。

*后台服务基于Springboot2 + Activiti6,整合文章请参考:https://blog.csdn.net/yy756127197/article/details/101211510 不需要流程设计器就排除3,4步骤 *

1. 多实例

1.1 流程设计

节点设置

说明:

  • Multi-instance type : 有两种类型,并行和串行
  • Collection(Multi-instance): 动态集合,根据变量传入
  • Completion condition(Multi-instance): 任务结束条件,默认全部完成
  • Element variable(Multi-instance): 遍历后每一项的别名
  • Cardinality(multi-instance) : 手动指定多实例循环几次

流程图

流程文件bpmn

<?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="http://www.activiti.org/processdef"><process id="multiInstance" name="多实例测试" isExecutable="true"><startEvent id="startEvent1"></startEvent><userTask id="task1" name="发起会议" activiti:assignee="admin"><extensionElements><modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete></extensionElements></userTask><sequenceFlow id="sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1" sourceRef="startEvent1" targetRef="task1"></sequenceFlow><userTask id="task2" name="会议签到" activiti:assignee="${user}"><extensionElements><modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete></extensionElements><multiInstanceLoopCharacteristics isSequential="false" activiti:collection="users" activiti:elementVariable="user"><completionCondition>${nrOfCompletedInstances/nrOfInstances &gt;= 0.5}</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id="sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC" sourceRef="task1" targetRef="task2"></sequenceFlow><endEvent id="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"></endEvent><sequenceFlow id="sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2" sourceRef="task2" targetRef="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_multiInstance"><bpmndi:BPMNPlane bpmnElement="multiInstance" id="BPMNPlane_multiInstance"><bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1"><omgdc:Bounds height="30.0" width="30.0" x="210.0" y="195.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="task1" id="BPMNShape_task1"><omgdc:Bounds height="80.0" width="100.0" x="375.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="task2" id="BPMNShape_task2"><omgdc:Bounds height="80.0" width="100.0" x="600.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529" id="BPMNShape_sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"><omgdc:Bounds height="28.0" width="28.0" x="795.0" y="196.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1" id="BPMNEdge_sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1"><omgdi:waypoint x="240.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="375.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC" id="BPMNEdge_sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC"><omgdi:waypoint x="475.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="600.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2" id="BPMNEdge_sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2"><omgdi:waypoint x="700.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="795.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

1.2 测试类

MultiInstanceTaskTest.java

import com.it.cloud.modules.activiti.service.IActReModelService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 多实例测试*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MultiInstanceTaskTest {@Autowiredprivate IActReModelService actReModelService;@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate TaskService taskService;@Autowiredprivate HistoryService historyService;/*** 部署流程定义*/@Testpublic void deploy() {Deployment deployment = repositoryService.createDeployment() // 创建部署.addClasspathResource("diagrams/multiInstance.bpmn20.xml") // 加载流程资源文件.name("multiInstance流程") // 流程名称.deploy(); // 部署System.out.println("流程部署ID:" + deployment.getId());System.out.println("流程部署Name:" + deployment.getName());}/*** 启动流程实例*/@Testpublic void start() {ProcessInstance pi = runtimeService.startProcessInstanceByKey("multiInstance"); // 流程定义表的KEY字段值System.out.println("流程实例ID:" + pi.getId());System.out.println("流程定义ID:" + pi.getProcessDefinitionId());}/*** 查看任务*/@Testpublic void queryTask() {List<Task> taskList = taskService.createTaskQuery() // 创建任务查询.taskAssignee("admin") // 指定某个人.list();for (Task task : taskList) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());}}/*** 完成任务*/@Testpublic void completeTask() {taskService.complete("42536");}/*** 完成任务2*/@Testpublic void completeTask2() {Map<String, Object> variables = new HashMap<String, Object>();variables.put("users", Arrays.asList("test1,test2,test3,test4".split(",")));taskService.complete("40005", variables);}
}

1.3 运行

运行deploy(),start()

1.3.1 查询任务

运行queryTask(),流程运行完服务任务,直接结束

效果:

1.3.2 完成发起会议任务

运行completeTask2(),设置变量users

效果:
数据表 ACT_RU_TASK

1.3.3 完成一个签到任务

运行completeTask()

效果:
数据表 ACT_RU_TASK

1.3.4 完成第二个签到任务

运行completeTask(),到达完成条件,流程结束

效果:
数据表 ACT_RU_TASK

2. 多实例-- 一票否决

2.1 流程设计

节点设置

说明:
跟前一个不同的地方在于完成条件,${nrOfCompletedInstances/nrOfInstances >= 0.5 || flag==false}
如果flag变量为false 就直接结束当前节点

流程图

流程文件bpmn

<?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="http://www.activiti.org/processdef"><process id="multiInstance-reject" name="多实例一票否决测试" isExecutable="true"><startEvent id="startEvent1"></startEvent><userTask id="task1" name="发起会议" activiti:assignee="admin"><extensionElements><modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete></extensionElements></userTask><sequenceFlow id="sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1" sourceRef="startEvent1" targetRef="task1"></sequenceFlow><userTask id="task2" name="会议签到" activiti:assignee="${user}"><extensionElements><modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete></extensionElements><multiInstanceLoopCharacteristics isSequential="false" activiti:collection="users" activiti:elementVariable="user"><completionCondition>${nrOfCompletedInstances/nrOfInstances &gt;= 0.5 || flag==false}</completionCondition></multiInstanceLoopCharacteristics></userTask><sequenceFlow id="sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC" sourceRef="task1" targetRef="task2"></sequenceFlow><endEvent id="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"></endEvent><sequenceFlow id="sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2" sourceRef="task2" targetRef="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_multiInstance-reject"><bpmndi:BPMNPlane bpmnElement="multiInstance-reject" id="BPMNPlane_multiInstance-reject"><bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1"><omgdc:Bounds height="30.0" width="30.0" x="210.0" y="195.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="task1" id="BPMNShape_task1"><omgdc:Bounds height="80.0" width="100.0" x="375.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="task2" id="BPMNShape_task2"><omgdc:Bounds height="80.0" width="100.0" x="600.0" y="170.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="sid-EA4EA283-C5CF-43C5-8401-E0BF40132529" id="BPMNShape_sid-EA4EA283-C5CF-43C5-8401-E0BF40132529"><omgdc:Bounds height="28.0" width="28.0" x="795.0" y="196.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1" id="BPMNEdge_sid-AB72BCEE-4568-4240-A4A8-23A79506CAC1"><omgdi:waypoint x="240.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="375.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC" id="BPMNEdge_sid-98BE643F-B247-46B2-94BA-EA9E06EBD9AC"><omgdi:waypoint x="475.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="600.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2" id="BPMNEdge_sid-BFD094C8-66EC-4ED2-8A35-0100E0B4E8B2"><omgdi:waypoint x="700.0" y="210.0"></omgdi:waypoint><omgdi:waypoint x="795.0" y="210.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

2.2 测试类

MultiInstanceRejectTaskTest.java

import com.it.cloud.modules.activiti.service.IActReModelService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 多实例测试*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MultiInstanceTaskTest {@Autowiredprivate IActReModelService actReModelService;@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate TaskService taskService;@Autowiredprivate HistoryService historyService;/*** 部署流程定义*/@Testpublic void deploy() {Deployment deployment = repositoryService.createDeployment() // 创建部署.addClasspathResource("diagrams/multiInstance.bpmn20.xml") // 加载流程资源文件.name("multiInstance流程") // 流程名称.deploy(); // 部署System.out.println("流程部署ID:" + deployment.getId());System.out.println("流程部署Name:" + deployment.getName());}/*** 启动流程实例*/@Testpublic void start() {ProcessInstance pi = runtimeService.startProcessInstanceByKey("multiInstance"); // 流程定义表的KEY字段值System.out.println("流程实例ID:" + pi.getId());System.out.println("流程定义ID:" + pi.getProcessDefinitionId());}/*** 查看任务*/@Testpublic void queryTask() {List<Task> taskList = taskService.createTaskQuery() // 创建任务查询.taskAssignee("admin") // 指定某个人.list();for (Task task : taskList) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());}}/*** 完成任务*/@Testpublic void completeTask() {taskService.complete("42536");}/*** 完成任务2*/@Testpublic void completeTask2() {Map<String, Object> variables = new HashMap<String, Object>();variables.put("users", Arrays.asList("test1,test2,test3,test4".split(",")));taskService.complete("40005", variables);}
}

2.3 运行

运行deploy(),start()

2.3.1 查询任务

运行queryTask(),流程运行完服务任务,直接结束

效果:

2.3.2 完成发起会议任务

运行completeTask2(),设置变量users

效果:
数据表 ACT_RU_TASK

2.3.3 完成一个签到任务

运行completeTask3(), 设置flag=dalse, 到达完成条件,流程结束

效果:
数据表 ACT_RU_TASK

这就实现了一票否决的效果,更多效果,可以设置完成条件来实现


源码地址

IT-CLOUD-ACTIVITI6
开源项目,持续更新中,喜欢请 Star~

项目推荐

IT-CLOUD :IT服务管理平台,集成基础服务,中间件服务,监控告警服务等。
开源项目,持续更新中,喜欢请 Star~

【弄nèng - Activiti6】Activiti6入门篇(七)—— 多实例任务相关推荐

  1. 【弄nèng - Skywalking】入门篇(二)—— Skywalking集群部署

    文章目录 一. 安装OAP 1.1 前置 1.2 下载 1.3 修改配置application.yml 1.4 高级部署 1.5 webapp配置 1.6 启动 二. 使用Agent 2.1 修改配置 ...

  2. 【弄nèng - Grafana】入门篇(十)—— Dashboard默认时间范围和刷新时间设置

    文章目录 1. Dashboard通用设置 General 2. 修改Dashboard默认时间范围 3. 修改某个Panel时间 项目推荐 Dashboard修改默认时间范围 1. Dashboar ...

  3. 算法入门篇七 前缀树

    牛客网 左程云老师的算法入门课 找二叉树的节点的后继节点 原则 如果节点有右子树,那么后继节点就是右子树的最左边的第一个节点 如果节点没有右子树,如果节点是父节点的右孩子,就继续往上找,直到找到一个父 ...

  4. 【弄nèng - SpringCloud】应用篇 —— 整合Zipkin【Finchley版】

    文章目录 1. Zipkin简介 2.术语 N. 插一杠子 N.1 下载Zipkin-server jar N.2 启动jar 3. 使用 3.1 it-zipkin-server 3.2 gatew ...

  5. 运动控制器编程_快速入门 | 篇二十一:运动控制器ZHMI组态编程简介一

    点击上方"正运动小助手",随时关注新动态! 运动控制器ZHMI组态编程简介一  今天我们来学习一下,运动控制器的ZHMI组态编程简介.本文主要从产品概述.控制器连接触摸屏使用.HM ...

  6. 明解C语言 入门篇 第七章练习题

    明解C语言 入门篇 第七章练习题 7-1 7-2 7-3 7-4 7-5 7-6 7-7(问题已解决) 7-8 7-9 7-10(此处借鉴了@野猪力量的代码) 7-11 7-1 #include &l ...

  7. EGE基础入门篇(七):组合图形

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(六):基本图形 下一篇:EGE基础入门篇(八):清屏与重绘 一. 组合图形 1. 复杂图形由基本图形组合而成   复杂的图形可以由基本图形组合而成,如 ...

  8. 【分享】 [教学]破解完全入门篇

    [分享] [教学]破解完全入门篇 3PtVw f   q85y)_c?   #r."#)pD   第一章--前言 /.$hZ$ q   好多哥们儿说看教程跟老大的书都看不太明白,所以,我尽量 ...

  9. C# 学习笔记入门篇(上)

    文章目录 C# 学习笔记入门篇 〇.写在前面 Hello World! 这篇学习笔记适合什么人 这篇学习笔记到底想记什么 附加说明 一.命名空间 "进入"命名空间 嵌套的命名空间. ...

  10. 每天15分钟JMeter入门篇(二):使用JMeter实现并发测试

    每天15分钟JMeter入门篇(一):Hello JMeter 每天15分钟JMeter入门篇(二):使用JMeter实现并发测试 每天15分钟JMeter入门篇(三):认识JMeter的逻辑控制器 ...

最新文章

  1. 从零搭建一套结构光3D重建系统[理论+源码+实践]
  2. string to xml java_Java String to XML - Parse String to XML DOM Example - 入门小站-rumenz.com
  3. wireshark tcp data中文_wireshark流量分析入门
  4. AWS — AWS Direct Connect
  5. C#中的get和post请求(工具类)
  6. jsp实现mysql存储过程_JSP调用MySQL存储过程收藏
  7. php csrf攻击 xss区别,用大白话谈谈XSS与CSRF
  8. 开源软件 cadsurf 阅读笔记
  9. 从物理服务器拷贝文件到容器,docker容器与物理机的文件传输—docker cp命令
  10. 手机浏览器网址_打开URL(在其他应用中访问网址)app下载-打开URL(在其他应用中访问网址)v2.6安卓版下载...
  11. 使用JSSDK分享页面
  12. c语言学习进阶-C语言程序稳定性测试
  13. cck8graphpad作图_Graphpad Prism 的 4 个隐藏技能助你轻松发表 SCI
  14. PAT:1031. 查验身份证(15) AC
  15. Linux文件压缩,解压常用命令
  16. java json.stringify_浅谈 JSON.stringify 方法
  17. word封面下划线对齐
  18. 【第十一篇】字体设置css变形(transfom)4种
  19. 微信{errcode:48001,errmsg:api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]}
  20. 撒罗满:2019年收集的最佳3D打印模型下载网站

热门文章

  1. 动态规划解决编辑距离问题
  2. 为什么你逃不脱打工被老板压榨的命运?
  3. selenium中,用xpath定位当前元素的相邻元素/兄弟元素
  4. cygwin补充安装软件包
  5. fiddler4如何只抓取指定浏览器的包
  6. Java生成唯一id的几种方式(已验证)
  7. Gnocchi 8、sacks基础
  8. 计算机“字符”,“字节”以及各单位说明
  9. html无序列表位置改变,如何设置子无序列表的位置?
  10. 一些Eclipse快捷键(超实用)