Flowable进阶学习(四)任务分配与流程变量

news2024/9/23 21:21:34

文章目录

  • 一、任务分配
    • 1. 固定分配
    • 2. 表达式分配
      • 值表达式:Value expression
      • 方法表达式:Method expression
    • 3. 监听器分配
  • 二、流程变量
    • 1. 全局变量
    • 2. 局部变量
    • 案例:

一、任务分配

1. 固定分配

在绘制流程图时或在流程文件中通过Assignee来指定的方式。
在这里插入图片描述在这里插入图片描述

2. 表达式分配

Flowable使用UEL(Unified Expression Language)进行表达式解析。Flowable支持两种UEL表达式:UEL-value和UEL-method。

值表达式:Value expression

解析为一个值,默认情况下,所有流程变量都可以使用。所有的SpringBean也可以使用在表达式里。eg:${myVar}${myBean.myProperty}

  1. 创建流程文件
    在这里插入图片描述在这里插入图片描述

  2. 启动一个流程实例

    /**
    * 启动流程实例
    */
    @Test
    public void test2_run_proc() {
       Map<String, Object> params = new HashMap<>();
       params.put("assignee0", "whx");
       params.put("assignee1", "huathy");
       ProcessInstance processInstance = processEngine.getRuntimeService()
               .startProcessInstanceById("qjlc23:1:4", params);
       System.out.println("processInstance.getName() = " + processInstance.getName());
       Map<String, Object> processVariables = processInstance.getProcessVariables();
       for (String key : processVariables.keySet()) {
           System.out.println("params => " + key + "~" + processVariables.get(key));
       }
    }
    
  3. 通过查看表数据变动,可以看到ASSIGNEE_的值为whx,可见表达式已经被解析。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    -- ACT_RU_TASK
    ID_ |REV_|EXECUTION_ID_|PROC_INST_ID_|PROC_DEF_ID_|TASK_DEF_ID_|SCOPE_ID_|SUB_SCOPE_ID_|SCOPE_TYPE_|SCOPE_DEFINITION_ID_|NAME_ |PARENT_TASK_ID_|DESCRIPTION_|TASK_DEF_KEY_                           |OWNER_|ASSIGNEE_|DELEGATION_|PRIORITY_|CREATE_TIME_           |DUE_DATE_|CATEGORY_|SUSPENSION_STATE_|TENANT_ID_|FORM_KEY_|CLAIM_TIME_|IS_COUNT_ENABLED_|VAR_COUNT_|ID_LINK_COUNT_|SUB_TASK_COUNT_|
    ----+----+-------------+-------------+------------+------------+---------+-------------+-----------+--------------------+------+---------------+------------+----------------------------------------+------+---------+-----------+---------+-----------------------+---------+---------+-----------------+----------+---------+-----------+-----------------+----------+--------------+---------------+
    7507|   1|7504         |7501         |qjlc23:1:4  |            |         |             |           |                    |提交请假申请|               |            |sid-04330515-D69E-4BA7-94FE-492984A4E5A0|      |whx      |           |       50|2023-01-21 23:41:58.912|         |         |                1|          |         |           |                1|         0|             0|              0|
    
  4. 完成流程实例

    /**
     * 完成任务
     */
    @Test
    public void test2_complete_proc() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processInstanceId("7501")
                .taskAssignee("whx").singleResult();
        taskService.complete(task.getId());
    }
    
  5. 查看数据库ACT_RU_TASK表(可见节点名称与任务指派人已变化) 在这里插入图片描述

方法表达式:Method expression

调用一个方法,可以带参或者不带。当调用无参方法的时候,要确保方法名后面添加空括号(避免与值表达式混淆)。传递的参数可以是字面值,也可以是表达式,会进行自动解析。eg:

${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.do(myvar, execution)}

myBean是spring容器中的一个Bean对象,表示调用bean的addNewOrder方法。

3. 监听器分配

可以使用监听器来完成很多flowable的流程业务。
我们在此处使用监听器来完成负责人的指定,那么我们在流程设计的时候就不需要指定assignee。

  1. 创建一个监听器类
package org.flowable.listener;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

/**
 * @author Huathy
 * @date 2023-01-22 12:28
 * @description 自定义监听器
 */
public class MyTaskListener implements TaskListener {

