Flowable进阶学习(六)网关

news2025/1/16 8:11:18

文章目录

  • 排他网关
    • 案例:
  • 并行网关
    • 案例:
  • 包容网关
    • 案例:
  • 事件网关

网关(gateway)用来控制流程的流向。来实现复杂的审批流程。
网关的分类包括:排他网关、并行网关、包容网关、事件网关。

排他网关

exclusive gateway也成为异域网关XORgateway。用于对流程中的决策建模。当执行到这个网关的时候,会按照所有出口顺序定义的顺序对他们进行计算。选择第一个条件计算为true的顺序流(当没有设置条件的时候,默认顺序六为true)继续流程。
注意:这里出口顺序流的含义与BPMN2.0中的一般情况不同。一般的,会选择所有计算条件为true的顺序流,并行执行。而使用排他网关时,只选择一条顺序流。当多条顺序流条件都为true的时候,仅会选择在XML中最先定义的顺序流继续执行。若没有可选的顺序流则会抛出异常。

案例:

绘制排他网关流程图,并分配处理人
在这里插入图片描述部署流程、运行实例、与完成任务

package com.hx;

import org.flowable.engine.*;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
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 排他网关
 */
public class Test9_ExclusiveGateway {
    ProcessEngineConfiguration configuration = null;
    ProcessEngine processEngine = null;

    static String PROC_DEF_ID = "qjlc-exclusive:1:4";

    @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();
        // 给流程定义中的UEL表达式赋值
        Map<String, Object> params = new HashMap<>();
        params.put("num", 2);
        // params.put("num", 3);
        // params.put("num", 4);
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID, params);
        System.out.println("processInstance.getId() = " + processInstance.getId());
    }

    /**
     * 任务完成
     */
    @Test
    public void complete_task() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionId(PROC_DEF_ID)
                .taskCandidateOrAssigned("xixi")
                .singleResult();
        if (task != null) {
            taskService.complete(task.getId());
            System.out.println("任务完成");
        }
    }
}

若从网关出去的线,所有条件都不满足的情况下,会抛出如下异常。
在这里插入图片描述
但是注意的是这里的任务并没有结束,还是原来的任务,我们可以重新设置流程变量:

@Test
public void test_set_variables(){
    TaskService taskService = processEngine.getTaskService();
    Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
            .taskCandidateOrAssigned("xixi").singleResult();
    taskService.setVariable(task.getId(),"num",10);
}

这里与之前案例中讲到的分支情况要做一个对比,其不同点在于使用网关的情况下,任务失败出现异常,该流程并未结束。而分支的情况若出现异常,则流程异常结束。这也是为什么需要排他网关的原因。在这里插入图片描述

并行网关

并行网关允许将流程拆分为多个分支,也可以将多个分支汇集到一起。并行网关的功能是基于流入流出的顺序流。

  • fork分支:用于任务的开始。并行后所有外出的顺序流,为每个顺序流都创建一个并发分支。
  • join汇聚:用于任务的汇聚。所有道道并行网关,在此处等待的进入分支,直到所有进入顺序流的分支都达到后,流程会通过汇集网关。

注意:如果同一个并行网关有多个进入和外出顺序流,他就同时具有分支和汇聚的功能。此时网关会线汇聚所有进入的顺序流,然后再切分为多个并行分支。
区别:并行网关并不会解析条件。即使顺序流中定义了条件,也会被忽略。

案例:

绘制流程图,并分配处理人。
在这里插入图片描述
当流程流转到并行网关位置的时候,在ACT_RU_TASK表和ACT_RU_EXECUTION表会新增俩条记录。一个流程可以包含多个任务和执行实例。
我们先运行完成任务的方法,完成一个经理审批,可以看到任务没有继续向下流转,而是等到所有并行任务完成后再向下流转。

package com.hx;

import org.flowable.engine.*;
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.Map;

/**
 * @author Huathy
 * @date 2022-05-12 23:40
 * @description 并行网关
 */
public class Test10_ParallelGateway {
    ProcessEngineConfiguration configuration = null;
    ProcessEngine processEngine = null;

    static String PROC_DEF_ID = "qjlc-parallel:1:20004";

    @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();
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID);
        System.out.println("processInstance.getId() = " + processInstance.getId());
    }

    /**
     * 任务完成
     */
    @Test
    public void complete_task() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
                .taskCandidateOrAssigned("whx").singleResult();
        if (task != null) {
            taskService.complete(task.getId());
            System.out.println("任务完成");
        }
    }
}

包容网关

包容网关可以看作是排他网关与并行网关的结合。并行网关也会像排他网关一样,解析定义条件。但区别是包含网关可以选择多条顺序流,这与并行网关是一样的。

  • 分支:所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行的方式继续执行,会为每个顺序流创建一个分支。
  • 汇聚:所有并行分支达到包含网关,会进入等待状态,直到每个包含流程token的进入顺序流的分支都到达。即包含网关只等待被选中执行了的进入顺序流。这也是与并行网关的区别。

