activiti-流程变量


以下内容均为黑马课程的学习笔记
视频链接: https://www.bilibili.com/video/BV1H54y167gf?p=106&spm_id_from=333.337.top_right_bar_window_history.content.click

二、流程变量

1、什么是流程变量

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

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

2、流程变量类型

如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无
法反序列化,需要生成 serialVersionUID。

在这里插入图片描述

3、流程变量作用域

流程变量的作用域可以是一个流程实例(processInstance),或一个任务(task),或一个执行实例
(execution)

3.1、globa变量

流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例时,可以称为 global 变量

注意:

如: Global变量:userId(变量名)、zhangsan(变量值)

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

3.2、local变量

任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。

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

4、流程变量的使用方法

4.1、在属性上使用UEL表达式

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

Activiti获取UEL表达式的值,即流程变量assignee的值 ,将assignee的值作为任务的负责人进行任务分配

4.2、在连线上使用UEL表达式

可以在连线上设置UEL表达式,决定流程走向。

比如:${price<10000} 。price就是一个流程变量名称,uel表达式结果类型为布尔类型。

如果UEL表达式是true,要决定 流程执行走向。

5、使用Global变量控制流程

5.1、需求

员工创建出差申请单,由部门经理审核,部门经理审核通过后出差3天及以下由人财务直接审批,3天以上先由总经理审核,总经理审核通过再由财务审批。

在这里插入图片描述

5.2、流程定义

1)、出差天数大于等于3连线条件

在这里插入图片描述

也可以使用对象参数命名,如evection.num:

在这里插入图片描述

2)、出差天数小于3连线条件

在这里插入图片描述

也可以使用对象参数命名,如:

在这里插入图片描述

5.3、设置global流程变量

在部门经理审核前设置流程变量,变量值为出差单信息(包括出差天数),部门经理审核后可以根据流程变量的值决定流程走向。

在设置流程变量时,可以在启动流程时设置,也可以在任务办理时设置

5.3.1、创建POJO对象

创建出差申请pojo对象

package com.itheima.demo.pojo;

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

/**
 * 出差申请 pojo
 */
public class Evection implements Serializable {
    /**
     * 主键id
     */
    private Long id;
    /**
     * 出差申请单名称
     */
    private String evectionName;
    /**
     * 出差天数
     */
    private Double num;
    /**
     * 预计开始时间
     */
    private Date beginDate;
    /**
     * 预计结束时间
     */
    private Date endDate;
    /**
     * 目的地
     */
    private String destination;
    /**
     * 出差事由
     */
    private String reson;

    public Long getId() {
        return id;
    }

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

    public String getEvectionName() {
        return evectionName;
    }

    public void setEvectionName(String evectionName) {
        this.evectionName = evectionName;
    }

    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 String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public String getReson() {
        return reson;
    }

    public void setReson(String reson) {
        this.reson = reson;
    }

    public Double getNum() {
        return num;
    }

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

5.3.2、启动流程时设置变量

在启动流程时设置流程变量,变量的作用域是整个流程实例。

通过Map<key,value>设置流程变量,map中可以设置多个变量,这个key就是流程变量的名字。

