在实际的业务中,可能存在存在这么一种情况,当流程运行到某一个环节时,可能需要同时多个人的参与,才可以完成此环节。此时就可以用到activiti的多实例来解决此问题。

一、将一个节点设置成多实例的方法:

要把一个节点设置为多实例,节点xml元素必须设置一个multiInstanceLoopCharacteristics子元素。


    当isSequential=true时,表示的顺序执行,即虽然该节点有多条任务,但只有上一条执行完,才可以执行下一条。

当isSequential=false时,表示的并行执行,即该节点下的多条任务可以同时执行。

二、设置会签环节的参与者:

<strong>activiti:collection:用于执行该会签环节的参与参与的人,此处是使用的一个名叫pers的流程变量
</strong>
<strong>activiti:elementVariable:此处表示的是每一个分支都有一个名叫per的流程变量,和上方的activiti:assignee结合使用就可以执行该分支应该由谁来处理。</strong>

三.指定会签环节的结束条件:


     当画红线的部分返回一个true的时候,该会签环节结束。进入下一个流程执行的环节.

completionCondition中写的是juel表达式。其中的mulitiInstance如果是和spring整合了,就是spring管理的bean的id,否则就是流程变量的key.

四、会签环节中涉及的几个默认的流程变量

1.nrOfInstances 该会签环节中总共有多少个实例

   2.nrOfActiveInstances 当前活动的实例的数量,即还没有 完成的实例数量。

   3.nrOfCompletedInstances 已经完成的实例的数量

五、代码如下:

1.分配会签环节的人:

/**
* 分配下一环节会签的人
*
* @author huan
*
*/
public class AssgineeMultiInstancePer implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) throws Exception {
System.out.println("设置会签环节的人员.");
execution.setVariable("pers", Arrays.asList("张三", "李四", "王五", "赵六"));
}
}

2.多实例判断完成的条件:(注意:有于我没有和spring整合,所以此类要实现Serializable接口

/**
* 多实例完成的条件判断
* @author huan
*/
public class MulitiInstanceCompleteTask implements Serializable {
private static final long serialVersionUID = 1L;
public boolean completeTask(DelegateExecution execution) {
System.out.println("总的会签任务数量:" + execution.getVariable("nrOfInstances") + "当前获取的会签任务数量:" + execution.getVariable("nrOfActiveInstances") + " - " + "已经完成的会签任务数量:" + execution.getVariable("nrOfCompletedInstances"));
System.out.println("I am invoked.");
return false;
}
}

3.会签环节中的一个监听器:

/**
* 测试会签过程中监听器的执行情况
* @author huan
*/
public class TestLinstener implements TaskListener {
private static final long serialVersionUID = -5754522101489239675L;
@Override
public void notify(DelegateTask delegateTask) {
System.out.print(delegateTask.getId() + " - " + delegateTask.getProcessInstanceId() + " - " + delegateTask.getEventName() + " - " + delegateTask.getTaskDefinitionKey());
}
}

4.测试代码:

/**
* 测试会签
* @author huan
*/
public class TestMultiInstance {
@Test
public void testProcess() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
RuntimeService runtimeService = processEngine.getRuntimeService();
TaskService taskService = processEngine.getTaskService();
Deployment deploy = repositoryService.createDeployment()//
.name("会签流程测试")//
.addInputStream("multiInstances.bpmn", this.getClass().getResourceAsStream("multiInstances.bpmn"))//
.addInputStream("multiInstances.png", this.getClass().getResourceAsStream("multiInstances.png"))//
.deploy();
System.out.println(deploy.getId() + " " + deploy.getName());
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("mulitiInstance", new MulitiInstanceCompleteTask());
ProcessInstance pi = runtimeService.startProcessInstanceByKey("multiInstances",variables);
System.out.println(pi.getId() + " " + pi.getActivityId());
Task task1 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("张三").singleResult();
System.out.println(task1.getId() + " - " + task1.getAssignee() + " - " + task1.getProcessInstanceId() + " - " + task1.getProcessDefinitionId());
Task task2 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("李四").singleResult();
System.out.println(task2.getId() + " - " + task2.getAssignee() + " - " + task2.getProcessInstanceId() + " - " + task2.getProcessDefinitionId());
Task task3 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("王五").singleResult();
System.out.println(task3.getId() + " - " + task3.getAssignee() + " - " + task3.getProcessInstanceId() + " - " + task3.getProcessDefinitionId());
Task task4 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("赵六").singleResult();
if (task4 != null) {
System.out.println(task4.getId() + " - " + task4.getAssignee() + " - " + task4.getProcessInstanceId() + " - " + task4.getProcessDefinitionId());
}
Task task5 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("钱七").singleResult();
System.out.println(task5);
taskService.complete(task1.getId());
taskService.complete(task2.getId());
taskService.complete(task3.getId());
Task task6 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("钱七").singleResult();
System.out.println(task6);
taskService.complete(task4.getId());
Task task7 = taskService.createTaskQuery().processInstanceId(pi.getId()).taskAssignee("钱七").singleResult();
System.out.println(task7);
taskService.complete(task7.getId());
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(pi.getId()).singleResult();
if (null == processInstance) {
System.out.println("流程完成.");
}
}
}