案例:

在这里插入图片描述

package com.hx;

import org.flowable.engine.*;
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.Map;

/**
 * @author Huathy
 * @date 2022-05-12 23:40
 * @description 包容网关
 */
public class Test11_InclusiveGateway {
    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());
    }

    static String PROC_DEF_ID = "qjlc-inclusive:1:4";

    /**
     * 运行流程实例
     */
    @Test
    public void test_run_proc() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 给流程定义中的UEL表达式赋值
        Map<String, Object> params = new HashMap<>();
        params.put("num", 3);
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID, params);
        System.out.println("processInstance.getId() = " + processInstance.getId());
    }

    /**
     * 任务完成
     */
    @Test
    public void complete_task() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
                .taskCandidateOrAssigned("dy").singleResult();
        if (task != null) {
            taskService.complete(task.getId());
            System.out.println("任务完成");
        }
    }
}

事件网关

事件网关允许根据事件判断流向。网关的每个外出顺序流都要连接到一个中间事件。当流程达到一个基于事件网关,网关会进入等待状态,暂停执行。同时会为每个外出顺序流创建相对的事件订阅。
事件网关的外出顺序流和普通顺序流不同,这些顺序流不会真的执行,相反他们流程引擎去决定指定到事件网关的流程需要订阅那些事件。需要考虑以下条件:

  1. 事件网关必须有两条或以上外出顺序流
  2. 事件网关后,只能使用intermediateCatchEvent类型
  3. 连接到事件网关的中间捕获事件必须只有一个入口顺序流。

参考:Flowable BPMN 用户手册——事件篇

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

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

相关文章

Python数据可视化之图表组成元素

1.1绘制 matplotlib 图表组成元素的主要函数matplotlib 是如何组织内容的&#xff1f;在一个图形输出窗口中&#xff0c;底层是一个 Figure实例&#xff0c;我们通常称之为画布&#xff0c;包含一些可见和不可见的元素。在画布上&#xff0c;自然是图形&#xff0c;这些图形就是…

Allegro如何自动居中走线操作指导

Allegro如何自动居中走线操作指导 Allegro支持自动将走线居中到两个孔的中间,避免手动去调整的麻烦,类似下图 具体操作如下 点击Spread Between VoidsOptions选择需要居中走线的层面,并且Void clearance输入0

OpenGL ES着色器语言(GLSL ES)规范 ——上篇

文章目录前言OpenGL ES基础一段基本的着色器代码大小写和分号数据值类型、命名规范、类型转换运算符矢量和矩阵矢量和矩阵类型矢量构造、访问矩阵构造、访问矢量矩阵运算规则特殊类型—结构体和数组结构体数组取样器总结前言 着色器语言通过控制GPU来进行前端图形的渲染&#…

《深入浅出计算机组成原理》学习笔记 Day10

浮点数与定点数1. 浮点数的不精确性2. 定点数的表示3. 浮点数的表示参考1. 浮点数的不精确性 32 比特只能表示 2 的 32 次方个不同的数&#xff0c;差不多是 40 亿个。如果表示的数超过能表示总的个数&#xff0c;那么就会有两个不同的数的二进制表示是一样的。计算机就会不知…

【深度学习炼丹】不平衡样本的处理

目录&#xff1a;不平衡样本的处理一、前言二、数据层面处理方法2.1 数据扩充2.2 数据&#xff08;重&#xff09;采样2.3 类别平衡采样三、算法&#xff08;损失函数&#xff09;层面处理方法3.1 Focal Loss3.2 损失函数加权四、参考资料一、前言 在机器学习的经典假设中往往…

VMWare 移动Linux CentOS 7虚拟机后连不上网怎么办

研究hadoop的时候发现虚拟机太大了&#xff0c;于是把3台节点的虚拟机剪切粘贴到移动硬盘上&#xff0c;但是出现了上不了网的问题 VMWare 移动Linux CentOS 7虚拟机后连不上网&#xff0c;ifconfig命令只出现lo不出现有IP地址的ens33&#xff0c;jps命令也出现了jps command …

机器学习模型搭建与评估

模型搭建和评估第三章 模型搭建和评估--建模模型搭建任务一&#xff1a;切割训练集和测试集任务二&#xff1a;模型创建任务三&#xff1a;输出模型预测结果第三章 模型搭建和评估-评估模型评估任务一&#xff1a;交叉验证任务二&#xff1a;混淆矩阵任务三&#xff1a;ROC曲线…

python爬虫学习笔记-mysql数据库介绍下载安装

