二、个人任务

2.1、分配任务负责人

2.1.1、固定分配

在进行业务流程建模时指定固定的任务负责人, 如图:

java list对象取属性String 类型 取最大值 java list怎么取值_activiti

并在 properties 视图中,填写 Assignee 项为任务负责人。

2.1.2、表达式分配

由于固定分配方式,任务只管一步一步执行任务,执行到每一个任务将按照 bpmn 的配置去分配任
务负责人。

2.1.2.1、UEL 表达式

Activiti 使用 UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即 统一表达式语言, activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method。

1)UEL-value 定义

如图:

java list对象取属性String 类型 取最大值 java list怎么取值_System_02

assignee0 这个变量是 activiti 的一个流程变量,

或者使用这种方式定义:

如图:

java list对象取属性String 类型 取最大值 java list怎么取值_System_03

user 也是 activiti 的一个流程变量, user.assignee 表示通过调用 user 的 getter 方法获取值。

2)UEL-method 方式

如图:

java list对象取属性String 类型 取最大值 java list怎么取值_Test_04

userBean 是 spring 容器中的一个 bean,表示调用该 bean 的 getUserId()方法。

3)UEL-method 与 UEL-value 结合

再比如:
${ldapService.findManagerForEmployee(emp)}
ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti
流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中。

4)其它

表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。
如下:
${order.price > 100 && order.price < 250}

2.1.2.2、编写代码配置负责人
1)定义任务分配流程变量

如图:

java list对象取属性String 类型 取最大值 java list怎么取值_System_05

java list对象取属性String 类型 取最大值 java list怎么取值_监听器_06

java list对象取属性String 类型 取最大值 java list怎么取值_监听器_07

java list对象取属性String 类型 取最大值 java list怎么取值_activiti_08

2)设置流程变量

在启动流程实例时设置流程变量,如下:

/**
     * 部署流程定义
     */
    @Test
    public void testDeployment(){
//        1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、得到RepositoryService实例
        RepositoryService repositoryService = processEngine.getRepositoryService();
//        3、使用RepositoryService进行部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/evection-uel.bpmn20.xml") // 添加bpmn资源
                .addClasspathResource("bpmn/evection.png")  // 添加png资源
                .name("出差申请流程")
                .deploy();
//        4、输出部署信息
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }
 /**
     * 启动流程,并设置流程负责人
     */
    @Test
    public void assigneeUEL(){
//      获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取 RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        设置assignee的取值,用户可以在界面上设置流程的执行
        Map<String,Object> assigneeMap = new HashMap<>();
        assigneeMap.put("assignee0","张三");
        assigneeMap.put("assignee1","李经理");
        assigneeMap.put("assignee2","王总经理");
        assigneeMap.put("assignee3","赵财务");
//        启动流程实例,同时还要设置流程定义的assignee的值
        runtimeService.startProcessInstanceByKey("myEvection-uel",assigneeMap);
//       输出
        System.out.println(processEngine.getName());
    }

执行成功后,可以在act_ru_variable表中看到刚才map中的数据

java list对象取属性String 类型 取最大值 java list怎么取值_activiti_09

2.1.2.3、注意事项

由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如:
某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在
流程变量中存在,否则 activiti 异常。

2.1.3、监听器分配

可以使用监听器来完成很多Activiti流程的业务。

在本章我们使用监听器的方式来指定负责人,那么在流程设计时就不需要指定assignee。

任务监听器是发生对应的任务相关事件时执行自定义 java 逻辑 或表达式。
任务相当事件包括:

java list对象取属性String 类型 取最大值 java list怎么取值_System_10


这图是旧版idea的actiBPMN插件可视化监听器设置图,新版idea已经无法搜索acitBPMN插件安装,我这里安装的是Activiti BPMN visualizer插件,这个插件目前我找资料找不到怎么设置监听器,所以就只是在xml代码上手动添加了

<userTask id="sid-c3772700-fbf3-4472-8f4f-1810ac4f02fb" name="创建申请">
      <extensionElements>
        <activiti:taskListener class="org.example.listener.MyTaskListener" event="create"/>
      </extensionElements>
    </userTask>

Event的选项包含:

Create:任务创建后触发
Assignment:任务分配后触发
Delete:任务完成后触发
complete:

java list对象取属性String 类型 取最大值 java list怎么取值_System_11

