Activiti流程任务管理

  • 1 任务的创建与删除
  •     1.1 Task接口
  •     1.2 创建与保存task实例
  •     1.3 删除任务
  • 2 任务权限
  •     2.1 设置候选用户,用户组
  •     2.2 权限数据查询
  •     2.3 设置任务持有人和代理人
  •     2.4 任务权限管理
  • 3 任务参数
  •     3.1 基本类型参数设置
  •     3.2 序列化参数
  •     3.3 获取参数
  •     3.4 参数作用域
  •     3.5 设置多个参数
  • 4 任务附件
  •     4.1 Attachment对象
  •     4.2 任务附件
  • 5 任务评论与事件记录
  •     5.1 Comment对象
  •     5.2 任务评论
  •     5.3 事件的记录
  • 6 任务声明与完成
  •     6.1 任务声明
  •     6.2 任务完成


1 任务的创建与删除

一个Task实例表示流程中的一个任务,Task是一个接口,其实现类为TaskEntityImpl,对应的数据库表为ACT_RU_TASK.TaskEntityImpl包括以下属性:
id:主键,对应ID_字段
revision:该数据版本号,对应REV_字段
owner:任务拥有人,对应OWNER_字段
assignee:被指定需要执行任务的人
delegationState:任务被委派的状态
parentTaskId:父任务的ID
name:任务名称
decription:任务的描述型
priority:任务的优先级,默认为50,表示正常状态
createTime:任务创建时间
dueDate:预定日期
executionId:该任务对应的执行流Id
processDefinitionId:任务对应的流程定义ID
claimTime:任务的提醒时间

TaskService taskService = engine.getTaskService();
//保存第一个task,不设置ID
Task task1 = taskService.newTask();
taskService.saveTask(task1);
//保存第二个Task,设置ID
Task task2 = taskService.newTask("审核任务");
taskService.saveTask(task2);
deleteTask(String taskId);//根据Task的ID删除task数据,调用该方法不会进行级联删除
deleteTask(String taskId,boolean cascade);//根据Task的ID删除Task数据,由调用者决定是否进行级联删除
deleteTasks(Collection<String> taskIds);//提供多个Task的ID进行多条数据删除,调用该方法不会进行级联删除
deleteTasks(Collection<String> taskIds);//

2 任务权限

TaskService taskservice = engine.getTaskService();
//保存第一个Task
Task task1 = taskService.newTask("task1");
taskService.saveTask(task1);
//保存第二个Task
Task task2 = taskService.newTask("task2");
taskService.saveTask(task2);
//绑定用户组与任务的关系
taskService.addCandidateGroup("task1","groupA");
//绑定用户与任务的关系
taskService.addCandidateUser("task2","userA");
//根据用户组查询任务
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("groupA").list();
//根据用户组id列表查询任务
List<String> groupIds = new ArrayList<String>();
groupIds.add("groupA");
groupIds.add("groupB");
tasks = taskService.createTaskQuery().taskCandidateGroupIn(groupIds).list();

//根据用户查询任务
tasks = taskService.createTaskQuery().taskCandidateUser("userA").list();

//查询权限数据
List<IdentityLink> links = taskService.getIdentityLinksForTask(tasks.get(0).getId());
System.out.println("关系数据量:" + link.size());

TaskService中提供了一个setOwner方法来设置任务的持有人,调用该方法后,会设置流程表的OWNER_字段为相应用户的ID

Task task1 = taskService.newTask("task1");
task1.setName("申请任务");
//设置任务持有人
taskService.setOwner(task1.getId(),user.getId());
Systemt.out.println("用户张三持有任务数量:"+taskService.createTaskQuery().taskOwner(user.getId()).count());

//设置任务代理人
taskService.setAssignee(task1.getId(),user.getId());
System.out.println("用户张三受理的任务数量:"+taskService.createTaskQuery().taskAssignee(user.getId()).count());
Task task1 = taskService.newTask("task1");
task1.setName("申请任务1");
taskService.saveTask(task1);

//添加任务权限数据
//调用addUserIdentityLink方法
taskService.addGroupIdentityLink(task1.getId(),groupA.getId(),IdentityLinkType.CANDIDATE);
taskService.addGroupIdentityLink(task1.getId(),groupA.getId(),IdentityLinkType.OWNER);
taskService.addGroupIdentityLink(task1.getId(),groupA.getId(),IdentityLinkType.ASSIGNEE);
Task task2 = taskService.newTask("task2");
task2 .setName("申请任务2");
taskService.saveTask(task2 );
taskService.addUserIdentityLink(task2.getId(),userA.getId(),IdentityLinkType.CANDIDATE);
taskService.addUserIdentityLink(task2.getId(),userA.getId(),IdentityLinkType.OWNER);
taskService.addUserIdentityLink(task2.getId(),userA.getId(),IdentityLinkType.ASSIGNEE);