数据库概述 为什么要使用数据库&#xff1f; 那我们在没有学习数据库的时候&#xff0c;数据存放在json或者磁盘文件中不也挺好的嘛&#xff0c;为啥还要学习数据库&#xff1f; 文件中存储数据&#xff0c;无法基于文件直接对数据进行操作或者运算&#xff0c;必须借助python将…

IDEA搭建Finchley.SR2版本的SpringCloud父子基础项目-------Ribbon负载均衡

1.概念 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法&#xff0c;将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配…

Python闭包与闭包陷阱

1 什么是闭包 在 Python 中&#xff0c;闭包是一种特殊的函数&#xff0c;它能够记住它所在的环境&#xff08;也称作上下文&#xff09;。这意味着闭包能够访问定义它的作用域中的变量。闭包通常用于封装数据和提供对外部访问的接口。 在 Python 中使用闭包有以下几点好处&a…

数据库和SQL概述

数据库和SQL概述 数据库的好处 实现数据的持久化使用完整的管理系统统一管理&#xff0c;易于查询 常用的一些名称缩写 DB&#xff1a;数据库(Database)&#xff1a;存储数据的“仓库”。它保存了一系列有组织的数据DBMS&#xff1a;数据库管理系统(Database Management Sy…

离线用户召回定时更新

3.6 离线用户召回定时更新 学习目标 目标 知道离线内容召回的概念知道如何进行内容召回计算存储规则应用 应用spark完成离线用户基于内容的协同过滤推荐 3.6.1 定时更新代码 完整代码 import os import sys # 如果当前代码文件运行测试需要加入修改路径&#xff0c;否则后面…

游戏启动器:LaunchBox Premium with Big Box v13.1

LaunchBox知道您会喜欢的功能&#xff0c;具有风格的游戏启动器&#xff0c;我们最初将 Launchbox 构建为 DOSBox 的一个有吸引力的前端&#xff0c;但它现在拥有对现代游戏和复古游戏模拟的支持。我们让您的所有游戏看起来都很漂亮。 整理您的游戏收藏 我们不仅漂亮&#xff…

基于微信小程序奶茶店在线点餐下单系统

奶茶在线下单系统用户端是基于微信小程序端&#xff0c;管理员端是基于web端&#xff0c;基于java编程语言&#xff0c;mysql数据库&#xff0c;idea工具开发&#xff0c;用户微信端可以注册登陆小程序&#xff0c;查看奶茶详情&#xff0c;搜索下单奶茶&#xff0c;在线奶茶评…

CSS @property(CSS 自定义属性)

CSS property&#xff08;CSS 自定义属性&#xff09;参考描述propertyHoudiniproperty兼容性描述符规则syntax扩展initial-valueinherits示例描述符的注意事项使用 JavaScript 来创建自定义属性CSS 变量与自定义属性重复赋值过渡简单的背景过渡动画更复杂的背景过渡动画错误示…

【ARM体系结构】之数据类型约定与工作模式

1、RISC和CISC的区别 1.1 RISC : 精简指令集 使用精简指令集的架构&#xff1a;ARM架构 RISC-V架构 PowerPC架构 MIPS架构ARM架构 &#xff1a;目前使用最广泛的架构&#xff0c;ARM面向的低端消费类市场RISC-V架构 &#xff1a;第五代&#xff0c;精简指令集的架构&#xff…

这样定义通用人工智能

🍿*★,*:.☆欢迎您/$:*.★* 🍿 正文 人类解决问题的途径,大体可以分为两种。一种是事实推理,另一种是事实验证。 为什么只是两种分类,因为根据和环境的交互与否。 事实推理解释为当遇到事件发生的时候,思考的过程。可以使用概率模型,或者更复杂的模型(目前没…

Out of Vocabulary处理方法

Out of Vocabulary 我们在NLP任务中一般都会有一个词表&#xff0c;这个词表一般可以使用一些大牛论文中的词表或者一些大公司的词表&#xff0c;或者是从自己的数据集中提取的词。但是无论当后续的训练还是预测&#xff0c;总有可能会出现并不包含在词表中的词&#xff0c;这…

(教程)如何在BERT模型中添加自己的词汇(pytorch版)

来源&#xff1a;投稿 作者&#xff1a;皮皮雷 编辑&#xff1a;学姐 参考文章&#xff1a; NLP | How to add a domain-specific vocabulary (new tokens) to a subword tokenizer already trained like BERT WordPiece | by Pierre Guillou | Medium https://medium.com/pi…

ROS2机器人编程简述humble-第三章-BUMP AND GO IN C++ .3

简述本章项目&#xff0c;参考如下&#xff1a;ROS2机器人编程简述humble-第三章-PERCEPTION AND ACTUATION MODELS .1流程图绘制&#xff0c;参考如下&#xff1a;ROS2机器人编程简述humble-第三章-COMPUTATION GRAPH .2然后&#xff0c;在3.3和3.4分别用C和Python编程实现&am…