首页 > 技术文章 > Activiti7进阶之个人任务和流程变量

xuweiweiwoaini 2020-09-13 09:56 原文

1 个人任务

1.1 分配任务负责人

1.1.1 固定分配

  • 在进行业务流程建模的时候指定固定的任务负责人。

固定分配

  • 在properties视图中,添加Assignee项为任务负责人。

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

1.1.2 表达式分配

1.1.2.1 UEL表达式

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

  • UEL-value定义如下:

    • assignee这个变量是Activiti的一个流程变量。

    UEL-value

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

    另外一种UEL-value

  • UEL-method定义如下:

    • holidayBean是Spring容器中的一个Bean,下图UEL-method的含义是调用该Bean的一个getHolidayId()方法。

UEL-method

1.1.2.2 使用流程变量分配任务

  • 定义任务分配流程变量:

UEL-value

  • 设置流程变量:在启动流程实例的时候设置流程变量
package com.sunxiaping;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-01 14:35
 */
public class ActivitiStartProcessInstanceTest {

    /**
     * act_hi_actinst 活动实例
     * act_hi_identitylink 参与者信息
     * act_hi_procinst 流程实例
     * act_hi_taskinst 任务实例
     * act_ru_execution 执行表
     * act_ru_identitylink 参与者信息
     * act_ru_task   任务表
     */
    @Test
    public void test() {
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //设置流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("assignee0", "张三");
        variables.put("assignee1", "李四");
        variables.put("assignee2", "王五");

        //根据流程定义的key启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", variables);
        //获取流程实例的相关信息
        String processDefinitionId = processInstance.getProcessDefinitionId();
        System.out.println("流程定义的id = " + processDefinitionId);
        String deploymentId = processInstance.getDeploymentId();
        System.out.println("流程部署的id = " + deploymentId);
        String id = processInstance.getId();
        System.out.println("流程实例的id = " + id);
        String activityId = processInstance.getActivityId();
        System.out.println("当前活动的id = " + activityId);

    }
}

1.1.2.3 注意事项

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

1.1.3 监听器分配

  • 任务监听器是发生对应的任务相关事件时执行自定义的Java逻辑或表达式。
  • 任务相关事件包括:
    • Event:
      • Create:任务创建后触发。
      • Assignment:任务分配后触发。
      • Delete:任务完成后触发。
      • All:所有事件发生都触发。

监听器分配

  • 自定义一个任务监听器类,然后此类必须实现org.activiti.engine.delegate.TaskListener接口:
package com.sunxiaping.task;

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

/**
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-05 15:44
 */
public class SelfTaskListener implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
    	//指定任务的负责人
    	delegateTask.setAssignee("张三");
    }
}

在实际开发中,一般也不使用监听器分配方式,太麻烦了。

2 流程变量

2.1 什么是流程变量?

  • 流程变量在Activiti中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和Activiti结合时少不了流程变量,流程变量就是Activiti在管理工作流时根据管理需要而设置的变量。
  • 比如在请假流程流转时如果请假天数>3天则有总经理审批,否则由人事直接审批,请假天数就可以设置流程变量,在流程流转时使用。

注意:虽然流程变量中可以存储业务数据,可以通过Activiti的API查询流程变量从而实现查询业务数据,但是不建议这么使用,因为业务数据查询由业务系统负责,Activiti设置流程变量是为了流程执行需要而创建的。

2.2 流程变量类型

流程变量类型.

注意:

  • 如果将POJO存储到流程变量中,必须实现序列化接口Serializable,为了防止由于新增字段无法反序列化。

2.3 流程变量的作用域

  • 流程变量的作用域范围可以是一个流程实例(ProcessInstance)、一个任务(Task)或一个执行实例(Execution)。

  • 流程变量的作用域范围的默认值是流程实例,作用域范围最大,可以称为global变量。

  • 流程变量的作用域范围如果仅仅针对一个任务或一个执行实例,那么作用域范围没有流程实例大,可以称为local变量。

  • global变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。

  • local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。local变量名也可以和global变量名相同,没有影响。

2.4 流程变量的使用方法

  • ①设置流程变量。

  • ②通过UEL表达式使用流程变量。

    • 1️⃣可以在assignee处设置UEL表达式,表达值的值就是任务的负责人。例如:${assignee},assignee就是一个流程变量的名称。

    在assignee处设置UEL表达式

    • 2️⃣可以在连线上设置UEL表达式,决定流程的走向。例如:${holidayNum>=3}${holidayNum<3}中holidayNum就是一个流程变量名称,UEL表达式的结果类型为boolean类型,如果UEL表达式的值是true,则总经理审批,否则直接人事存档。

    在连线上设置UEL表达式