5.流程文件:

<?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/test">
<process id="multiInstances" name="流程会签测试" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="A001"></sequenceFlow>
<serviceTask id="A001" name="设置下一环节的人" activiti:class="com.huan.activiti.liuyang.会签.AssgineeMultiInstancePer"></serviceTask>
<userTask id="B001" name="会签环节" activiti:assignee="${per}">
<extensionElements>
<activiti:taskListener event="complete" class="com.huan.activiti.liuyang.会签.TestLinstener"></activiti:taskListener>
</extensionElements>
<multiInstanceLoopCharacteristics isSequential="false" activiti:collection="pers" activiti:elementVariable="per">
<completionCondition>${mulitiInstance.completeTask(execution)}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<sequenceFlow id="flow2" sourceRef="A001" targetRef="B001"></sequenceFlow>
<userTask id="C001" name="会签后的环节" activiti:assignee="钱七"></userTask>
<sequenceFlow id="flow3" sourceRef="B001" targetRef="C001"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="C001" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_multiInstances">
<bpmndi:BPMNPlane bpmnElement="multiInstances" id="BPMNPlane_multiInstances">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="100.0" y="240.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="A001" id="BPMNShape_A001">
<omgdc:Bounds height="71.0" width="117.0" x="190.0" y="222.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="B001" id="BPMNShape_B001">
<omgdc:Bounds height="55.0" width="105.0" x="380.0" y="230.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="C001" id="BPMNShape_C001">
<omgdc:Bounds height="55.0" width="105.0" x="561.0" y="230.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="740.0" y="240.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="135.0" y="257.0"></omgdi:waypoint>
<omgdi:waypoint x="190.0" y="257.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="307.0" y="257.0"></omgdi:waypoint>
<omgdi:waypoint x="380.0" y="257.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="485.0" y="257.0"></omgdi:waypoint>
<omgdi:waypoint x="561.0" y="257.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="666.0" y="257.0"></omgdi:waypoint>
<omgdi:waypoint x="740.0" y="257.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

7.流程图:


  如若那个地方写的不对,欢迎指出。