//删除任务权限数据
taskService.deleteCandidateGroup(task1.getId(),groupA.getId());
//删除类型为OWNER的权限
taskService.deleteGroupIdentityLink(task1.getId(),groupA.getId(),IdentityLinkType.OWNER);
//删除类型为ASSIGNEE的权限
taskService.deleteGroupIdentityLink(task1.getId(),groupA.getId(),IdentityLinkType.ASSIGNEE);

// 添加用户权限
taskService.deleteCandidateUser(task1.getId(),user.getId());
taskService.deleteCandidateUser(task1.getId(),user.getId(),IdentityLinkType.OWNER);
taskService.deleteCandidateUser(task1.getId(),user.getId(),IdentityLinkType.ASSIGNEE);

3 任务参数

Activiti中的参数均保存在ACT_RU_VARIABLE表中,设置参数可以调用TaskService的setVariable(String taskId,String variableName,Object value);方法,其中参顺类型为Object,根据传入的参数类型,参数表的Type_字段会记录参数的类型标识,当前Activiti支持以下基本参数类型:
Boolean,Date,Double,Integer,Long,Null,Short,String,相应的参数类型标识为首字母小写,如Boolean的参数标识为boolean

taskService.setVariable(task1.getId(),"arg0",false);
taskService.setVariable(task1.getId(),"arg1",1.5D);
taskService.setVariable(task1.getId(),"arg2",10L);
//TestVO
public class TestVO implements Serializable{
	private String name;
	public TestVO(String name){
		this.name = name;
	}
	
	public String getName(){
		return this.name;
	}
}

//设置序列化参数
taskService.setVariable(task1.getId(),"arg0",new TestVO("crazyit"));
taskService.setVariable(task1.getId,"days",5);
taskService.setVariable(task1.getId,"target",new TestVO("北京"));
//获取天数
Integer days = (Integer)taskService.getVariable(task1.getId(),"days");
// 获取目的地
TestVO target = (TestVO)taskService.getVariable(task1.getId(),"target");

如果设置一个任务参数,希望在整个流程中都可以使用,那么可以调用setVatiable方法,如果只希望该参数仅仅在当前这个任务中使用,那么可以调用TaskService的setVariableLocal方法.调用了setVariable方法后,如果调用getVariableLocal方法来获取参数,将查不到任何值,因为getVariableLocal方法会查询当前任务的参数.getVariable方法会查询任务参数(setVariableLocal方法设置的参数)和流程的全局参数(setVariable方法设置的参数),并且会优先查询任务参数

taskService.setVariable(task.getId(),"days",10);
taskService.setVariableLocal(task.getId(),"target","欧洲");
//获取参数
Object data1 = taskService.getVariable(task.getId(),"days");
Object data2 = taskService.getVariable(task.getId(),"target");
Object data3 = taskService.getVariableLocal(task.getId(),"days");
Map<String,Object> vars = new HashMap<String,Object>();
vars.put("days",10);
vars.put("target","欧洲");
taskService.setVariables(task1.getId(),vars);

4 任务附件

一个AttachMent实例标识一条任务附件的数据,Attachment接口提供了获取任务附件属性的各个方法,如何设置该对象的属性,完全由TaskService完成.该接口的实现类为AttachmentEntityImpl,包含以下属性:
id:附件表的主键
revision:附件表的版本
name:附件的名称
description:附件描述
type:附件类型
taskId:该附件对应的任务id,杜英task_id_字段
processInstanceId:流程实例ID,对应PROC_INST_ID
url:附件的url,由调用者提供
contentId:附件内容的ID,如果调用者提供了输入流作为附件的内容,那么这些内容将会被保存到资源表(ACT_GE_BYTEARRAY)中,该字段将为资源表的外键ID

// 部署流程描述文件
Deployment dep = repositoryService.createDeployment().addClasspathResource("bpmn/vocation.bpmn").deploy();
//查找流程定义
ProcessDefinition pd = repositoryService.createProcessDefintitQuery().deploymentId(dep.getId()).singleResult();
//启动流程
ProcessInstance pi = runtimeService.startProcessInstanceById(pd.getId());
//查找任务
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();

