所谓多实例任务,就是一个任务,需要多个人协作完成,大致可以分为两种:

(1)并行多实例:完成任务没有先后顺序的要求,并行执行

(2)串行多实例:完成任务有先后顺序,也就是说,必须等待前一个人完成了任务,下一个人的           任务才开始

在流程图中也可以体现出并行多实例与串行多实例的区别,注意看领导审批节点,多了3条线,如果3条线是竖直的,那就是并行多实例,如下所示:

 如果3条线是水平的,那就是串行多实例,如下所示:

 bpmn文件的流程图,本质就是一个xml文件,普通的用户任务和多实例的任务区别如下:

    <userTask activiti:exclusive="true" id="_3" name="请假申请"/>
    <userTask activiti:assignee="${leader}" activiti:exclusive="true" id="_4" name="领导审批">
      <multiInstanceLoopCharacteristics activiti:collection="${leaderList}" activiti:elementVariable="leader" isSequential="true">
        <completionCondition><![CDATA[${nrOfInstances == nrOfCompletedInstances}]]></completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>

区别就在于多实例任务里面多了一个multiInstanceLoopCharacteristics 节点

 下面简单解释一些其含义:

  1. isSequential,为true表示是串行多实例,false表示是并行多实例
  2. activiti:collection,表示多实例的人员集合,${leaderList}是取变量leaderList的值
  3. activiti:elementVariable,人员集合中的元素变量,这里要UserTask中activiti:assignee的值对应,这里变量名称都是leader
  4. nrOfInstances,实例总数(nr是number的简写)
  5.  nrOfCompletedInstances,已完成的实例数
  6. completionCondition,表示多实例任务的完成条件

 下面以并行多实例为例,看看多实例任务的流转过程,下面是本次示例的流程图

 主要的xml如下:

  <process id="test_huiqian_2" isClosed="false" isExecutable="true" name="测试多实例会签" processType="None">
    <startEvent id="_2" name="StartEvent"/>
    <userTask activiti:assignee="${applyUser}" activiti:exclusive="true" id="_3" name="申请人确认">
      <extensionElements>
        <activiti:taskListener delegateExpression="${huiQianTaskListener}" event="complete"/>
      </extensionElements>
      <multiInstanceLoopCharacteristics activiti:collection="${applyUserList}" activiti:elementVariable="applyUser" isSequential="false">
        <completionCondition><![CDATA[${agreeCnt/nrOfInstances>=0.5}]]></completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>
    <exclusiveGateway gatewayDirection="Unspecified" id="_4" name="ExclusiveGateway"/>
    <userTask activiti:assignee="${leader}" activiti:exclusive="true" id="_5" name="领导审批"/>
    <exclusiveGateway gatewayDirection="Unspecified" id="_6" name="ExclusiveGateway"/>
    <endEvent id="_7" name="EndEvent"/>
    <sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_10" name="确认申请" sourceRef="_4" targetRef="_5">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${isApply == 'true'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_11" sourceRef="_5" targetRef="_6"/>
    <sequenceFlow id="_12" name="领导审批通过" sourceRef="_6" targetRef="_7">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leaderAudit == 'true'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_13" name="放弃申请" sourceRef="_4" targetRef="_7">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${isApply == 'false'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_14" name="领导审批不通过" sourceRef="_6" targetRef="_3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leaderAudit == 'false'}]]></conditionExpression>
    </sequenceFlow>
  </process>

注意到:

<completionCondition><![CDATA[${agreeCnt/nrOfInstances>=0.5}]]></completionCondition>

 说明只要有一半的人同意了,多实例任务就完成了,进入到下一个节点

启动流程

 启动流程,设置多实例任务的参与者:张三、李四、王五

       String key = "test_huiqian_2";
        // 申请人列表
        List<String> applyUserList = new ArrayList<>(3);
        applyUserList.add("张三");
        applyUserList.add("李四");
        applyUserList.add("王五");
        Map<String,Object> variables = new HashMap<>(1);
        variables.put("applyUserList",applyUserList);
        // 申请人同意的数量
        variables.put("agreeCnt",0);
        variables.put("isApply","false");
        // 启动流程
        runtimeService.startProcessInstanceByKey(key, variables);

启动流程后,进入到多实例任务,留意以下几张表的数据变化:

  1. 用户任务表,act_ru_task
  2. 节点执行表,act_ru_execution
  3. 用户与流程关联表,act_ru_identitylink
  4. 变量表,act_ru_variable

(1)用户任务表,act_ru_task,可以看到插入了3条数据,张三、李四、王五都有了待办任务

 (2)节点执行表,act_ru_execution,可以看到插入了5条数据,其中parent_id_为空的是父执行流,整个过程都会保留。而id_为120013的数据是活动节点的执行流,会根据流程的流转进行更新。剩下的3条数据就和act_ru_task表的3条数据一一对应了。

 (3)用户与流程关联表,act_ru_identitylink,插入了流程的参与者

 (4)变量表,act_ru_variable

 

完成多实例任务

  • 当张三完成任务后

act_ru_task表删除了张三的任务

 

但是,并没有删除act_ru_execution对应的数据,而是更新了版本号REV_和是否激活标志IS_ACTIVE

 

  • 当李四完成任务后

act_ru_task表删除了李四的任务

 同样的,并没有删除act_ru_execution对应的数据,而是更新了版本号REV_和是否激活标志IS_ACTIVE

  • 当王五完成任务后

 

 因为此时满足了多实例的完成条件,有50%以上的人同意了。所以删除了对应的act_ru_task和act_ru_execution表等数据

同时插入下一环节的数据到act_ru_task和act_ru_execution

 

 

 

 任务完成之后,act_ru开头的表都会被清空。

示例代码地址:https://github.com/qiuxinfa/activiti-study

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