2.5 使用global变量控制流程

2.5.1 需求

  • 员工创建请假流程申请单,由部门经理审批,部门经理审批通过后请假3天以下的由人事经理直接审批,3天及3天以上的由总经理审批,总经理审批通过再通过人事经理存档。

使用global变量控制流程的需求

2.5.2 画流程定义

  • 请假大于等于3天的连线条件:

请假大于等于3天的连线条件

  • 请假小于3天的连线条件:

请假小于3天的连线条件

本人在画BPMN文件的时候将填写请假申请单的assignee设置为张三,部门经理审批的assignee设置为李四,总经理审批的assignee设置为王五,人事经理存档设置为赵六。

2.5.3 设置global流程变量

2.5.3.1 准备工作

  • 导入相关jar包的Maven坐标:
<properties>
    <activiti.version>7.0.0.GA</activiti.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>7.0.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-model</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-converter</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-json-converter</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-layout</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti.cloud</groupId>
        <artifactId>activiti-cloud-services-api</artifactId>
        <version>7-201802-EA</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.19</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!-- log start -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.13.3</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.30</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.13.3</version>
    </dependency>
    <!-- log end -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.activiti.cloud.dependencies</groupId>
            <artifactId>activiti-cloud-dependencies</artifactId>
            <version>7.0.0.GA</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>
  • 日志文件(log4j2.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="INFO">
    <!--先定义所有的appender-->
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="Console" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
    <loggers>
        <root level="INFO">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>
  • Activiti的核心配置文件(activiti-cfg.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--  配置数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="url"
                  value="jdbc:mysql://192.168.1.146:3306/activiti?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
        <property name="password" value="123456"/>
        <property name="maxActive" value="3"/>
        <property name="maxIdle" value="1"/>
    </bean>

    <!-- Activiti单独运行的ProcessEngine配置 -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!--
            activiti数据库表处理策略
                false(默认值):检查数据库的版本和依赖库的版本,如果不匹配就抛出异常
                true:构建流程引擎时,执行检查,如果需要就执行更新。如果表不存在,就创建。
                create-drop:构建流程引擎时创建数据库报表,关闭流程引擎时就删除这些表。
                drop-create:先删除表再创建表。
                create:构建流程引擎时创建数据库表,关闭流程引擎时不删除这些表
        -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>
  • 请假实体类(Holiday.java)
package com.sunxiaping.task;

import java.io.Serializable;
import java.util.Date;

/**
 * 请假实体类
 *
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-06 14:30
 */
public class Holiday implements Serializable {

    /**
     * 主键
     */
    private Integer id;

    /**
     * 申请人名字
     */
    private String holidayName;

    /**
     * 开始时间
     */
    private Date beginDate;

    /**
     * 结束时间
     */
    private Date endDate;

    /**
     * 请假天数
     */
    private Float num;

    /**
     * 请假事由
     */
    private String reason;

    /**
     * 请假类型:病假、婚假、丧假等
     */
    private String type;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getHolidayName() {
        return holidayName;
    }

    public void setHolidayName(String holidayName) {
        this.holidayName = holidayName;
    }

    public Date getBeginDate() {
        return beginDate;
    }

    public void setBeginDate(Date beginDate) {
        this.beginDate = beginDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public Float getNum() {
        return num;
    }

    public void setNum(Float num) {
        this.num = num;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
  • 将流程定义和对应的图片放入到resources目录下:

在classpath下放入流程定义文件和图片

2.5.3.2 启动流程时设置

  • 示例:
package com.sunxiaping.test;

import com.sunxiaping.task.Holiday;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * global流程变量测试:启动流程时设置
 *
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-06 14:28
 */
public class ActivitiGlobalVariableStartProcessInstanceTest {
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        processEngine = configuration.buildProcessEngine();
    }

    @After
    public void after() {
        if (processEngine != null) {
            processEngine.close();
        }
    }

    /**
     * 流程定义部署
     */
    @Test
    public void testDeployment() {
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取Deployment对象
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/holiday.bpmn")
                .addClasspathResource("diagram/holiday.png")
                .name("请假申请流程")
                .deploy();
        String id = deployment.getId();
        System.out.println("流程部署的id = " + id);
        String name = deployment.getName();
        System.out.println("流程部署的名称 = " + name);
        String key = deployment.getKey();
        System.out.println("流程部署的key = " + key);
    }

    /**
     * 启动流程的时候给流程变量赋值
     */
    @Test
    public void testStartProcessInstance() {
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //封装global流程变量
        Holiday holiday = new Holiday();
        holiday.setNum(3f);
        holiday.setHolidayName("如花");
        holiday.setId(1);
        holiday.setType("年假");
        holiday.setReason("想男友了");
        holiday.setBeginDate(new Date());
        LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
        Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
        holiday.setEndDate(endDate);

        Map<String, Object> variables = new HashMap<>();
        variables.put("holiday", holiday);

        //根据流程定义的key启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);

        String id = processInstance.getId();
        System.out.println("流程实例的id = " + id);

        String name = processInstance.getName();
        System.out.println("流程实例的名称 = " + name);

        String processDefinitionId = processInstance.getProcessDefinitionId();
        System.out.println("流程定义的id = " + processDefinitionId);
    }

    /**
     * 测试张三完成任务
     */
    @Test
    public void testZhangSanTask() {
        String assignee = "张三";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取张三任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("张三任务的id = " + id);
            taskService.complete(id);
        }
    }

    /**
     * 测试李四完成任务
     */
    @Test
    public void testLiSiTask() {
        String assignee = "李四";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取李四任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("李四任务的id = " + id);
            taskService.complete(id);
        }
    }

    /**
     * 测试王五和赵六的任务,查看到底是王五还是赵六有任务
     */
    @Test
    public void testWangWuTask() {
        String assignee = "王五";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取王五任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("王五任务的id = " + id);
        }

        assignee = "赵六";
        taskService = processEngine.getTaskService();
        //获取赵六任务的列表
        taskList = taskService.createTaskQuery().taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("赵六任务的id = " + id);
        }
    }
}