//创建附件
Attachment att1 = taskService.createAttachment("web.url",task.getId(),pi.getId(),"163.com","163 web page","http:///www.163.com");
//创建图片输入流
InputStream is = new FileInputStream(new Fil("resource/artifact/result.png"));
//设置输入流为任务附件
Attachment att2 = taskService.createAttachment("web.url",task.getId(),pi.getId(),"163.com","163 web page",is);

//查询附件
// 根据流程实例id查询附件
List<Attachment> attas1 = taskService.getProcessInstanceAttachments(pi.getId());
//根据任务id查询附件
List<Attachment> attas2 = taskService.getTaskAttachments(task.getId());
//根据附件id查询附件
Attachment attResult = taskService.getAttachment(att1.getId());
//根据附件id查询附件内容
InputStream stream1 = taskService.getAttachmentContent(att2.getId());

//删除附件
taskService.deleteAttachment(att2.getId());

5 任务评论与事件记录

一个comment实例标识评论表的一条数据,CommentEnttityImpl实际实现了两个接口,Event和Comment.如果该对象作为Event接口返回,则可以认为它返回的是事件记录的数据,如果该对象作为Comment返回,则其返回的是评论数据.CommentEntityImpl包含以下属性:
id:评论表的主键
type:该数据的类型,对应TYPE_字段,该属性有两个值,分别为"event"和"comment".当type为"event"时,表示数据为事件的记录;当值为"comment"时,表示为任务或者流程的评论数据
userId:产生数据用户的ID,对应user_id_字段
time:该数据的产生时间,对应TIME_字段
taskId:该评论数据对应的任务ID
processInstanceId:该评论(或者事件记录)数据对应的流程实例ID,对应PROC_INST_ID_字段
action:该数据的操作标识
message:该评论(或者事件记录)数据的信息
fullMessage:该评论(或者事件记录)数据的信息

//启动流程
ProcessInstance pi = runtimeService.startProcessInstanceById(pd.getId());
//查找任务
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
//添加任务评论
taskService.addComment(task.getId(),pi.getId(),"this is comment message");
//查询评论
List<Comment> comments = taskService.getTaskComments(task.getId());
//启动流程
ProcessInstance pi = runtimeService.startProcessInstanceById(pd.getId());
//查找任务
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
//调用各个记录事件的方法
taskService.addComment(task.getId(),pi.getId(),"this is comment message");
taskService.addUserIdentityLink(task.getId(),"1","user");
taskService.deleteUserIdentityLink(task.getId(),"1","user");
taskService.addGroupIdentityLink(task.getId(),"1", "group");
taskService.deleteGroupIdentityLink(task.getId(),"1", "group");
Attachment atta = taskService.createAttachment("test",task.getId(),pi.getId(),"test","test","");
taskService.deleteAttachment(atta.getId());
//查询Comment和Event
List<Comment> comments = taskService.getTaskComments(task.getId());
System.out.println("总的评论数:" + comments.size());
List<Event> events = taskService.getTaskEvents(task.getId());
System.out.println("总共的事件数量:"+events.size());

// 查询事件与评论
List<Comment> commonts1 = taskService.getProcessInstanceComments(pi.ghetId());
taskService.getTaskComments(task.getId());
Sysytem.out.println("任务评论数量:"+commontsl.size());
List<Event> events = taskService.getTaskEvents(task.getId());
System.out.println("事件数量:"+events.size());

6 任务声明与完成

调用TaskService的claim方法可以将任务分配到用户下,即设置任务表的ASSIGNEE_字段为用户的ID,该效果与使用setAssignee方法的效果类似,但不同的是,一旦调用了claim方法,如果再次调用该方法将同一个任务分配到其他用户,则会抛出异常

taskService.claim(task.getId,"1");
//此处将会抛出异常
taskService.claim(task.getId,"2");
// vars 为临时参数
taskService.complete(task.getId(),vars,vars2)
//再次查找任务
task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
//无法查询临时参数
String tempVar = (String)taskService.getVariable(task.getId(),"temp");

//不带参数的方法
taskService.complete(task.getId());

在调用complete方法时,会将完成的task数据从任务表中删除,如果发现这个任务是流程中的最后一个任务,则会连同流程实例的数据也一并删除,并按照历史(histroy)配置来记录流程的历史数据