activiti会签 多实例例子的更多相关文章

  1. activiti官网实例项目activiti-explorer之扩展流程节点属性2

    情景需求:需要查找activiti-explorer项目中获取流程id的方法,然后根据流程id获取相应字段在节点属性中添加内容. 大致流程:拿取整个流程id获取对应表单属性,在页面节点属性中展示对应表 ...

  2. Activiti的流程实例及挂起激活(七)

    1.1什么是流程实例 参与者(可以是用户也可以是程序)按照流程定义内容发起一个流程,这就是一个流程实例.是动态的.流程定义和流程实例的图解: 1.2启动流程实例 流程定义部署在 activiti 后, ...

  3. Activiti的流程实例【ProcessInstance】与执行实例【Execution】

    最近,我在做流程引擎Activiti相关的东西,刚开始时的一个知识点困扰了我许久,那就是Activiti的ProcessInstance与Execution的区别,这是一个Activiti的难点,能够 ...

  4. JSAAS的Activiti会签开发扩展处理

    1.什么是会签? 在流程业务管理中,任务是通常都是由一个人去处理的,而多个人同时处理一个任务,这种任务我们称之为会签任务.这种业务需求很常见,如一个请款单,领导审批环节中,就需要多个部门领导签字.在流 ...

  5. activiti并发多实例子流程任务处理

    一直在搞工作流(activiti),总结一下关于工作流(activiti)中同时并发处理多个子流程的操作方法. 先说下我要实现的业务: 1.办公室发通知(在系统申报页面上,勾选科室,被选中的科室执行第 ...

  6. activiti整合开发实例总结

    参考手册:http://www.mossle.com/docs/activiti/ 一.applicationContext.xml中引入activiti相关配置的xml文件 <!-- begi ...

  7. activiti官网实例项目activiti-explorer之获取流程节点

    如上图在保存步骤中添加获取节点信息方法nodes(); 方法如下: //获取所有节点    JsonNode modelNode = new ObjectMapper().readTree(repos ...

  8. activiti官网实例项目activiti-explorer实操详情

    参考链接:https://www.xuchuruo.cn/Activiti-modeler%E6%95%B4%E5%90%88%E5%88%B0Spring.html 按照链接文章提示操作完成之后,启 ...

  9. [UE4] C++实现Delegate Event实例(例子、example、sample)

    转自:http://aigo.iteye.com/blog/2301010 虽然官方doc上说Event的Binding方式跟Multi-Cast用法完全一样,Multi-Cast论坛上也有很多例子, ...

随机推荐

  1. RIAD配置

    一.RIAD 磁盘阵列介绍 二.阵列卡介绍 三.案例举例   一.RAID磁盘阵列介绍 是Redundant Array of Independent Disks的缩写,中文简称为独立冗余磁盘阵列 把 ...

  2. 注释swap分区

    grep  "#" fstab |grep "swap" >/dev/null || sed -i 's/^.*swap/#&/g' fstab

  3. JSON,XML设计模式详解

    JSON在Java中的应用: Json概念: json 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式用来存储和表示数据.JSON的语言简洁清晰,广为大众所欢迎,是一种理想的数据交换语言 ...

  4. PHP匿名类的用法

    在PHP7之后,PHP中加入了匿名类的特性.匿名类和匿名方法让PHP成为了更现代化的语言,也让我们的代码开发工作越来越方便.我们先来看看匿名类的简单使用. // 直接定义 $objA = new cl ...

  5. PHPCMS V9轻松完成WAP手机网站搭建全教程

    ---恢复内容开始--- 应用PHPCMS V9轻松完成WAP手机网站搭建全教程 用PHPCMS最新发布的V9搭建了PHPCMS研究中心网站(http://www.17huiyi.net)完成后,有用 ...

  6. Java面向对象系列(3)- 回顾方法的调用

    方法的调用 静态方法 非静态方法 形参和实参 值传递和引用传递 this关键字(继承篇讲解) 静态方法 非静态方法 形参和实参 package oop.demo01; public class Dem ...

  7. 鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行 | 百篇博客分析OpenHarmony源码 | v49.04

    百篇博客系列篇.本篇为: v49.xx 鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁 ...

  8. P2150-[NOI2015]寿司晚宴【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P2150 题目大意 将\(2\sim n\)选出一些分成两个集合,要求这两个集合中没有一对数不是互质的.求方案数对\ ...

  9. 常见JS

    1.获取当前月份第一天 var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; v ...

  10. LaTeX bib 引用为 作者 + 年份

    将bib文件命名为ref.bib %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%% @Description: %%%%%%%% @Version: 1.0 %%%% ...