2.5.3.3 完成任务时设置

  • 示例:
package com.sunxiaping.test;

import com.sunxiaping.task.Holiday;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * global流程变量测试:完成任务时设置
 *
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-06 14:28
 */
public class ActivitiGlobalVariableCompleteTaskTest {
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        processEngine = configuration.buildProcessEngine();
    }

    @After
    public void after() {
        if (processEngine != null) {
            processEngine.close();
        }
    }

    /**
     * 流程定义部署
     */
    @Test
    public void testDeployment() {
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取Deployment对象
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/holiday.bpmn")
                .addClasspathResource("diagram/holiday.png")
                .name("请假申请流程")
                .deploy();
        String id = deployment.getId();
        System.out.println("流程部署的id = " + id);
        String name = deployment.getName();
        System.out.println("流程部署的名称 = " + name);
        String key = deployment.getKey();
        System.out.println("流程部署的key = " + key);
    }

    /**
     * 启动流程
     */
    @Test
    public void testStartProcessInstance() {
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //根据流程定义的key启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);

        String id = processInstance.getId();
        System.out.println("流程实例的id = " + id);

        String name = processInstance.getName();
        System.out.println("流程实例的名称 = " + name);

        String processDefinitionId = processInstance.getProcessDefinitionId();
        System.out.println("流程定义的id = " + processDefinitionId);
    }

    /**
     * 测试张三完成任务,张三完成任务的时候给global变量赋值
     */
    @Test
    public void testZhangSanTask() {
        String assignee = "张三";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取张三任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("张三任务的id = " + id);

            //封装global流程变量
            Holiday holiday = new Holiday();
            holiday.setNum(3f);
            holiday.setHolidayName("如花");
            holiday.setId(1);
            holiday.setType("年假");
            holiday.setReason("想男友了");
            holiday.setBeginDate(new Date());
            LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
            Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
            holiday.setEndDate(endDate);

            Map<String, Object> variables = new HashMap<>();
            variables.put("holiday", holiday);

            taskService.complete(id, variables);
        }
    }

    /**
     * 测试李四完成任务
     */
    @Test
    public void testLiSiTask() {
        String assignee = "李四";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取李四任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("李四任务的id = " + id);
            taskService.complete(id);
        }
    }

    /**
     * 测试王五和赵六的任务,查看到底是王五还是赵六有任务
     */
    @Test
    public void testWangWuTask() {
        String assignee = "王五";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取王五任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("王五任务的id = " + id);
        }

        assignee = "赵六";
        taskService = processEngine.getTaskService();
        //获取赵六任务的列表
        taskList = taskService.createTaskQuery().taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("赵六任务的id = " + id);
        }
    }
}

