TaskService
- 对用户任务UserTask的管理和流程的控制
- 设置用户任务的权限信息(设置候选人等)
- 针对用户任务添加任务附件,任务评论和事件记录
TaskService对Task的管理和控制
- Task对象的创建和删除
- 查询Task,驱动Task节点完成执行
- Task相关参数变量variable设置
TaskService变量的作用域
// 查询task
Task task1 = taskService.createTaskQuery().singleResult();
// 设置全局变量
taskService.setVariable(task1.getId(),"key1","value1");
// 设置局部变量
taskService.setVariableLocal(task1.getId(),"key2","value2");
// 获取全局变量
Map<String,Object> a = taskService.getVariables(task1.getId());
// 获取局部变量
Map<String,Object> b = taskService.getVariablesLocal(task1.getId());
// 获取全局变量
Map<String,Object> c = runtimeService.getVariables(processInstance.getId());
使用taskService设置局部变量后,局部变量的作用域只限于当前任务内,如果任务结束后,那么局部变量也就随着消失了。
除了直接设置变量外,在任务提交的时候也可以附带变量,即使用taskService.complete()
,这个complete方法多个重载方法:
public void complete(String taskId);
public void complete(String taskId, Map<String, Object> variables);
public void complete(String taskId, Map<String, Object> variables, boolean localScope) ;
其中:taskId(对应act_ru_task中的id_),variables(下一次任务所需要的参数),作用是完成这一次任务,并且下一步任务需要流程变量的。要注意的是localScope这个参数:localScope(存储范围:本任务) 。当这个布尔值为true表示作用范围为当前任务,当任务结束后,再也取不到这个值了,act_ru_variables这个表中也没有这个参数的信息了;如果为false表示这个变量是全局的,任务结束后在act_ru_variables表中仍然能查到变量信息。相关内容可以查看下面这篇文章:
https://blog.csdn.net/u013026207/article/details/53405265
TaskService设置Task权限信息
- 候选用户candidateUser和候选组candidateGroup
- 指定拥有人Owner和办理人Assignee
- 通过claim设置办理人(签收 )
示例:
首先编写流程文件如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1536107421286" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="second_approve" isClosed="false" isExecutable="true" name="二级审批" processType="None">
<startEvent id="startEvent" name="开始"/>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="myTask"/>
<userTask id="myTask" name="my-task" activiti:candidateUsers="yubuyun">
</userTask>
<sequenceFlow id="flow2" sourceRef="myTask" targetRef="endEvent"/>
<endEvent id="endEvent" name="取消"/>
</process>
</definitions>
其中设置了节点的候选人为yubuyun。
后台代码如下:
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery()
.taskCandidateUser("yubuyun")
.taskUnassigned()
.listPage(0,100);
logger.info("taskList={}",taskList);
for(Task task : taskList){
taskService.claim(task.getId(),"yubuyun");
}
上述代码中先对任务进行查询,查询条件为候选人为yubuyun,并且还没有被签收,然后才对查询结果进行签收。这样做的原因是,如果某个task之前已经被签收claim了,再次执行claim命令的时候就会抛出异常,记一个任务只能被签收一次,为此防止抛出异常,可以先查询任务是否被签收。
OWNER 和 ASSIGNEE 的区别
在act_ru_task表中有OWNER_和ASSIGNEE_两个字断。
这两个字段的意义是:
1,ASSIGNEE_(受理人):task任务的受理人,就是执行TASK的人,这个又分两种情况(有值,NULL)
- 有值的情况:XML流程里面定义的受理人,TASK会直接填入这个人;
- NULL:XML没有指定受理人或者只指定了候选组;
没有值的时候,可以使用签收功能去指定受理人,就是候选组里面谁签收谁就成了受理人。
- OWNER_(委托人):受理人委托其他人操作该TASK的时候,受理人就成了委托人OWNER_,其他人就成了受理人ASSIGNEE_
owner字段就是用于受理人委托别人操作的时候运用的字段。
Task task=taskService.createTaskQuery().singleResult();
//签收
taskService.claim(task.getId(), "billy");
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:billy
//委托
taskService.delegateTask(task.getId(), "cc");
logger.info(taskService.createTaskQuery().singleResult().getOwner());
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:owner是Billy,assignee是cc
TaskService设置Task附加信息
- 任务附件Attachment创建与查询
- 任务评论Comment创建与查询
- 事件记录Event创建与查询
添加附件示例
// 添加附件(地址位于/url/test.png)到task中
taskService.createAttachment("url",task.getId(),
processInstance.getId(),
"name",
"desc",
"/url/test.png");
// 查询附件
List<Attachment> attachmentList = taskService.getTaskAttachments(task.getId());
for(Attachment attachment : attachmentList){
logger.info("attach={}",attachment);
}
最终打印结果是一个对象,说明附件作为对象保存到数据库中。
attach=org.activiti.engine.impl.persistence.entity.AttachmentEntityImpl@680d4a6a
添加评论示例
taskService.addComment(task.getId(),processInstance.getId(),"record note 1");
taskService.addComment(task.getId(),processInstance.getId(),"record note 2");
List<Comment> commentList = taskService.getTaskComments(task.getId());
for(Comment comment : commentList){
logger.info("comment={}", ToStringBuilder.reflectionToString(comment, ToStringStyle.MULTI_LINE_STYLE));
}
评论对象输出为:
[main] INFO com.activiti.HelloWorld - comment=comment,<null>,Tue Oct 02 22:49:53 CST 2018,105008,105004,AddComment,record note 2,record note 2,105016,false,false,false
[main] INFO com.activiti.HelloWorld - comment=comment,<null>,Tue Oct 02 22:49:53 CST 2018,105008,105004,AddComment,record note 1,record note 1,105015,false,false,false
事件记录
事件记录查询为:
List<Event> eventList = taskService.getTaskEvents(task.getId());
for(Event event : eventList){
logger.info("event={}",ToStringBuilder.reflectionToString(event,ToStringStyle.SIMPLE_STYLE));
}
输出结果如下:
[main] INFO com.activiti.HelloWorld - comment=comment,<null>,Tue Oct 02 22:52:35 CST 2018,107508,107504,AddComment,record note 2,record note 2,107516,false,false,false
[main] INFO com.activiti.HelloWorld - comment=comment,<null>,Tue Oct 02 22:52:35 CST 2018,107508,107504,AddComment,record note 1,record note 1,107515,false,false,false
[main] INFO com.activiti.HelloWorld - event=comment,<null>,Tue Oct 02 22:52:35 CST 2018,107508,107504,AddComment,record note 2,record note 2,107516,false,false,false
[main] INFO com.activiti.HelloWorld - event=comment,<null>,Tue Oct 02 22:52:35 CST 2018,107508,107504,AddComment,record note 1,record note 1,107515,false,false,false
[main] INFO com.activiti.HelloWorld - event=event,<null>,Tue Oct 02 22:52:35 CST 2018,107508,107504,AddAttachment,name,<null>,107514,false,false,false
[main] INFO com.activiti.HelloWorld - event=event,<null>,Tue Oct 02 22:52:35 CST 2018,107508,<null>,AddUserLink,lizongyu_|_owner,<null>,107512,false,false,false
从日志可以看出comment和event结果相同,但是event除了相同部分外,还有添加附件和添加用户的事件记录。