天天看点

【flowable】九、flowable候选人和候选人组

flowable候选人和候选人组

之前在流程定义中的任务节点设置的负责人assignee都是固定的负责人,在流程定义设计时将参与者与文件固定设置了,如需变更任务负责人需要修改流程定义,系统可扩展性差。

针对这种情况可以给任务设置多个候选人或者候选人组,可以从候选人中选择参与者来完成任务。

这里讨论的是组任务,不同于流程变量来控制任务负责人。

1 候选人

1.1 设计流程

设计一个简单的新流程。

首先是“请假申请”,在分配用户项设置两个候选用户。

【flowable】九、flowable候选人和候选人组
【flowable】九、flowable候选人和候选人组

“经理审核”就设置一个

${assignee0}

流程变量即可。

1.2 部署流程和启动流程实例
/**
     * 部署流程
     */
    @Test
    public void deployment() {
        //获取ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取RepositoryService对象,部署流程定义
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //执行部署
        repositoryService.createDeployment()
                .addClasspathResource("flowable-4.bpmn20.xml")
                .deploy();
    }

    /**
     * 启动流程
     */
    @Test
    public void startProcess() {
        //获取ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //通过RuntimeService启动流程
        //通过流程定义ID启动流程实例
        //流程定义的ID在流程部署成功后,act_re_procdef表生成的数据主键ID就是流程定义ID
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //设置候选人流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("candidate0", "员工1");
        variables.put("candidate1", "员工2");

        ProcessInstance processInstance = runtimeService.startProcessInstanceById("flowable-4:1:10004", variables);
        // 输出相关的流程实例信息
        System.out.println("流程定义的ID:" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例的ID:" + processInstance.getId());
    }
           

流程启动后,

act_ru_variable

表可以看到候选人流程变量

【flowable】九、flowable候选人和候选人组

act_ru_task

表的

ASSIGNEE_

字段是null

【flowable】九、flowable候选人和候选人组

说明当前任务并没有分配给任何人,无人受理

1.3 任务查询

可以通过候选人进行查询任务

/**
     * 候选人任务查询
     */
    @Test
    public void queryTaskCandidate() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId("12501")
                //设置taskCandidateUser候选人条件来查询任务,这里的参数值就是候选人流程变量绑定的值
                //员工1和员工2都是可以查询到数据的
                .taskCandidateUser("员工1")
                .list();
        for (Task task : taskList) {
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getName() = " + task.getName());
        }
    }
           
1.4 任务拾取

根据候选人查询到任务后就可以拾取该任务。注意:当一个任务被拾取后,其他用户是无法拾取该任务的。

任务拾取成功后,就会变成个人任务

/**
     * 候选人拾取任务
     */
    @Test
    public void claimTaskCandidate() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("12501")
                //设置taskCandidateUser候选人条件来查询任务,这里的参数值就是候选人流程变量绑定的值
                //员工1和员工2都是可以查询到数据的
                .taskCandidateUser("员工1")
                .singleResult();


        if (task != null) {
            /**
             * 拾取任务
             * 即使该用户不是任务的候选人也可以拾取任务,建议拾取时做校验,根据候选人查询
             * 任务拾取成功后,就会变成个人任务,之后的操作就和之前一样了,complete即可
             */
            taskService.claim(task.getId(), "员工1");
        }
    }
           
【flowable】九、flowable候选人和候选人组

说明:即使不是任务的候选人也可以进行拾取任务,所以需要根据任务候选人去查询任务再去进行拾取

1.5 任务归还

如果任务拾取之后不想操作或者误拾取任务也可以进行归还任务。

/**
     * 任务归还
     */
    @Test
    public void unClaimTaskCandidate() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("12501")
                //员工1拾取的任务,需要通过员工1查询
                .taskAssignee("员工1")
                .singleResult();

        if (task != null) {
            taskService.unclaim(task.getId());
        }
    }
           

任务成功归还后,

ASSIGNEE_

就会为null,需要由任务候选人重新拾取

【flowable】九、flowable候选人和候选人组
1.6 任务交接

如果任务拾取后,不想操作也不想归还,可以交接给他人进行处理。

/**
     * 任务交接
     */
    @Test
    public void taskCandidate() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("12501")
                //员工1拾取的任务,需要通过员工1查询
                .taskAssignee("员工1")
                .singleResult();

        if (task != null) {
            /**
             * 任务交接,就是更新任务的分配人字段
             * 由于可分配给任意的人员,所以建议实际开发中做判断处理,只将任务分配给候选人
             */
            taskService.setAssignee(task.getId(), "员工3");
        }
    }
           
1.7 任务完成

就是之前正常处理流程,调用complete方法

/**
     * 任务完成
     */
    @Test
    public void taskComplete() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("12501")
                .taskAssignee("员工3")
                .singleResult();

        if (task != null) {
            //流程设计的时候,经理审批有个`assignee0`流程变量,所以这里设置下
            Map<String, Object> variables = new HashMap<>();
            variables.put("assignee0", "经理");
            taskService.complete(task.getId(), variables);
        }
    }
           

2 候选人组

