首页 > 其他分享 >Flowable 任务如何认领,回退?

Flowable 任务如何认领,回退?

时间:2022-10-12 16:31:53浏览次数:50  
标签:RU task javaboy Flowable list 如下 认领 ACT 回退

有的时候,一个任务节点会存在多个候选人,例如 zhangsan 提交一个任务,这个任务即可以 lisi 处理,又可以 wangwu 处理,那么针对这种多个任务候选人的情况,我们该如何处理?今天一起来看看。

1\. 绘制流程图

首先我们还是使用之前旧的流程图,但是在为 UserTask 设置分配用户的时候,我们设置多个用户,如下图:

Flowable 任务如何认领,回退?_ide

设置完成后,我们下载这个流程文件,来看下对应的 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 三个用户处理,用户名之间用 ​​,​​ 隔开。

2\. 查询任务处理人

接下来我们部署并启动上面这个流程,具体如何部署如何启动,这个在之前的文章中松哥已经和大家聊过了,这里不再赘述。

当流程启动成功之后,现在我们很容易想到像之前文章那样,去查询 javaboy 需要处理的 UserTask,如下:

List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
for (Task task : list) {
logger.info("id:{};name:{};taskDefinitionKey:{}", task.getId(), task.getName(), task.getTaskDefinitionKey());
}

但是我们却发现这个 SQL 执行完成后,查询不到任何数据!为什么呢?我们来分析下。

经过前面几篇文章的介绍,现在小伙伴们都知道了,上面这个方法最终查询的是数据库中的 ​​ACT_RU_TASK​​ 表,查询的 SQL 如下:

Flowable 任务如何认领,回退?_java_02

那我们就去检查 ​​ACT_RU_TASK​​ 表以及它的 ​​ASSIGNEE_​​ 字段,结果如下:

Flowable 任务如何认领,回退?_java_03

我们发现 ​​ACT_RU_TASK​​ 表中记录的 ​​ASSIGNEE_​​ 字段值为 null!

为 null 这个其实也好理解,毕竟这个 UserTask 有多个人可以处理,但是只有一个字段,没法储存,肯定有其他存储方式。

好啦,不和大家卖关子了,这种有多个候选人的任务,我们应该按照如下方式来查询:

@Test
void test12() {
List<Task> list = taskService.createTaskQuery().taskCandidateUser("javaboy").list();
for (Task task : list) {
logger.info("id:{};name:{};taskDefinitionKey:{}", task.getId(), task.getName(), task.getTaskDefinitionKey());
}
}

小伙伴们看到,这里应该调用 ​​taskCandidateUser​​ 方法进行处理。那么这个方法查询的是哪张表呢?我们来看下上面方法最终执行的 SQL,如下:

: ==>  Preparing: SELECT RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ is null and exists(select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TYPE_ = 'candidate' and LINK.TASK_ID_ = RES.ID_ and ( LINK.USER_ID_ = ? ) ) order by RES.ID_ asc
: ==> Parameters: javaboy(String)
: <== Total: 1

小伙伴们看到,这里的查询涉及到两张表,分别是 ​​ACT_RU_TASK​​ 和 ​​ACT_RU_IDENTITYLINK​​,两张表联合查询查出来的,那我们来看看 ​​ACT_RU_IDENTITYLINK​​ 表的内容:

Flowable 任务如何认领,回退?_java_04

小伙伴们看到,​​TYPE_​​ 为 candidate 的就表示这个 Task 的候选人,id 为 ​​c5693038-3f42-11ed-b9e2-acde48001122​​ 的 Task 一共有三个候选人,两张表联合查询,才可以查到这个 UserTask 该由谁来处理。

另外一种常见的需求就是,已经知道了要处理的流程实例了,但是不知道应该由谁来处理,此时通过查询 ​​ACT_RU_IDENTITYLINK​​ 表就可以确定一个流程实例都有哪些参与者,如下:

