候选者组
## 目录
bpmn指定候选者
可以直接在节点写死候选者,多名候选者之间用逗号隔开
但是常见业务场景中,候选者并不会被写死,而是在节点用UEL表达式,根据业务需求传入候选者
代码通用部分
这里先给出后续代码需要用到的包和我个人封装好的函数
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//创建操作activity的核心对象 ProcessEngine 所有操作都需要用它完成
public ProcessEngine createProcessEngine(){
//创建ProcessEngineConfiguration
ProcessEngineConfiguration configuration =ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cgf.xml");
//通过ProcessEngineConfiguration创建ProcessEngine,此时根据配置文件设置决定是否创建数据库的表或者更新表
ProcessEngine processEngine =configuration.buildProcessEngine();
System.out.println("创建完成:"+processEngine);
return processEngine;
}
启动流程并设置流程变量
依据下图绘制了bpmn并设置好了UEL表达式,其中“创建”节点assignee
使用了${assignee}
,“经理”节点candidate groups
使用了${groups}
指定创建申请的责任人assignee
为zhangsan,经理节点的候选者为a,b,c
// 启动流程时设置流程变量
@Test
public void startProcessInstance() {
//创建ProcessEngine
ProcessEngine processEngine =createProcessEngine();
// 流程id
String processDefinitionKey = "duoren";
// 定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
//候选者们放在数组中
List<String> usr = new ArrayList<String>();
usr.add("a");
usr.add("b");
usr.add("c");
variables.put("assignee", "zhangsan");
variables.put("groups", usr);
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
System.out.println(" 流 程 实 例 id:" + processInstance.getProcessInstanceId());
}
查询组任务
当流程实例从创建节点推进到经理节点时,a,b,c三人都可以查询到该流程实例
重点是使用了taskService.createTaskQuery().processDefinitionKey(流程id).taskCandidateGroup(候选人).list()
,其中.taskCandidateGroup(候选人)
代表查询candidate groups
此时流程实例没有指定责任人assignee
,没有人能调用task.complete
去推进任务
//根据获选人查询组任务 区别于根据assignee查询个人的所有任务
@Test
public void findGroupTaskList() {
//创建ProcessEngine
ProcessEngine processEngine =createProcessEngine();
// 流程id
String processDefinitionKey = "duoren";
// 任务候选人 节点上设置的所有候选人都能看到这个流程实例
String candidateUser = "b";
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
//查询组任务
List<Task> list = taskService.createTaskQuery()//
.processDefinitionKey(processDefinitionKey)//
.taskCandidateGroup(candidateUser)//根据候选人查询
.list();
for (Task task : list) {
System.out.println("----------------------------");
System.out.println("流程实例id: " + task.getProcessInstanceId());
System.out.println("任务id: " + task.getId());
System.out.println("任务负责人: " + task.getAssignee());
System.out.println("任务名称: " + task.getName());
}
}
拾取组任务
核心就是用taskService.claim(任务id, 责任人)
将任务的assignee
与指定责任人绑定
可以看得出这个函数并不存在鉴权,所以被指定的责任人即便不是当前节点列出的候选人也没问题,因此需要手动实现鉴权
组任务拾取后,该任务已有负责人,此时同处一个流程节点的其他候选人就看不到这个任务了 只有拾取了人物的人可以看到
假设b用户拾取了任务,此时b用户只能根据assignee
查询个人的所有任务,看到刚才拾取的任务
@Test
public void claimTask(){
//创建ProcessEngine
ProcessEngine processEngine =createProcessEngine();
TaskService taskService = processEngine.getTaskService();
//要拾取的任务id
String taskId = "5002";
//任务候选人id
String userId = "b";
//拾取任务
//校验该用户有没有拾取任务的资格
Task task = taskService.createTaskQuery()//
.taskId(taskId)
.taskCandidateGroup(userId)//根据候选人查询
.singleResult();
if(task!=null){
taskService.claim(taskId, userId);
System.out.println("任务拾取成功");
}
}
附上b用户拾取组任务后,查询b用户的个人待办任务的代码
// 查询当前个人待执行的任务
@Test
public void findPersonalTaskList() {
//创建ProcessEngine
ProcessEngine processEngine = createProcessEngine();
// 任务负责人
String assignee = "b";
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
//下面的Task类是org.activiti.engine.task
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("duoren")
.taskAssignee(assignee)
.list();
for (Task task : list) {
System.out.println(" 流 程 实 例 id : " + task.getProcessInstanceId());
System.out.println("任务id: " + task.getId());
System.out.println("任务负责人: " + task.getAssignee());
System.out.println("任务名称: " + task.getName());
}
}
归还组任务
核心就是用taskService.claim(任务id, 责任人)
将任务的assignee
设置为null
可以看得出这个函数并不存在鉴权,所以在将任务的责任人设置为null
前,需要手动确认当前操作用户是否是任务的责任人
如果用户拾取任务后归还任务 那么其他候选人就又能看到任务并拾取了
@Test
public void setAssigneeToGroupTask() {
//创建ProcessEngine
ProcessEngine processEngine =createProcessEngine();
// 查询任务使用TaskService
TaskService taskService = processEngine.getTaskService();
// 当前待办任务id
String taskId = "5002";
// 任务负责人
String userId = "b";
// 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务
Task task = taskService.createTaskQuery().taskId(taskId)
.taskAssignee(userId).singleResult();
if (task != null) {
// 如果设置为null,归还组任务,该 任务没有负责人
taskService.setAssignee(taskId, null);
}
}
交接组任务
核心就是用taskService.claim(任务id, 责任人)
将任务的assignee
与另一个用户绑定
可以看得出这个函数并不存在鉴权,所以在将任务的责任人设置为其他用户前,需要手动确认当前操作用户是否是任务的责任人
@Test
public void setAssigneeToCandidateUser() {
//创建ProcessEngine
ProcessEngine processEngine =createProcessEngine();
// 查询任务使用TaskService
TaskService taskService = processEngine.getTaskService();
// 当前待办任务
String taskId = "5002";
// 任务负责人
String userId = "b";
// 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务
Task task = taskService.createTaskQuery().taskId(taskId)
.taskAssignee(userId).singleResult();
if (task != null) {
// 将此任务交给其它候选人办理该 任务
String candidateuser = "a";
taskService.setAssignee(taskId, candidateuser);
}
}