当候选人很多的情况下,我们可以分组来处理。先创建组,然后把用户分配到这个组中。

2.1 管理用户和组

2.1.1 用户管理

通过

act_id_user

表维护用户

/**
     * 维护用户
     */
    @Test
    public void createUser() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 通过 IdentityService 完成相关的用户和组的管理
        IdentityService identityService = processEngine.getIdentityService();

        User user = null;
        for (int i = 1; i <= 3; i++) {
            user = identityService.newUser("员工" + i);
            user.setFirstName(i+"");
            user.setEmail(i+"@qq.com");
            identityService.saveUser(user);
        }
    }
           

2.1.2 用户组管理

通过

act_id_group

表维护

/**
     * 维护用户组
     */
    @Test
    public void createGroup() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 通过 IdentityService 完成相关的用户和组的管理
        IdentityService identityService = processEngine.getIdentityService();

        Group group = identityService.newGroup("group1");
        group.setName("研发部");
        group.setType("1");
        identityService.saveGroup(group);

    }
           

2.1.3 用户和用户组关联

通过

act_id_membership

表维护

/**
     * 用户和用户组关联
     */
    @Test
    public void userGroup() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        IdentityService identityService = processEngine.getIdentityService();

        // 根据组的编号找到对应的Group对象
        Group group = identityService.createGroupQuery().groupId("group1").singleResult();
        //找到用户
        List<User> users = identityService.createUserQuery().list();
        for (User user : users) {
            //用户分配给用户组
            identityService.createMembership(user.getId(), group.getId());
        }

    }
           
2.2 候选人组应用

用户和用户组的创建及关联搞清楚后,就可以使用候选人组实现流程任务分配了

2.2.1 设计流程

设计一个新的流程。

【flowable】九、flowable候选人和候选人组
【flowable】九、flowable候选人和候选人组

2.2.2 部署流程和启动流程实例

/**
     * 部署流程
     */
    @Test
    public void deployment() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        repositoryService.createDeployment().addClasspathResource("flowable-5.bpmn20.xml").name("候选人组流程").deploy();
    }

    /**
     * 启动流程
     */
    @Test
    public void startProcess() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //查询到用户组
        IdentityService identityService = processEngine.getIdentityService();
        Group group = identityService.createGroupQuery().groupId("group1").singleResult();

        //然后给流程设计里面的${group1}流程变量赋值
        Map<String, Object> variables = new HashMap<>();
        variables.put("group1", group.getId());

        runtimeService.startProcessInstanceById("flowable-5:1:32504", variables);
    }
           

act_ru_identitylink

表中可以看到流程任务绑定的候选人组

【flowable】九、flowable候选人和候选人组

2.2.3 任务的拾取和完成

/**
     * 查询候选人组任务
     */
    @Test
    public void queryTaskCandidateGroup() {
        //获取ProcessEngine引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //根据用户获取候选组
        IdentityService identityService = processEngine.getIdentityService();
        Group group = identityService.createGroupQuery().groupMember("员工1").singleResult();

        //获取组任务
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId("35001")
                .taskCandidateGroup(group.getId())
                .list();

        for (Task task : taskList) {
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getName() = " + task.getName());
        }
    }
           
/**
     * 拾取组任务
     * 就是通过候选组绑定查询出来的任务,然后拾取,和普通的流程任务操作一样
     * 正常业务开发下,该组下的任务只能由该组人员拾取
     * 拾取之后,不想操作的话也可以退还或者交接给他人
     */
    @Test
    public void claimTaskCandidate() {
//获取ProcessEngine引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //根据用户获取候选组
        IdentityService identityService = processEngine.getIdentityService();
        Group group = identityService.createGroupQuery().groupMember("员工1").singleResult();

        //获取组任务
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId("35001")
                .taskCandidateGroup(group.getId())
                .list();

        for (Task task : taskList) {
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getName() = " + task.getName());
            //拾取
            taskService.claim(task.getId(), "员工1");
            System.out.println("任务:"+task.getName()+"拾取成功");
        }
    }
           
/**
     * 完成组任务
     * 就是完成正常的一个流程任务
     */
    @Test
    public void completeTask() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        Task task = taskService.createTaskQuery().processInstanceId("35001").taskAssignee("员工1").singleResult();
        Assert.assertNotNull(task);
        //流程设计的时候有个assignee0流程变量,这里需要设置下
        Map<String, Object> variables = new HashMap<>();
        variables.put("assignee0", "经理");
        taskService.complete(task.getId(), variables);
    }
           

启动流程实例之后,查询当前任务执行表:

记录了当前执行的任务,由于该任务是组任务,

assignee_

字段值是null,让拾取任务之后该字段才会有拾取用户的信息。

查询任务参与者:

select * from act_ru_identitylink
           

记录了参与任务用户或组,当前任务如果设置了候选人,就会向该表插入候选人记录,有几个候选人就插入几条记录,与

act_ru_identitylink

对应的还有一张历史表

act_hi_identitylink

,向

act_ru_identitylink

插入记录的同时也会向

act_hi_identitylink

插入记录。

继续阅读