Activiti5入门--组任务分配

在上一章中,我们学习了个人任务分配的相关知识,本章,我们将学习组任务分配的相关知识。

和前面一样,我们新建包cn.demo.grouptask,新建类TaskTest.java以及流程图文件task.bpmn

定义审批流程

为了方便学习,我们同样定义一个审批流程。不同于个人任务的是,该审批流程的办理人不是一个人,而是好几个人,除此以外,其它方面和个人任务审批流程是一样的。

组任务审批流程

三种方式指定用户任务

和个人任务一样,组任务也有三种分配方式

  1. 直接指定办理人,即直接设置用户任务Assignee字段的值
  2. 使用流程变量,通过流程变量动态指定办理人的值
  3. 使用实现org.activiti.engine.delegate.TaskListener接口的类方法来动态指定办理人

下面,我们一一讲解。

直接指定办理人

现在,我们先来直接指定办理人,在个人任务中,我们直接指定办理人时,设置的是字段Assignee的值,而现在,若要设置组任务的办理人,则需要设置字段Candidate-user的值,并且办理人之间使用英文逗号分隔。

组任务直接指定办理人

一切准备好之后,我们开始部署流程定义以及启动流程实例。

部署流程定义

和前面一样,我们按如下部署流程定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 部署流程定义
*/
@Test
public void deploymentProcessDefinition() {
InputStream inputStreamBpmn = this.getClass().getResourceAsStream("task.bpmn");
InputStream inputStreamPng = this.getClass().getResourceAsStream("task.png");
Deployment deploy = processEngine.getRepositoryService()
.createDeployment() // 创建一个部署对象
.name("任务") // 添加部署的名称
.addInputStream("task.bpmn", inputStreamBpmn)
.addInputStream("task.png",inputStreamPng)
.deploy(); // 完成部署
System.out.println("部署ID: " + deploy.getId());
System.out.println("部署名称: " + deploy.getName());
}

运行代码,输出如下结果

部署ID: 6101
部署名称: 任务

此时,流程定义已经部署好了,接下来就是启动流程实例了。

启动流程实例

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 启动流程实例
*/
@Test
public void startProcessInstance() {
// 流程定义的key
String processDefinitionKey = "task";
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey);
System.out.println("流程实例ID: " + processInstance.getId());
System.out.println("流程定义ID: " + processInstance.getProcessDefinitionId());
}

运行代码,输出如下结果

流程实例ID: 6201
流程定义ID: task:4:6104

此时,我们查询一下act_ru_task(正在执行的任务表)

正在执行的任务1

组任务正在执行的任务2

可以看到,和个人记录不一样的是,该记录的Assignee字段的内容为空

我们查询另外一张表act_ru_identitylink(任务办理人表,个人任务,组任务)

组任务的任务表

可以看到,该表USER_ID字段的小A,小B,小C和小D就是我们在组任务审批流程中指定的任务办理人,只是,对于他们每一个人,该表中都存在两条数据

  1. 当字段TYPE_的值为candidate 时,TASK_ID的值不为空
  2. 当字段TYPE_的值为participant是,PROC_INST_ID的值不为空

我们查询act_hi_identitylink(历史任务办理人表,个人任务,组任务)

历史任务办理人表

在这张表的数据包括了以往的所有历史办理人,对于个人任务办理人来说,其字段TYPE的值都为participant,而对于组任务办理人来说,其TYPE值为participantcandidate的记录都存在。

查询任务