2.5.3.4 通过当前流程实例设置

  • 通过流程实例的id设置全局流程变量,该流程实例必须没有执行完毕。

  • 示例:

package com.sunxiaping.test;

import com.sunxiaping.task.Holiday;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * global流程变量测试:通过当前流程实例设置
 *
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-06 14:28
 */
public class ActivitiGlobalVariableCurrentExecutionIdTest {
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        processEngine = configuration.buildProcessEngine();
    }

    @After
    public void after() {
        if (processEngine != null) {
            processEngine.close();
        }
    }

    /**
     * 流程定义部署
     */
    @Test
    public void testDeployment() {
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取Deployment对象
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/holiday.bpmn")
                .addClasspathResource("diagram/holiday.png")
                .name("请假申请流程")
                .deploy();
        String id = deployment.getId();
        System.out.println("流程部署的id = " + id);
        String name = deployment.getName();
        System.out.println("流程部署的名称 = " + name);
        String key = deployment.getKey();
        System.out.println("流程部署的key = " + key);
    }

    /**
     * 启动流程
     */
    @Test
    public void testStartProcessInstance() {
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //根据流程定义的key启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);

        String id = processInstance.getId();
        System.out.println("流程实例的id = " + id);

        String name = processInstance.getName();
        System.out.println("流程实例的名称 = " + name);

        String processDefinitionId = processInstance.getProcessDefinitionId();
        System.out.println("流程定义的id = " + processDefinitionId);
    }


    /**
     * 通过流程实例的id设置流程变量,该流程必须没有执行完毕
     */
    @Test
    public void testSetVariable(){
        String executionId = "2501";

        //封装global流程变量
        Holiday holiday = new Holiday();
        holiday.setNum(3f);
        holiday.setHolidayName("如花");
        holiday.setId(1);
        holiday.setType("年假");
        holiday.setReason("想男友了");
        holiday.setBeginDate(new Date());
        LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
        Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
        holiday.setEndDate(endDate);

        Map<String, Object> variables = new HashMap<>();
        variables.put("holiday", holiday);

        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //设置流程变量
        runtimeService.setVariables(executionId,variables);
    }



    /**
     * 测试张三完成任务
     */
    @Test
    public void testZhangSanTask() {
        String assignee = "张三";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取张三任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("张三任务的id = " + id);

            taskService.complete(id);
        }
    }

    /**
     * 测试李四完成任务
     */
    @Test
    public void testLiSiTask() {
        String assignee = "李四";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取李四任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("李四任务的id = " + id);
            taskService.complete(id);
        }
    }

    /**
     * 测试王五和赵六的任务,查看到底是王五还是赵六有任务
     */
    @Test
    public void testWangWuTask() {
        String assignee = "王五";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取王五任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("王五任务的id = " + id);
        }

        assignee = "赵六";
        taskService = processEngine.getTaskService();
        //获取赵六任务的列表
        taskList = taskService.createTaskQuery().taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("赵六任务的id = " + id);
        }
    }
}

2.5.3.5 通过当前任务设置

  • 该任务必须待办任务,act_ru_task表中存在。如果该任务已经结束,就会报错。

  • 示例:

package com.sunxiaping.test;

import com.sunxiaping.task.Holiday;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * global流程变量测试:通过当前流程实例设置
 *
 * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
 * @version 1.0
 * 2020-08-06 14:28
 */