    /**
     * 监听器触发的方法
     *
     * @param delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("==》MyTaskListener监听器触发");
        System.out.println("delegateTask.getName() = " + delegateTask.getName());
        // 当满足条件则设置任务分配人为huathy否则为whx
        if ("提交请假申请".equals(delegateTask.getName()) && "create".equalsIgnoreCase(delegateTask.getEventName())) {
            delegateTask.setAssignee("huathy");
        } else {
            delegateTask.setAssignee("whx");
        }
    }
}
  1. 设计流程,导出流程文件
    在这里插入图片描述3. 部署流程
    @Test
    public void test1_deploy() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("请假流程23-02.bpmn20.xml")
                .name("测试请假流程2023-02").deploy();
        System.out.println("deploy.getName() = " + deploy.getName());
        System.out.println("deploy.getId() = " + deploy.getId());
    }
    

二、流程变量

流程实例按步骤执行时,需要使用一些数据。在Flowable中,这些数据称作变量(variable),并存储到数据库中。变量可以用在表达式中(例如在排他网关中用于选择正确的出口路径),也可以在Java服务任务(service task)中用于调用外部服务(例如为服务提供输入或结果存储),等等。
咯iu成实例可以持有变量(称作流程变量process variables),用户任务以执行(excutions)——流程当前活动节点的指针——也可以持有变量。流程实例可以持有任意数量的变量,每个变量存储为ACT_RU_VARIABLE数据库表的一行记录。
所有的startProcessInstanceXXX方法都有一个可选参数,用于在流程实例创建及启动时设置变量。eg:在RuntimeService中:

ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables);

也可以在流程执行中加入变量,eg:RuntimeService

void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);

实例关系:通常情况下没有子流程的,流程实例与执行实例一一对应。
实例关系

1. 全局变量

流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例的时候,可以称为global变量。eg:userId。
global变量中变量名不可重复,设置相同名称的变量,新值会覆盖旧值。

2. 局部变量

任务和执行实例仅仅是针对要给任务和一个执行实例的范围,范围没有流程实例大,成为local变量。
local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同。local变量名也可以与global变量名相同。

案例:

员工创建出差申请单,由上级领导审批通过后,根据天数判断,3天内可由财务审批通过,3天以上需要流转到总经理审批,再由财务审批。

员工出差流程图

package com.hx;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;

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

/**
 * @author Huathy
 * @date 2022-05-12 23:40
 * @description
 * 1.首先部署流程   2.运行流程实例   3.提交出差申请   4.更新流程变量
 * 5.完成上级审批   6.观察数据库变化
 */
public class Test6_Demo1_Evection {
    ProcessEngineConfiguration configuration = null;
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        // 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngine
        configuration = new StandaloneInMemProcessEngineConfiguration();
        // 配置相关数据库连接
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("admin");
        configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable1?serverTimeZone=UTC&nullCatalogMeansCurrent=true");
        // 如果数据库中的表结构不存在则新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        processEngine = configuration.buildProcessEngine();
    }

    @Test
    public void test_deploy() {
        // 2. 获取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3. 完成流程部署操作
        Deployment deploy = repositoryService.createDeployment()
                // 关联要部署的流程文件
                .addClasspathResource("出差申请流程.bpmn20.xml")
                .name("出差申请流程2023")
                .deploy();  // 部署流程
        System.out.println("deploy.getId() => " + deploy.getId());
        System.out.println("deploy.getName() => " + deploy.getName());
    }

    @Test
    public void test_run_proc() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> params = new HashMap<>();
        params.put("assignee0", "whx");
        params.put("assignee1", "hx1");
        params.put("assignee2", "hx2");
        params.put("assignee3", "huathy");
        runtimeService.startProcessInstanceById("CCSQLC:1:4", params);
    }

    @Test
    public void test_complete_task1() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 2);
        taskService.complete(task.getId(), processVariables);
    }

    /**
     * 根据taskID来更新本地(实例)变量
     */
    @Test
    public void test_update_variables_local() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 6);
        taskService.setVariablesLocal(task.getId(), processVariables);
    }

    /**
     * 根据taskID来更新流程变量
     */
    @Test
    public void test_update_variables() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量。当局部变量和全局变量都存在的时候,取出来的是局部变量。
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 5);
        taskService.setVariables(task.getId(), processVariables);
    }

    /**
     * 完成上级审批
     */
    @Test
    public void test_complete_task2() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        taskService.complete(task.getId());
    }
}