创建新的.bpmn20.xml文件

java list对象取属性String 类型 取最大值 java list怎么取值_System_12

创建申请和审核申请的用户任务都不需要设置Assignee

java list对象取属性String 类型 取最大值 java list怎么取值_System_13

定义任务监听类,且类必须实现 org.activiti.engine.delegate.TaskListener 接口

package org.example.listener;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

/**
 * 监听器
 */
public class MyTaskListener implements TaskListener {

    /**
     * 指定负责人
     * @param delegateTask
     */
    public void notify(DelegateTask delegateTask) {
        //判断当前的任务是创建申请 并且是create时间
        if("创建申请".equals(delegateTask.getName())&&
                "create".equals(delegateTask.getEventName())){
            //这里指定任务负责人
            delegateTask.setAssignee("张三");
        }
    }
}

给bpmn20.xml资源文件的用户任务添加监听器

<userTask id="sid-c3772700-fbf3-4472-8f4f-1810ac4f02fb" name="创建申请">
      <extensionElements>
        <activiti:taskListener class="org.example.listener.MyTaskListener" event="create"/>
      </extensionElements>
    </userTask>

测试代码

package org.example.test;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;

public class TestListener {
    /**
     * 部署流程定义
     */
    @Test
    public void testDeployment(){
//        1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、得到RepositoryService实例
        RepositoryService repositoryService = processEngine.getRepositoryService();
//        3、使用RepositoryService进行部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/demo-listen.bpmn20.xml") // 添加bpmn资源
                .name("测试监听器")
                .deploy();
//        4、输出部署信息
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess() {
//        1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        3、根据流程定义Id启动流程
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("demo-listen");
    }
}

结果图

SELECT * FROM ACT_RU_TASK

java list对象取属性String 类型 取最大值 java list怎么取值_activiti_14

DelegateTask对象的内容如下:

java list对象取属性String 类型 取最大值 java list怎么取值_activiti_15

2.1.3.1、注意事项

使用监听器分配方式,按照监听事件去执行监听类的 notify 方法,方法如果不能正常执行也会影响
任务的执行。

2.2、查询任务

查询任务负责人的待办任务

代码如下:

// 查询当前个人待执行的任务
@Test
public void findPersonalTaskList() {
    // 流程定义key
    String processDefinitionKey = "myEvection1";
    // 任务负责人
    String assignee = "张三";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取TaskService
    TaskService taskService = processEngine.getTaskService();
    List<Task> taskList = taskService.createTaskQuery()
    	.processDefinitionKey(processDefinitionKey)
    	.includeProcessVariables()
        .taskAssignee(assignee)
        .list();
    for (Task task : taskList) {
        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());
    }
}
关联 businessKey

需求:
在 activiti 实际应用时,查询待办任务可能要显示出业务系统的一些相关信息。

比如:查询待审批出差任务列表需要将出差单的日期、 出差天数等信息显示出来。

出差天数等信息在业务系统中存在,而并没有在 activiti 数据库中存在,所以是无法通过 activiti 的 api 查询到出差天数等信息。
实现:
在查询待办任务时,通过 businessKey(业务标识 )关联查询业务系统的出差单表,查询出出差天数等信息。

@Test
    public void findProcessInstance(){
//        获取processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取TaskService
        TaskService taskService = processEngine.getTaskService();
//        获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        查询流程定义的对象
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection1")
                .taskAssignee("张三")
                .singleResult();
//        使用task对象获取实例id
        String processInstanceId = task.getProcessInstanceId();
//          使用实例id,获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
//        使用processInstance,得到 businessKey
        String businessKey = processInstance.getBusinessKey();

        System.out.println("businessKey=="+businessKey);

    }

2.3、办理任务

注意:在实际应用中,完成任务前需要校验任务的负责人是否具有该任务的办理权限 。

/**
     * 完成任务,判断当前用户是否有权限
     */
    @Test
    public void completTask() {
        //任务id
        String taskId = "15005";
//        任务负责人
        String assingee = "张三";
        //获取processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 创建TaskService
        TaskService taskService = processEngine.getTaskService();
//        完成任务前,需要校验该负责人可以完成当前任务
//        校验方法:
//        根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskAssignee(assingee)
                .singleResult();
        if(task != null){
            taskService.complete(taskId);
            System.out.println("完成任务");
        }
    }