@Test
void test13() {
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
for (ProcessInstance pi : list) {
List<IdentityLink> identityLinksForProcessInstance = runtimeService.getIdentityLinksForProcessInstance(pi.getId());
for (IdentityLink identityLink : identityLinksForProcessInstance) {
logger.info("ProcessInstanceId:{},UserId:{}",identityLink.getProcessInstanceId(),identityLink.getUserId());
}
}
}

我们来看看上面这个执行的 SQL,如下:

Flowable 任务如何认领,回退?_java_05

可以看到,其实就是通过查询 ​​ACT_RU_IDENTITYLINK​​ 表获取我们想要的数据。

3\. 认领任务

对于这种有候选人的任务,我们需要先认领,再处理。认领的本质,其实就是给 ​​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​​ 表中的数据,如下:

Flowable 任务如何认领,回退?_java_06

可以看到,此时 ​​ASSIGNEE_​​ 字段就有值了,同时 ​​CLAIM_TIME​​ 字段也记录了任务的认领时间。

再来看看任务认领执行的 SQL,基本上和我们所想的一致。

Flowable 任务如何认领,回退?_java_07

4\. 处理任务

认领后的任务该如何处理,这个就和我们上篇文章中介绍的方式一致了,如下:

@Test
void test11() {
List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
for (Task task : list) {
taskService.complete(task.getId());
}
}

具体原理上篇文章中已经介绍过了,这里就不再赘述了。

任务执行完成后,​​ACT_RU_IDENTITYLINK​​ 表中的记录也会随之删除。

5\. 变量与监听器

前面这种方式设置的任务候选人我们是在绘制流程图的时候直接硬编码的,这显然不是一个好办法。如果能通过变量来传递任务的候选人,就会方便很多。

5.1 候选人变量

我们可以在绘制流程图的时候,用变量代替直接指定候选人,方式如下:

Flowable 任务如何认领,回退?_java_08

此时,生成的流程 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());
}

多个用户之间,用英文 ​​,​​ 隔开。

好了,流程启动成功后,接下来的操作参考 3、4 小节,这里我就不再赘述了。

5.2 监听器

当然,我们也可以通过监听器来为 UserTask 设置多个候选处理人用户,首先我们创建一个监听器如下:

public class MyUserTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
delegateTask.addCandidateUser("javaboy");
delegateTask.addCandidateUser("zhangsan");
delegateTask.addCandidateUser("lisi");
}
}

然后在绘制流程图的时候,删除掉 UserTask 分配的用户,然后重新为 UserTask 设置一个监听器:

Flowable 任务如何认领,回退?_2d_09

然后设置一个在创建 UserTask 的时候触发的监听器:

Flowable 任务如何认领,回退?_java_10

然后我们下载这个流程图对应的 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 指定了额外的监听器。

好啦,这个流程现在就可以直接启动了,启动时也不需要额外的变量。

流程启动成功后,接下来的操作参考 3、4 小节,这里我就不再赘述了。

6\. 任务回退

当一个任务认领(Claim)之后,但是又不想处理,此时我们可以将任务退回。方式如下:

@Test
void test16() {
List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
for (Task task : list) {
taskService.setAssignee(task.getId(), null);
}
}

其实思路很简答,就是重新为任务设置处理人,且处理人为 null,这就是将任务回退了,接下来其他人可以重新认领该任务了。

7\. 修改任务候选人

7.1 增加

任务候选人也不是一成不变的,也可以动态修改,当一个流程启动之后,流程已经走到某一个 Task 了,此时我们想要修改该 Task 的候选人,也是可以的,方式如下:

@Test
void test17() {
List<Task> list = taskService.createTaskQuery().taskCandidateUser("javaboy").list();
for (Task task : list) {
taskService.addCandidateUser(task.getId(),"wangwu");
}
}

添加完成后,查看 ​​ACT_RU_IDENTITYLINK​​ 表,我们发现 wangwu 已经添加进来了:

Flowable 任务如何认领,回退?_ide_11

7.2 删除

如果想要删除一个候选人,方式如下:

@Test
void test18() {
List<Task> list = taskService.createTaskQuery().taskCandidateUser("javaboy").list();
for (Task task : list) {
taskService.deleteCandidateUser(task.getId(), "wangwu");
}
}