public class ActivitiGlobalVariableCurrentTaskIdTest {
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        processEngine = configuration.buildProcessEngine();
    }

    @After
    public void after() {
        if (processEngine != null) {
            processEngine.close();
        }
    }


    /**
     * 流程定义部署
     */
    @Test
    public void testDeployment() {
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取Deployment对象
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/holiday.bpmn")
                .addClasspathResource("diagram/holiday.png")
                .name("请假申请流程")
                .deploy();
        String id = deployment.getId();
        System.out.println("流程部署的id = " + id);
        String name = deployment.getName();
        System.out.println("流程部署的名称 = " + name);
        String key = deployment.getKey();
        System.out.println("流程部署的key = " + key);
    }

    /**
     * 启动流程
     */
    @Test
    public void testStartProcessInstance() {
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //根据流程定义的key启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);

        String id = processInstance.getId();
        System.out.println("流程实例的id = " + id);

        String name = processInstance.getName();
        System.out.println("流程实例的名称 = " + name);

        String processDefinitionId = processInstance.getProcessDefinitionId();
        System.out.println("流程定义的id = " + processDefinitionId);
    }
    

    /**
     * 测试张三完成任务
     */
    @Test
    public void testZhangSanTask() {
        String assignee = "张三";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取张三任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();

            //封装global流程变量
            Holiday holiday = new Holiday();
            holiday.setNum(3f);
            holiday.setHolidayName("如花");
            holiday.setId(1);
            holiday.setType("年假");
            holiday.setReason("想男友了");
            holiday.setBeginDate(new Date());
            LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
            Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
            holiday.setEndDate(endDate);

            Map<String, Object> variables = new HashMap<>();
            variables.put("holiday", holiday);


            taskService.setVariables(id,variables);

            System.out.println("张三任务的id = " + id);

            taskService.complete(id);
        }
    }

    /**
     * 测试李四完成任务
     */
    @Test
    public void testLiSiTask() {
        String assignee = "李四";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取李四任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("李四任务的id = " + id);
            taskService.complete(id);
        }
    }

    /**
     * 测试王五和赵六的任务,查看到底是王五还是赵六有任务
     */
    @Test
    public void testWangWuTask() {
        String assignee = "王五";
        //流程定义的key
        String processDefinitionKey = "holiday";
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //获取王五任务的列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("王五任务的id = " + id);
        }

        assignee = "赵六";
        taskService = processEngine.getTaskService();
        //获取赵六任务的列表
        taskList = taskService.createTaskQuery().taskAssignee(assignee).list();

        for (Task task : taskList) {
            //任务的id
            String id = task.getId();
            System.out.println("赵六任务的id = " + id);
        }
    }

}

2.5.4 注意事项

  • 如果UEL表达式中流程变量名不存在则报错。
  • 如果UEL表达式中流程变量值为null,流程不按UEL表达式去执行,而流程结束。
  • 如果UEL表达式都不符合条件,流程结束。
  • 如果连接不设置条件,会走flow序号小的那条线。

2.5.5 操作的数据库表

  • 设置流程变量会在当前执行流程变量表(act_ru_variable)插入记录,同时也会在历史流程变量表(act_hi_varinst)中也插入记录。

2.6 设置Local流程变量(实际开发中一般不用)

2.6.1 完成任务前设置

  • 在任务完成前设置Local流程变量,当前运行的Local流程变量只能在该任务结束前使用,任务结束该变量无法在当前流程实例使用,可以通过查询历史任务查询。

  • 示例:

/**
     * 测试张三完成任务
     */
@Test
public void testZhangSanTask() {
    String assignee = "张三";
    //流程定义的key
    String processDefinitionKey = "holiday";
    //获取TaskService对象
    TaskService taskService = processEngine.getTaskService();
    //获取张三任务的列表
    List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

    for (Task task : taskList) {
        //任务的id
        String id = task.getId();
        System.out.println("张三任务的id = " + id);

        //封装global流程变量
        Holiday holiday = new Holiday();
        holiday.setNum(3f);
        holiday.setHolidayName("如花");
        holiday.setId(1);
        holiday.setType("年假");
        holiday.setReason("想男友了");
        holiday.setBeginDate(new Date());
        LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
        Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
        holiday.setEndDate(endDate);

        Map<String, Object> variables = new HashMap<>();
        variables.put("holiday", holiday);

        taskService.setVariablesLocal(id,variables);

        taskService.complete(id);
    }
}

2.6.2 通过当前任务设置

  • 示例:
/**
     * 测试张三完成任务
     */
@Test
public void testZhangSanTask() {
    String assignee = "张三";
    //流程定义的key
    String processDefinitionKey = "holiday";
    //获取TaskService对象
    TaskService taskService = processEngine.getTaskService();
    //获取张三任务的列表
    List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(assignee).list();

    for (Task task : taskList) {
        //任务的id
        String id = task.getId();

        //封装global流程变量
        Holiday holiday = new Holiday();
        holiday.setNum(3f);
        holiday.setHolidayName("如花");
        holiday.setId(1);
        holiday.setType("年假");
        holiday.setReason("想男友了");
        holiday.setBeginDate(new Date());
        LocalDateTime endLocalDateTime = LocalDateTime.now().plusDays(3);
        Date endDate = Date.from(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
        holiday.setEndDate(endDate);

        Map<String, Object> variables = new HashMap<>();
        variables.put("holiday", holiday);


        taskService.setVariables(id,variables);

        System.out.println("张三任务的id = " + id);

        taskService.complete(id);
    }
}

推荐阅读