现在,我们暂时把目光转移到查询任务上来。我们查询一下小A的任务,查询方法还是使用taskAssignee(assignee)方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void findMyPersonalTask() {
String assignee = "小A";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskAssignee(assignee) // 指定个人任务,指定办理人
/*排序*/
.orderByTaskCreateTime().asc()
.list();
// 存储在act_ru_task表
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

执行代码,毫无疑问地,由于查询个人任务本质上是查询act_ru_task(正在执行的任务表),而该表中表示任务办理人ASSIGNEE_字段的值为空,因此,我们无法查询到任何数据。

此时,我们应该查询某个人的组任务,而不是个人任务。为了查询某个人的组任务,我们使用taskCandidateUser(assignee)方法替换taskAssignee(assignee)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 查询当前人的组任务
*/
@Test
public void findMyGroupTask() {
String assignee = "小A";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskCandidateUser(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
// 存储在act_ru_task表
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

执行代码,我们就得到了小A的组任务详细信息了

任务ID: 6204
任务名称: 审批
任务的创建时间: Mon Oct 29 21:30:55 CST 2018
任务的办理人: null
流程实例ID: 6201
执行对象ID: 6201
流程定义ID: task:4:6104

接着上一节,我们来查询任务办理人,包括历史的还是正在执行的办理人。先查正在执行的任务办理人表

查询正在执行的任务办理人

对于查询正在执行的任务办理人来说,我们自然而然地想到使用taskService的方法来查询,通过getIdentityLinksForTask(taskId)方法,传入taskId,我们可以查询到正在执行的任务办理人信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 查询正在执行的任务办理人表
*/
@Test
public void findRunPersonTask() {
String taskId = "6204";
List<IdentityLink> list = processEngine.getTaskService().getIdentityLinksForTask(taskId);
if (list != null && list.size() > 0) {
for (IdentityLink identityLink : list) {
System.out.println("任务Id:" + identityLink.getTaskId());
System.out.println("办理人类型:" + identityLink.getType());
System.out.println("流程实例Id:" + identityLink.getProcessInstanceId());
System.out.println("用户Id:" + identityLink.getUserId());
System.out.println();
}
}
}

运行代码,可以得到如下结果

任务Id:6204
办理人类型:candidate
流程实例Id:null
用户Id:小A

任务Id:6204
办理人类型:candidate
流程实例Id:null
用户Id:小C

任务Id:6204
办理人类型:candidate
流程实例Id:null
用户Id:小B

任务Id:6204
办理人类型:candidate
流程实例Id:null
用户Id:小D

可以看到,查询到的是TYPE_值为candidate的记录信息

查询历史任务办理人

与查询正在执行的任务办理人不同,对于查询历史任务办理人,我们使用的是historyService服务,我们既可以通过任务Id来查询,也可以通过流程实例Id来查询,这里我们使用流程实例Id来完成查询操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void findHistoryPersonTask() {
// 流程实例Id
String processInstanceId = "6201";
List<HistoricIdentityLink> list = processEngine.getHistoryService()
.getHistoricIdentityLinksForProcessInstance(processInstanceId);
if(list!=null && list.size()>0) {
for (HistoricIdentityLink historicIdentityLink : list) {
System.out.println("任务Id:" + historicIdentityLink.getTaskId());
System.out.println("办理人类型:" + historicIdentityLink.getType());
System.out.println("流程实例Id:" + historicIdentityLink.getProcessInstanceId());
System.out.println("用户Id:" + historicIdentityLink.getUserId());
System.out.println();
}
}
}

运行代码,得到如下结果

任务Id:null
办理人类型:participant
流程实例Id:6201
用户Id:小A

任务Id:null
办理人类型:participant
流程实例Id:6201
用户Id:小C

任务Id:null
办理人类型:participant
流程实例Id:6201
用户Id:小B

任务Id:null
办理人类型:participant
流程实例Id:6201
用户Id:小D

可以预料到,若我们使用任务Id来查询历史任务办理人,则办理人类型为candidate,同时任务Id将不为空,流程实例Id则相反,其值将为空。

拾取任务

虽然我们定义的是组任务,但是,我们还是需要将任务分配给某个人处理,因此,我们需要使用taskServiceclaim(taskId,userId)方法来拾取任务(认领任务),即将任务分配给个人。在分配任务时,可以分配组任务给非组任务的成员。在这里,我们指定给大F

1
2
3
4
5
6
7
8
9
10
11
/**
* 拾取任务,将组任务分配给个人任务,指定任务办理人Assignee字段
*/
@Test
public void claim() {
String taskId = "6204";
// 分配个人任务(可以是组任务的成员,也可以是非组任务的成员)
String userId = "大F";
processEngine.getTaskService()
.claim(taskId, userId);
}

若没有异常,我们查询act_ru_task(正在执行的任务表),可以看到ASSIGNEE_字段的值不为空,其值为大F

拾取任务

此时,我们若查询大F的个人任务,将能够获取到大F个人任务的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 查询当前人的组任务
*/
@Test
public void findMyPersonTask() {
String assignee = "大F";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskAssignee(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

运行代码,得到如下结果

任务ID: 6204
任务名称: 审批
任务的创建时间: Mon Oct 29 21:30:55 CST 2018
任务的办理人: 大F
流程实例ID: 6201
执行对象ID: 6201
流程定义ID: task:4:6104

可以看到,我们确实能够查询到大F的个人任务信息,但是,使用其他人去查询是获取不到的。

查询一下act_ru_identitylink(正在执行任务办理人表)

正在执行任务-拾取任务

再查询一下act_hi_identitylink(历史任务办理人表)

历史任务办理人-拾取任务

可以看到,两张表中的关于大F的记录都只有一条,且其TYPE_的值为participant,这说明该任务已经成为大F的个人任务。

回退任务

若大F不愿意处理该任务,我们可以通过设置办理人的值为空值回退任务。

1
2
3
4
5
6
7
8
9
/**
* 将个人任务回退到组任务,前提,之前一定是组任务
*/
@Test
public void setAssigneeTask() {
String taskId = "6204";
processEngine.getTaskService()
.setAssignee(taskId, null);
}

若我们此时查询act_ru_task(正在执行的任务表),则可以发现ASSIGNEE_字段的值为空,此时我们无法查询到大F的个人任务了,个人任务重新成为组任务,当然,可以这样操作是建立在该任务之前是组任务的基础之上的。

添加组任务成员

除了上述拾取任务外,我们还可以添加和删除组任务成员,下面我们先添加组任务成员大H

1
2
3
4
5
6
7
8
9
10
/**
* 向组任务中添加成员
*/
@Test
public void addGroupUser(){
String taskId = "6204";
String userId = "大H";
processEngine.getTaskService()
.addCandidateUser(taskId, userId);
}

查询act_ru_identitylink(正在执行的任务办理人表),我们看到数据表添加了两条关于大H的记录

添加任务成员

删除组任务成员

现在,我们删除组任务成员小B

1
2
3
4
5
6
7
8
9
10
/**
* 从组任务删除成员
*/
@Test
public void deleteGroupUser(){
String taskId = "6204";
String userId = "小B";
processEngine.getTaskService()
.deleteCandidateUser(taskId, userId);
}

查询act_ru_identitylink(正在执行的任务办理人表)

删除组任务成员

数据表数据显示,小B还保留了一条TYPE字段值为participant类型的记录。此时,我们查询小B的组任务,无法查到该记录,说明在act_ru_identitylink(正在执行的任务办理人表)中,TYPE_字段的值为candidate的记录将用于查询组任务。

现在,我们让小A来拾取任务

1
2
3
4
5
6
7
8
@Test
public void claim() {
String taskId = "6204";
// 分配个人任务(可以是组任务的成员,也可以是非组任务的成员)
String userId = "小A";
processEngine.getTaskService()
.claim(taskId, userId);
}

这样,组任务就被重新分配给了个人,于是,我们可以查询到小A的个人任务了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 查询当前人的组任务
*/
@Test
public void findMyPersonTask() {
String assignee = "小A";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskAssignee(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

运行代码,我们获得小A个人任务的详细信息

任务ID: 6204
任务名称: 审批
任务的创建时间: Mon Oct 29 21:30:55 CST 2018
任务的办理人: 小A
流程实例ID: 6201
执行对象ID: 6201
流程定义ID: task:4:6104

然后,我们完成小A任务

1
2
3
4
5
6
7
8
9
/**
* 完成我的任务
*/
@Test
public void completeMyPersonalTask() {
String taskId = "6204";
processEngine.getTaskService().complete(taskId);
System.out.println("完成任务:任务Id:" + taskId);
}

若无异常,控制台输出

完成任务:任务Id:6204

通过以上操作步骤,证明直接指定组任务办理人是可行的。

使用流程变量指定办理人

和个人任务直接指定办理人的缺点一样,直接指定组任务办理人也是不够灵活的。因此,我们可以考虑使用流程变量指定组任务办理人。

流程变量指定办理人

部署流程定义和启动流程实例

和前面一样,我们重新部署流程定义

部署ID: 6801
部署名称: 任务

部署流程定义以后,我们启动流程实例,并在启动流程实例的同时,设置组任务的办理人,和前一节一样,各个办理人之间使用逗号分隔。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 启动流程实例
*/
@Test
public void startProcessInstance() {
// 流程定义的key
String processDefinitionKey = "task";
Map<String,Object> map = new HashMap<String,Object>();
map.put("userIDs", "大大,中中,小小");
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey,map);
System.out.println("流程实例ID: " + processInstance.getId());
System.out.println("流程定义ID: " + processInstance.getProcessDefinitionId());
}

运行代码,输出如下结果

流程实例ID: 6901
流程定义ID: task:5:6804

查询任务

可以预见,查询act_ru_identitylink(正在执行的任务办理人表),大大,中中,小小分别有两条记录,只是两条记录办理人类型不一样而已。现在,我们来查询大大的组任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 查询当前人的组任务
*/
@Test
public void findMyGroupTask() {
String assignee = "大大";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskCandidateUser(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

运行代码,得到如下结果

任务ID: 6905
任务名称: 审批
任务的创建时间: Tue Oct 30 21:15:04 CST 2018
任务的办理人: null
流程实例ID: 6901
执行对象ID: 6901
流程定义ID: task:5:6804

拾取任务

从上面的信息中,我们得到了任务Id,接下来,我们让大大来拾取任务。

1
2
3
4
5
6
7
8
9
10
11
/**
* 拾取任务,将组任务分配给个人任务,指定任务办理人Assignee字段
*/
@Test
public void claim() {
String taskId = "6905";
// 分配个人任务(可以是组任务的成员,也可以是非组任务的成员)
String userId = "大大";
processEngine.getTaskService()
.claim(taskId, userId);
}

完成任务

当大大完成拾取任务后,我们就可以完成该任务了。

1
2
3
4
5
6
7
8
9
/**
* 完成我的任务
*/
@Test
public void completeMyPersonalTask() {
String taskId = "6905";
processEngine.getTaskService().complete(taskId);
System.out.println("完成任务:任务Id:" + taskId);
}

运行代码,没有异常。这样,我们就完成该审批流程,实践证明使用流程变量指定组任务办理人也是可以的。

使用类指定办理人

前面已经介绍了两种方式,现在,我们就介绍最后一种,使用类指定办理人。

为了更好地说明如何使用类指定办理人,我们新建包cn.demo.groupbyclass,并新建类TaskTest,流程图文件task.bpmn

既然是使用类指定办理人,那么我们就不再指定Candidate user,因此,该字段值为空,不需要任何值,只是需要一个实现org.activiti.engine.delegate.TaskListener的类,该类添加了郭靖、黄蓉这两个成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.demo.groupbyclass;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
public class TaskListenerImpl implements TaskListener {
@Override
public void notify(DelegateTask arg0) {
// 设置组任务办理人
arg0.addCandidateUser("郭靖");
arg0.addCandidateUser("黄蓉");
}
}

和个人任务使用类指定办理人一样,我们同样需要设置审批用户任务的监听类

使用类指定组任务办理人

部署流程定义和启动流程实例

一切准备好之后,同样地,我们部署一个新流程定义

部署ID: 7101
部署名称: 任务

然后,我们启动流程实例

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 启动流程实例
*/
@Test
public void startProcessInstance() {
// 流程定义的key
String processDefinitionKey = "task";
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey);
System.out.println("流程实例ID: " + processInstance.getId());
System.out.println("流程定义ID: " + processInstance.getProcessDefinitionId());
}

运行代码,得到如下结果

流程实例ID: 7201
流程定义ID: task:6:7104

这样,我们的组任务成员就包含了郭靖,黄蓉两人了。接下来,我们将组任务分配给郭靖,并由其去完成任务。

查询任务

我们来查询一下郭靖的组任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 查询当前人的组任务
*/
@Test
public void findMyGroupTask() {
String assignee = "郭靖";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskCandidateUser(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

运行代码,得到如下结果

任务ID: 7204
任务名称: 审批
任务的创建时间: Tue Oct 30 21:57:28 CST 2018
任务的办理人: null
流程实例ID: 7201
执行对象ID: 7201
流程定义ID: task:6:7104

拾取任务

通过上面的信息,我们使用任务Id让郭靖拾取任务

1
2
3
4
5
6
7
8
9
10
11
/**
* 拾取任务,将组任务分配给个人任务,指定任务办理人Assignee字段
*/
@Test
public void claim() {
String taskId = "7204";
// 分配个人任务(可以是组任务的成员,也可以是非组任务的成员)
String userId = "郭靖";
processEngine.getTaskService()
.claim(taskId, userId);
}

若无异常,则表示任务拾取成功,组任务分配给了郭靖,为保险起见,我们查询一下郭靖的个人任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 查询当前人的个人任务
*/
@Test
public void findMyPersonTask() {
String assignee = "郭靖";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() // 创建任务对象
/*查询条件(部分)*/
.taskAssignee(assignee)
/*排序*/
.orderByTaskCreateTime().asc()
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
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());
System.out.println("执行对象ID: " + task.getExecutionId());
System.out.println("流程定义ID: " + task.getProcessDefinitionId());
System.out.println("");
}
}
}

运行代码,输出如下信息

任务ID: 7204
任务名称: 审批
任务的创建时间: Tue Oct 30 21:57:28 CST 2018
任务的办理人: 郭靖
流程实例ID: 7201
执行对象ID: 7201
流程定义ID: task:6:7104

输出不为空,证明郭靖确实拾取了任务。

完成任务

最后,我们来完成任务

1
2
3
4
5
6
7
8
9
/**
* 完成我的任务
*/
@Test
public void completeMyPersonalTask() {
String taskId = "7204";
processEngine.getTaskService().complete(taskId);
System.out.println("完成任务:任务Id:" + taskId);
}

总结

组任务三种指定办理人的方式

  1. 直接指定办理人,即直接设置用户任务Assignee字段的值
  2. 使用流程变量,通过流程变量动态指定办理人的值
  3. 使用实现org.activiti.engine.delegate.TaskListener接口的类方法来动态指定办理人的值 ,即使用delegateTask.addCandidateUser(userId)添加组任务办理人

认领(拾取)和回退组任务

组任务要进行处理,必须分配给特定的办理人(认领任务),此时,可以使用processEngine.getTaskService().claim(taskId, userId)方法分配任务给特定办理人。

注意:该特定办理人既可以是组任务成员中的人,也可以不是组任务成员的人

当然,我们也可以使用processEngine.getTaskService(). setAssignee(taskId, null)方法回退组任务,前提是该任务之前是组任务。

添加或删除组任务成员

在组任务中,我们既可以使用processEngine.getTaskService().addCandidateUser(taskId, userId)方法向组任务添加人员,也可以使用processEngine.getTaskService().addCandidateUser(taskId, userId)从组任务中删除人员。

任务办理人相关的表

act_ru_identitylink(正在执行的任务办理人表)表存放任务的办理人,包括个人任务和组任务,表示正在执行的任务

act_hi_identitylink(历史任务办理人表)表存放任务的办理人,包括个人任务和组任务,表示历史任务

区别在于:

  1. 如果是个人任务,TYPE_的类型为participant(参与者)

  2. 如果是组任务,TYPE_的类型包括candidate(候选者)和participant(参与者)两种