删除成功之后,​​ACT_RU_IDENTITYLINK​​ 表中对应的数据也就被清除掉了。

8\. 查询历史数据

如果一个流程执行结束了,我们还想查询这个流程曾经涉及到的参与者,可以通过如下方式查询:

@Test
void test14() {
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().list();
for (HistoricProcessInstance historicProcessInstance : list) {
List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForProcessInstance(historicProcessInstance.getId());
for (HistoricIdentityLink link : links) {
logger.info("userId:{},taskId:{},type:{},processInstanceId:{}",link.getUserId(),link.getTaskId(),link.getType(),link.getProcessInstanceId());
}
}
}

这里最终其实就是去 ​​ACT_HI_IDENTITYLINK​​ 表中查询,对应的 SQL 如下:

Flowable 任务如何认领,回退?_java_12

上面这是查询一个流程的参与人,当然我们也可以查询一个 Task 的候选人与处理人,如下:

@Test
void test15() {
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().list();
for (HistoricTaskInstance historicTaskInstance : list) {
List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(historicTaskInstance.getId());
for (HistoricIdentityLink link : links) {
logger.info("userId:{},taskId:{},type:{},processInstanceId:{}", link.getUserId(), link.getTaskId(), link.getType(), link.getProcessInstanceId());
}
}
}

查询对应的 SQL 如下:

Flowable 任务如何认领,回退?_ide_13

和我们所想的基本一致。

标签:RU,task,javaboy,Flowable,list,如下,认领,ACT,回退
From: https://blog.51cto.com/u_15773567/5749114

相关文章

  • Flowable 设置任务处理人的四种方式
    UserTask看名字就知道,需要人工干预,而人工处理的方式有很多种,我们可以设置节点是由哪个用户处理,也可以设置是由哪个用户组来处理(相当于是由哪个角色来处理),今天这篇文章我主......
  • uniapp 实现回退监听 弹出提示 小程序与H5已解决
    H5小程序<!--退出填写提示框--><view>自定义提示框<viewv-if="outTipsShow"></view></view>//退出填写提示框......
  • 玩转 Flowable 流程实例
    文章目录​​1.捋清三个概念​​​​2.五种流程启动方式​​​​3.简单实践​​​​4.删除流程实例​​​​5.获取运行的活动节点​​​​上篇文章​​松哥和大家聊了......
  • git回退到某个提交
    git是一个分布式版本控制软件,分布式版本库的做法使源代码的发布和交流都极为方便,因此有不少用户都在使用git。最近小编也正在学习git这款软件,发现要想熟练运用git,学会git中......
  • git commit之后,回退方法
     原文 写完代码后,我们一般这样gitadd.//添加所有文件gitcommit-m"本功能全部完成" 执行完commit后,想撤回commit,怎么办? 这样凉拌:gitreset--softHE......
  • Git 版本回退
    第一步:gitcheckout[分支名]切换到要操作的分支上;第二步:gitlog查看历史提交记录,找到想要回退的版本号;第三步:gitreset--hard[版本号]将本地仓库代码回退到指定版......
  • flowable初体验踩坑及概述
    遵守bpmn2.0协议(前提)(还在找比较好用的绘图工具)可以使用idea插件进行绘图保存成xml进行改造编写FlowableBPMNvisualizer和JBossjBPM,暂时使用的是idea的这两个......
  • git reset 回退版本
    -先模拟提交过程,一共提交四次,每次都向文本里写一个新数#向文本中写入0$echo0>a.t$gitadd.#第一次提交到仓库$gitcommit-m'0'#向文本中写入1$echo1......
  • Docker系列---【Docker中启动flowable查看流转日志时字体显示方框问题】
    1.问题描述我用了flowable,在本地测试没问题,在linux环境也没问题,在docker中启动发现流程图字体显示有问题,显示方框。2.原因分析因为flowable返回的直接是图片,直......
  • Git版本回退
    转自:https://www.liaoxuefeng.com/wiki/896043488029600/8970135735121921.reset命令--hard参数首先查看commit记录,myproj%gitlogcommit7ce989d2294aeede765a479......