    /**
     * 启动流程实例,设置流程变量的值
     */
    @Test
    public void startProcess(){
//        获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        流程定义key
        String key = "myEvection2";
//       创建变量集合
        Map<String, Object> map = new HashMap<>();
//        创建出差pojo对象
        Evection evection = new Evection();
//        设置出差天数
        evection.setNum(2d);
//      定义流程变量,把出差pojo对象放入map
        map.put("evection",evection);
//      设置assignee的取值,用户可以在界面上设置流程的执行
        map.put("assignee0","张三");
        map.put("assignee1","李经理");
        map.put("assignee2","王总经理");
        map.put("assignee3","赵财务");
//        启动流程实例,并设置流程变量的值(把map传入)
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(key, map);
//      输出
        System.out.println("流程实例名称="+processInstance.getName());
        System.out.println("流程定义id=="+processInstance.getProcessDefinitionId());

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

说明:

startProcessInstanceByKey(processDefinitionKey, variables)

流程变量作用域是一个流程实例,流程变量使用Map存储,同一个流程实例设置变量map中key相同,后者覆盖前者。

5.3.2、任务办理时设置变量

在完成任务时设置流程变量,该流程变量只有在该任务完成后其它结点才可使用该变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已存在相同的名字则后设置的变量替换前边设置的变量。

这里需要在创建出差单任务完成时设置流程变量

    /**
     * 完成任务,判断当前用户是否有权限
     */
    @Test
    public void completTask() {
        //任务id
        String key = "myEvection2";
//        任务负责人
        String assingee = "张三";
//       获取processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//       创建TaskService
        TaskService taskService = processEngine.getTaskService();
//       创建变量集合
        Map<String, Object> map = new HashMap<>();
//        创建出差pojo对象
        Evection evection = new Evection();
//        设置出差天数
        evection.setNum(2d);
//      定义流程变量
        map.put("evection",evection);
//        完成任务前,需要校验该负责人可以完成当前任务
//        校验方法:
//        根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assingee)
                .singleResult();
        if(task != null){
            //完成任务是,设置流程变量的值
            taskService.complete(task.getId(),map);
            System.out.println("任务执行完成");
        }
    }

说明:

通过当前任务设置流程变量,需要指定当前任务id,如果当前执行的任务id不存在则抛出异常。

任务办理时也是通过map<key,value>设置流程变量,一次可以设置多个变量。

5.3.3、通过当前流程实例设置

通过流程实例id设置全局变量,该流程实例必须未执行完成。

    @Test
    public void setGlobalVariableByExecutionId(){
//    当前流程实例执行 id,通常设置为当前执行的流程实例
        String executionId="2601";
//     获取processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        创建出差pojo对象
        Evection evection = new Evection();
//        设置天数
        evection.setNum(3d);
//      通过流程实例 id设置流程变量
        runtimeService.setVariable(executionId, "evection", evection);
//      一次设置多个值
//      runtimeService.setVariables(executionId, variables)
    }

注意:

executionId必须当前未结束 流程实例的执行id,通常此id设置流程实例 的id。也可以通runtimeService.getVariable()获取流程变量。

5.3.4、通过当前任务设置
@Test
	public void setGlobalVariableByTaskId(){
		
		//当前待办任务id
		String taskId="1404";
//     获取processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		Evection evection = new Evection();
		evection.setNum(3);
		//通过任务设置流程变量
		taskService.setVariable(taskId, "evection", evection);
		//一次设置多个值 
		//taskService.setVariables(taskId, variables)
	}

注意:

任务id必须是当前待办任务id,act_ru_task中存在。如果该任务已结束,会报错

也可以通过taskService.getVariable()获取流程变量。

5.4、测试

正常测试:

​ 设置流程变量的值大于等于3天

​ 设计流程变量的值小于3天

异常测试:

​ 流程变量不存在

​ 流程变量的值为空NULL,price属性为空

​ UEL表达式都不符合条件

​ 不设置连线的条件

####5.5、注意事项

1、 如果UEL表达式中流程变量名不存在则报错。

2、 如果UEL表达式中流程变量值为空NULL,流程不按UEL表达式去执行,而流程结束 。

3、 如果UEL表达式都不符合条件,流程结束

4、 如果连线不设置条件,会走flow序号小的那条线

5.6、操作数据库表

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

//当前流程变量表
SELECT * FROM act_ru_variable 

记录当前运行流程实例可使用的流程变量,包括 global和local变量

Id_:主键

Type_:变量类型

Name_:变量名称

Execution_id_:所属流程实例执行id,global和local变量都存储

Proc_inst_id_:所属流程实例id,global和local变量都存储

Task_id_:所属任务id,local变量存储

Bytearray_:serializable类型变量存储对应act_ge_bytearray表的id

Double_:double类型变量值

Long_:long类型变量值

Text_:text类型变量值

 #历史流程变量表
SELECT * FROM act_hi_varinst 

记录所有已创建的流程变量,包括 global和local变量

字段意义参考当前流程变量表。

6、设置local流程变量

6.1、任务办理时设置

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

/*
*处理任务时设置local流程变量
*/
@Test
public void completTask() {
   //任务id
   String taskId = "1404";
//  获取processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
//  定义流程变量
   Map<String, Object> variables = new HashMap<String, Object>();
   Evection evection = new Evection ();
   evection.setNum(3d);
// 定义流程变量
   Map<String, Object> variables = new HashMap<String, Object>();
//  变量名是holiday,变量值是holiday对象
    variables.put("evection", evection);
//  设置local变量,作用域为该任务
    taskService.setVariablesLocal(taskId, variables);
//  完成任务
   taskService.complete(taskId);
}

​ 说明:

设置作用域为任务的local变量,每个任务可以设置同名的变量,互不影响。

6.2、通过当前任务设置
@Test
public void setLocalVariableByTaskId(){
//   当前待办任务id
    String taskId="1404";
//  获取processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    Evection evection = new Evection ();
    evection.setNum(3d);
//  通过任务设置流程变量
    taskService.setVariableLocal(taskId, "evection", evection);
//  一次设置多个值 
    //taskService.setVariablesLocal(taskId, variables)
}

注意:

任务id必须是当前待办任务id,act_ru_task中存在。

6.3、 Local变量测试1

如果上边例子中设置global变量改为设置local变量是否可行?为什么?

Local变量在任务结束后无法在当前流程实例执行中使用,如果后续的流程执行需要用到此变量则会报错。

6.4、 Local变量测试2

在部门经理审核、总经理审核、财务审核时设置local变量,可通过historyService查询每个历史任务时将流程变量的值也查询出来。

代码如下:

// 创建历史任务查询对象
      HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
      // 查询结果包括 local变量
      historicTaskInstanceQuery.includeTaskLocalVariables();
for (HistoricTaskInstance historicTaskInstance : list) {
         System.out.println("==============================");
         System.out.println("任务id:" + historicTaskInstance.getId());
         System.out.println("任务名称:" + historicTaskInstance.getName());
         System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
     System.out.println("任务local变量:"+ historicTaskInstance.getTaskLocalVariables());

}

注意:查询历史流程变量,特别是查询pojo变量需要经过反序列化,不推荐使用。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在原有Activiti的教程资源上对零散的源码进行了集中整理,并增加了pdm、IDE集成Activiti插件等文件,附上部分菜单,整理不易,给分支持,后期继续分享其他资源 01 - 问候Activiti他大爷 1.Activiti简介 2.Activiti的HelloWorld实现 1.Activiti的25张表; 2.引入Activiti配置文件activiti.cfg.xml; 3.在Eclipse 上安装Activiti插件; 4.初识Activiti流程设计工具; 5.了解Activiti bpmn图表对应的 XML 文件 6.Activiti HelloWorld实现(代码层次) 7.Activiti HelloWorld实现(表数据发生的变化) 02 - Activiti流程定义 1.流程定义添加(部署) 1.Classpath加载方式; 2.Zip加载方式; 2.流程定义查询 1.查询流程定义; 2.查询某个流程定义的流程设计图片; 3.查询最新版本的流程定义集合; 3.流程定义删除 1.删除key相同的所有流程定义 4.流程定义的‘修改’ 03 - Activiti流程实例 1.构建学生请假审批流程 2.执行对象概念 3.判断流程实例状态 4.历史流程实例查询 5.历史活动查询 04 - Activiti流程变量 1.流程变量的概念 2.使用TaskService设置和获取流程变量 3.局部流程变量 4.使用RuntimeService设置和获取流程变量 5.启动流程的时候设置流程变量 6.完成任务的时候设置流程变量 05 - Activiti流程控制网关 1.连线 2.排它网关 3.并行网关 06 - Activiti任务分配 1.个人任务分配 2.多用户任务分配 3.内置用户组设计表以及IdentityService 4.组任务分配
Activiti6最大的变化点就是对代码进行了重构,该版本修复以往的Bug并不多,但内部实现相对来说变化比较大。其突出的变化如下所示: 新增两款新引擎,Form引擎和DMN引擎(动态引擎)。其中DMN引擎允许开发人员创建自己的决策表。可以通过变量和定义的规则方式从决策表中计算结果。这些决策表的数据可以被rule task调用,决策表与流程实例是完全隔离的,相互之间不需要知道对方的存在。Form引擎可以通过Activiti6 UI界面进行配置,通俗一点的理解就是Activiti6将Form表单独立出来了。Form表单信息可以以JSON格式进行定义和使用。Activiti6 UI 默认包括新的规则引擎和表单引擎。 新增ad-hoc子流程。可以参考文章(ad-hoc子流程使用)。 作业执行器被重构。Activiti6版本仅保留了Activiti5版本中的异步作业执行器(async executor)。定时作业被划分了四个不同的表:executable jobs, timer jobs, suspended jobs 和deadletter jobs。引擎可以更快的执行作业。定时器作业在新的版本存储于单独的表中,一个线程会定时轮训需要执行的作业,快到期的作业会被添加到suspended jobs表中。重试的作业已经被干掉了,需要重试的作业会被添加到deadletter jobs表中。这样的重构意义主要是为了提高查询效率,可以执行的作业可以很快的被查询出来。 作业执行器通过消息队列的方式进行,关于这一点可以参考随后的文章。 瞬态变量的引入。瞬态变量不会存储到 Activiti 变量表中,但仍为单一的事务持续时间执行。比如可以在REST服务之间进行调用的时候使用,或者使用于Java service task。 引入了事务依赖监听器,可以参考Activiti依赖事务监听器(上)的讲解。 Activiti 6 UI 程序中,添加了DMN编辑器。 对于多实例节点而言,添加了终止多实例节点的相关方法。这个特性允许开发人员使用API结束多实例所有节点的执行。 优化补偿活动行为和在子流程中的使用。 在运行流程实例以及执行实例中添加了开始时间以及启动流程实例的人字段。在ru_task中增加了任务的认领时间(claim time)。 妥善解决数据库架构 (oracle/postgres) 的使用。 修复历史数据捕获。 大量重构 Activiti 6 UI 应用程序,例如应用程序中定义现在部署作为正常的活动部署,没有为其单独的应用程序定义表。 改进Activiti 6 QA中的问题。
主要内容: 2:工作流的执行过程 演示程序:Activiti控制台 3:Activiti介绍 Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务 流程图。 3.1:工作流引擎 ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。 3.2:BPMN 业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram) 3.3:数据库(先学后看) Activiti数据库支持: Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。 ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。 ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。 ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。 ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。 ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。 表结构操作: 3.3.1:资源库流程规则表 1)act_re_deployment 部署信息表 2)act_re_model 流程设计模型部署表 3)act_re_procdef 流程定义数据表 3.3.2:运行时数据库表 1)act_ru_execution 运行时流程执行实例表 2)act_ru_identitylink 运行时流程人员表,主要存储任务节点与参与者的相关信息 3)act_ru_task 运行时任务节点表 4)act_ru_variable 运行时流程变量数据表 3.3.3:历史数据库表 1)act_hi_actinst 历史节点表 2)act_hi_attachment 历史附件表 3)act_hi_comment 历史意见表 4)act_hi_identitylink 历史流程人员表 5)act_hi_detail 历史详情表,提供历史变量的查询 6)act_hi_procinst 历史流程实例表 7)act_hi_taskinst 历史任务实例表 8)act_hi_varinst 历史变量表 3.3.4:组织机构表 1)act_id_group 用户组信息表 2)act_id_info 用户扩展信息表 3)act_id_membership 用户与用户组对应信息表 4)act_id_user 用户信息表 这四张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足 3.3.5:通用数据表 1)act_ge_bytearray 二进制数据表 2)act_ge_property 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录, 3.4:activiti.cfg.xml(activiti的配置文件) Activiti核心配置文件,配置流程引擎创建工具的基本参数和数据库连接池参数。 定义数据库配置参数: jdbcUrl: 数据库的JDBC URL。 jdbcDriver: 对应不同数据库类型的驱动。 jdbcUsername: 连接数据库的用户名。 jdbcPassword: 连接数据库的密码。 基于JDBC参数配置的数据库连接 会使用默认的MyBatis连接池。 下面的参数可以用来配置连接池(来自MyBatis参数): jdbcMaxActiveConnections: 连接池中处于被使用状态的连接的最大值。默认为10。 jdbcMaxIdleConnections: 连接池中处于空闲状态的连接的最大值。 jdbcMaxCheckoutTime: 连接被取出使用的最长时间,超过时间会被强制回收。 省略...
activiti-eclipse-plugin是一个用于在Eclipse中集成和使用Activiti工作流引擎的插件。Activiti是一个开源的Java工作流引擎,它提供了一个完整的工作流管理解决方案,用于在企业应用中设计、执行和管理各种类型的工作流程。 使用activiti-eclipse-plugin,开发人员可以在Eclipse中方便地创建、编辑和部署Activiti流程定义文件。该插件提供了一个可视化的图形编辑器,可以通过拖拽和连接不同的活动元素(如任务、网关、事件等)来定义工作流程。开发人员还可以在插件中设置和配置各种属性,如任务分配、流程变量、事件监听器等。 activiti-eclipse-plugin还提供了与Activiti引擎的无缝集成。开发人员可以在Eclipse中运行和调试Activiti流程实例,查看流程执行的状态和变量。通过插件中的任务列表,开发人员可以管理和处理工作流程中的各种任务,并与其他系统进行集成。 此外,activiti-eclipse-plugin还提供了一些辅助工具和功能,如流程图导出、流程定义验证、任务候选人管理等。这些功能可以帮助开发人员更好地使用Activiti引擎,并提高工作流程的开发效率和质量。 总而言之,activiti-eclipse-plugin是一个强大的工具,可以帮助开发人员在Eclipse中使用Activiti工作流引擎,快速开发和管理各种类型的工作流程。它提供了方便的图形编辑器、流程运行调试功能和其他辅助工具,使开发人员能够更加轻松地使用Activiti来实现复杂的工作流应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值