一.简介
有的时候,一个任务节点会存在多个候选人,例如:张三提交一个任务,这个任务即可以由李四处理,又可以由王五处理,那么针对这种多个任务候选人的情况,该如何处理?
二.绘制流程图
首先我们还是使用之前旧的流程图,但是在为 UserTask 设置分配用户的时候,我们设置多个用户,流程图截图如下:
分配图截图如下:
设置完成后,载这个流程文件,该流程对应的XML文件,内容如下:
<process id="demo01" name="demo01" isExecutable="true">
<documentation>demo01</documentation>
<startEvent id="startEvent1" flowable:initiator="INITATOR" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:candidateUsers="javaboy,zhangsan,lisi" flowable:formFieldValidation="true"></userTask>
<sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
<endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
<sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>
可以看到,UserTask 中的 flowable:candidateUsers=“javaboy,zhangsan,lisi” 就表示这个 UserTask 由 javaboy、zhangsan 和 lisi 三个用户处理,用户名之间用 , 隔开。
三.认领任务
对于这种有候选人的任务,我们需要先认领,再处理。认领的本质,其实就是给 ACT_RU_TASK 表中,这个 UserTask 记录的 ASSIGNEE_ 字段设置上值。代码如下:
@Test
void test12() {
List<Task> list = taskService.createTaskQuery().taskCandidateUser("javaboy").list();
for (Task task : list) {
taskService.claim(task.getId(),"javaboy");
}
}
认领之后,再来看下 ACT_RU_TASK 表中的数据,截图如下:
可以看到,此时 ASSIGNEE_ 字段就有值了,同时 CLAIM_TIME 字段也记录了任务的认领时间。
再来看任务认领执行的 SQL,截图如下:
四.处理任务
认领后的任务该如何处理,代码如下:
@Test
void test11() {
List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
for (Task task : list) {
taskService.complete(task.getId());
}
}
任务执行完成后,ACT_RU_IDENTITYLINK 表中的记录也会随之删除。
五.变量与监听器
前面这种方式设置的任务候选人我们是在绘制流程图的时候直接硬编码的,这显然不是一个好办法。如果能通过变量来传递任务的候选人,就会方便很多。
1.候选人变量
在绘制流程图的时候,用变量代替直接指定候选人,截图如下:
此时,生成的流程 XML 文件中,UserTask 节点的处理人内容如下:
<process id="demo01" name="demo01" isExecutable="true">
<documentation>demo01</documentation>
<startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:candidateUsers="${userIds}" flowable:formFieldValidation="true"></userTask>
<sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
<endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
<sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>
UserTask 节点中的 flowable:candidateUsers=“${userIds}” 就表示流程的处理人由 userIds 变量控制。
接下来启动流程,注意,此时启动流程需要传递 userIds 变量,代码如下:
@Test
void test01() {
Map<String, Object> userIds = new HashMap<>();
userIds.put("userIds", "javaboy,zhangsan,lisi");
ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01",userIds);
logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}
多个用户之间,用英文 , 隔开。
流程启动成功后,接下来的操作参考 三、四 点。
2.监听器
也可以通过监听器来为 UserTask 设置多个候选处理人用户,首先我们创建一个监听器,代码如下:
public class MyUserTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
delegateTask.addCandidateUser("javaboy");
delegateTask.addCandidateUser("zhangsan");
delegateTask.addCandidateUser("lisi");
}
}
然后在绘制流程图的时候,删除掉 UserTask 分配的用户,然后重新为 UserTask 设置一个监听器,截图如下:
然后设置一个在创建 UserTask 的时候触发的监听器,截图如下:
下载这个流程图对应的 XML 文件,内容如下:
<process id="demo01" name="demo01" isExecutable="true">
<documentation>demo01</documentation>
<startEvent id="startEvent1" flowable:initiator="INITATOR" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:formFieldValidation="true">
<extensionElements>
<flowable:taskListener event="create" class="org.javaboy.flowableidm.MyUserTaskListener"></flowable:taskListener>
</extensionElements>
</userTask>
<sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
<endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
<sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>
可以看到,在 userTask 节点中,通过 extensionElements 指定了额外的监听器。
这个流程可以直接启动了,启动时也不需要额外的变量。
流程启动成功后,接下来的操作参考 三、四 点。