候选者组

## 目录

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);
    }
}
posted @ 2022-11-08 13:59  夏·舍  阅读(36)  评论(0编辑  收藏  举报