每次完成任务后,查看数据库中的运行时变量表的变化。可以观察到局部变量在任务完成后被删除存入了历史变量表。随后再进行任务流转。
在这里插入图片描述在完成上级领导审批节点后,观察ACT_RU_TASK表,也可以看到节点流转到了财务审批。说明这里使用的是全局变量进行判断。局部变量已经在上一任务完成时被删除。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.2 特征图尺寸计算与参数共享|池化层的作用|整体网络架构|VGG网络架构|残差网络Resnet|感受野的作用

文章目录特征图尺寸计算与参数共享池化层的作用整体网络架构VGG网络架构&#xff08;了解向&#xff0c;背景向&#xff09;残差网络Resnet&#xff08;了解向&#xff0c;背景向&#xff09;感受野的作用特征图尺寸计算与参数共享 给个例子&#xff1a; 如果输入的数据是32323…

GDB的常用命令

GDB是一个调试程序&#xff0c;可以用来调试C/C程序。这个C/C要产生符号表才能使用GDB调用。例如C&#xff1a; g -g source.cppGDB常用命令 首先要生成一个有调试符号的ELF文件&#xff08;exe curable and linkable format),简单点说就是一个带调试符号可执行文件。加-g参数…

client-go实战之八:更新资源时的冲突错误处理

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 系列文章链接 client-go实战之一&#xff1a;准备工作client-go实战之二:RESTClientclient-go实战之三&#xff1a;Clientsetclient-go实战之四&#xff1a;…

matlab控制理论学习

一、求传递函数表达式residue() 1、极点不同的情况 分子和分母的矩阵分别为&#xff1a; >> num[2 5 3 6]; >> den[1 6 11 6]; 使用下列命令&#xff0c;即可对分式进行展开&#xff0c;展开后有多项&#xff0c;每一项的分子一定是数字&#xff0c;而分母则是一个…

mysql底层解析——连接层,包括连接、解析、缓存、引擎、存储等

1、 前言 打算写一个系列的文章&#xff0c;主要是mysql底层解析。 很多时候&#xff0c;程序员对mysql处于频繁使用&#xff0c;但都一知半解的程度&#xff0c;除了会加个索引&#xff0c;貌似也没啥优化的技能了。事实上&#xff0c;mysql能有今日的成就&#xff0c;必然不…

Selenium4新特性-关联定位策略

Selenium 4 引入了关联元素定位策略(Relative Locators)。这种方式主要是应对一些不好定位的元素&#xff0c;但是其周边相关联的元素比较好定位。实现步骤是先定位周边较容易定位的元素&#xff0c;再根据关联元素定位策略定位到想定位的那个元素。如下以具体案例讲解用法。 以…

UDS诊断系列介绍15-FIM模块功能介绍

本文框架1. 系列介绍1.1 FIM模块概述2. FIM相关概念2.1 FID概念2.2 FIM数据结构3. FIM模块作用过程4. Autosar系列文章快速链接1. 系列介绍 UDS&#xff08;Unified Diagnostic Services&#xff09;协议&#xff0c;即统一的诊断服务&#xff0c;是面向整车所有ECU的一种诊断…

English Learning - L1-13 主动脉修饰 (上) 2023.1.16 周一

English Learning - L1-13 主动脉修饰 &#xff08;上&#xff09; 2023.1.16 周一11 主动脉修饰11.1 定语两大核心when 引导的定语从句where 引导的定语从句为什么有时关系词前会有介词到底用 which 还是用 that ?1. 先行词是 all, much, little, few, the one 等不定代词&a…

Java---微服务---SpringCloud(1)

SpringCloud011.认识微服务1.0.学习目标1.1.单体架构1.2.分布式架构1.3.微服务1.4.微服务技术对比1.5.SpringCloud1.6.总结2.服务拆分和远程调用2.1.服务拆分原则2.2.服务拆分示例2.2.1.导入Sql语句2.2.2.导入demo工程2.3.实现远程调用案例2.3.1.案例需求&#xff1a;2.3.2.注册…

如何使用Facebook Insights提升SEO策略

搜索流量是所有网站都必须考虑的重要因素&#xff0c;但如何才能吸引到更多的访问者呢&#xff1f;我们都知道 Google的 SEO算法&#xff0c;那 Google针对搜索流量的算法有哪些&#xff1f;Facebook Insights &#xff08;Facebook Search Engine Insight&#xff09;是一款搜…

基于python个性化推荐购物系统的设计与实现

源码获取&#xff1a;https://www.bilibili.com/video/BV1Ne4y1g7dC/ 一、开发工具及技术 Python3.6.8&#xff0c;Django3&#xff0c;mysql8&#xff0c;navicat数据库管理工具&#xff0c;html页面&#xff0c;javascript脚本&#xff0c;jquery脚本&#xff0c;bootstrap…

从零实现一个组件库(一)项目环境搭建

文章目录前言monorepo架构1.monorepo架构的优势2.使用pnpm搭建monorepo架构&#xff08;1&#xff09;全局安装pnpm&#xff08;2&#xff09;初始化项目&#xff08;3&#xff09;新建workspace.yaml文件4.不同包之间的相互引用TypeScript支持1.安装TypeScript2.初始化TypeScr…

6、工程和模块管理

文章目录6、工程和模块管理6.1 IDEA 项目结构6.2 Project和Modoule的概念6.3 创建模块6.4 删除模块6.5 导入别人的模块6.6 当导入的模块字符集问题&#xff0c;导致中文乱码6.7 同时打开两个IDEA项目工程1 新建一个IDEA项目2 两个IDEA项目工程效果3 打开两个IDEA项目【尚硅谷】…

Kubernetes:开源 K8s 管理工具 Rancher 认知

写在前面 博文内容涉及Rancher 的介绍&#xff0c;集群内安装查看 Rancher 的基本功能理解不足小伙伴帮忙指正 我所渴求的&#xff0c;無非是將心中脫穎語出的本性付諸生活&#xff0c;為何竟如此艱難呢 ------赫尔曼黑塞《德米安》 Rancher 介绍 Rancher 是一个 Kubernetes 管…

计算机基础——python数据结构之顺序表和链表

计算机基础——数据结构概述数据结构算法时间复杂度python的代码执行时间测量模块线性表顺序表顺序表的连续存储顺序表的两种基本实现方式链表单向链表顺序表和单链表的对比双向链表单向循环链表概述 数据是信息的载体&#xff0c;是描述客观师傅属性的数、字符以及所有能输入…

抖音小黄车挂淘宝店相关问题记录

不开淘宝店&#xff0c;但作为技术被客户问起来&#xff0c;总得知道个一二&#xff0c;今天研究了一下&#xff0c;大致情况如下&#xff1a; 抖音绑定淘宝推广id 大致流程就是抖音开通橱窗&#xff0c;橱窗和淘宝挂钩&#xff0c;淘宝商品引入橱窗。 首先要满足抖音要求&a…

AlmaLinux 9 安装Oracle GraalVM Enterprise Edition 21.3.x

今天我们尝试一下在AlmaLinux 9 安装Oracle GraalVM Enterprise Edition 21.3.x。 GraalVM Enterprise 21 是一个 Long-Term-Support (LTS) 版本。 注意&#xff1a;下载Oracle GraalVM Enterprise Edition需要有Oracle账户&#xff0c;如果没有&#xff0c;可以通过访问创建您…

【SpringCloud】Nacos注册中心、配置中心用法与原理(上)

【SpringCloud】Nacos注册中心、配置中心用法与原理&#xff08;上&#xff09; 一、Nacos注册中心 1. 安装Nacos 【BUG】请注意Nacos2.0版本与1.0版本是有差别的&#xff01; 2. Nacos的服务注册使用样例 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;配…

PowerShell 学习笔记

一、PowerShell 强大之处使用方便面向对象使用.net平台功能兼容性好&#xff08;兼容CMD等&#xff09;可扩展性好二、快捷键Tab&#xff1a;自动补齐命令或者文件名三、管道和重定向管道&#xff1a;上条命令的输出作为下一条命令的输入举例如下&#xff1a;列出当前目录ls结果…

FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(四)

第七章 实战项目提升&#xff0c;完善简历 19.OV7725摄像头实时采集送HDMI显示&#xff08;四&#xff09; 在介绍完OV7725初始化配置和视频采集模块后&#xff0c;就到了整个项目的核心部分即DDR3乒乓存储图像模块&#xff0c;为了实现整个FPGA项目工程当中良好的实时性&…