Flowable进阶学习(六)网关(排他网关、并行网关、包容网关、事件网关)


网关(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. 连接到事件网关的中间捕获事件必须只有一个入口顺序流。

1. 定时事件

定时触发的相关事件,包括定时器启动事件、定时器捕获中间事件、定时器边界事件。

1.1 定时器启动事件

定时器启动事件在指定时间创建流程实例。在流程只需要启动一次,或者流程需要在特定的时间间隔重复启动时,都可以使用。
注意:
1. 子流程不能有定时器启动事件。
2. 定时器启动事件,在流程部署的同事就开始计时。不需要调用startProcessInstanceByXXX就会定时启动。而调用startProcessInstanceByXXX方法,会另外启动一个新的流程实例。
3. 当部署带有定时器启动事件的流程更新版本的时候,上衣版本的定时器作业会被移除。这是因为通常并不希望旧版本的流程仍然自动启动新的流程实例。定时器启动时间,用一个钟表图标的圆圈来表示。

案例
  1. 绘制流程
    在这里插入图片描述在配置文件中开启定时任务,默认是关闭的。
flowable:
  async-executor-activate: true

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

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
从基础讲起,结合应用场景,由浅到深细化讲解BPMN和Flowable的相关组件,并结合具体实例,演示功能的使用和注意事项。最终结合Springboot搭建一套工作流系统,囊括一般项目中所需要的知识点,理论结合实际,让真正入门到熟练。 1 简介 2 学习指南 2.1 Flowable初体验 2.1.1 Flowable是什么? 2.1.2 Flowable 和 Activiti 2.1.3 构建命令行应用程序 2.1.3.1 创建一个流程引擎 2.1.3.2 部署一个流程定义 2.1.3.3 启动一个流程实例 2.1.3.4 查询和完成一个任务 2.1.3.5 写一个JavaDelegate 2.1.3.6 查询历史数据 2.2 Flowable整合Spring 2.3 Flowable整合SpringBoot 2.4 Flowable流程定义部署 2.4.1 使用xml部署 2.4.2 使用压缩文件部署 2.4.3 使用IO流部署 3 BPMN2.0简介 3.1 什么是BPMN2.0 3.2 创建一个BPMN 3.2.1 直接编写XML文件 3.2.2 使用插件编写 3.2.2.1 在线安装插件 3.2.2.2 离线安装 3.2.2.3 插件使用说明 4 BPMN2.0组成 4.1 事件 4.1.1 事件定义 4.1.2 计时器事件定义 4.1.2.1 timeDate 4.1.2.1.1 开始事件TimerStartEvent 4.1.2.1.2 中间事件TimerCatchingEvent 4.1.2.1.3 边界事件TimerBoundaryEvent 4.1.2.2 timeDuration 4.1.2.2.1 开始事件TimerStartEvent 4.1.2.1.2 中间事件TimerCatchingEvent 4.1.2.1.3 边界事件TimerBoundaryEvent 4.1.2.3 timeCycle 4.1.2.3.1 开始事件TimerStartEvent 4.1.2.3.2 中间事件TimerCatchingEvent 4.1.2.3.3 边界事件TimerBoundaryEvent 4.1.3 消息事件 4.1.3.1 开始事件MessageStartEvent 4.1.3.2 中间事件MessagecatchingEvent 4.1.3.3 边界事件MessageBoundaryEvent 4.1.4 错误事件 4.1.4.1 开始事件ErrorStartEvent 4.1.4.2 边界事件ErrorBoundaryEvent 4.1.5 信号事件 4.1.5.1 开始事件SignalStartEvent 4.1.5.2 中间事件 4.1.5.2.1 捕捉事件SignalCatchingEvent 4.1.5.2.2 抛出事件SignalThrowingEvent 4.1.5.3 边界事件SignalBoundaryEvent dream21st 4.1.6结束事件 4.1.6.1 错误结束事件ErrorEndEvent 4.1.6.2 中断结束事件TerminateEndEvent 4.1.6.2.1 中断结束事件案例一 4.1.6.2.2 中断结束事件案例二 4.1.6.3 取消结束事件 CancelEndEvent 4.1.7 补偿事件CompensationThrowing 4.1.8 网关 4.1.8.1 并行网关ParallelGateway 4.1.8.2 网关ExclusiveGateway 4.1.8.3 包容网关InclusiveGateWay 4.1.8.4 事件网关EventGateway 4.2 任务 4.2.1 用户任务UserTask 4.2.1.1 用户任务入门案例Assignee指定 4.2.1.2 CandidateUser和CandidateGroup指定 4.2.1.3 多人会签MultiInstance 4.2.1.4 动态表单 4.2.2 服务任务ServiceTask 4.2.3 手工任务ManualTask 4.2.4 接受任务ReceiveTask 4.2.5 调用流程CallActivity 4.2.5.1 固定子流程 4.2.5.2 动态子流程 4.3 容器 5 工作流实战案例 5.1 实战案例一 5.1.1 部署流程定义 5.1.2 启动流程实例 5.1.3 查询待办任务 5.1.4 提交任务 5.1.5 查询候选任务 5.1.6 获取候选任务 5.1.7 通过流程实例ID查询任务流转图 5.2 实战案例二
并行网关Flowable工作流引擎中的一个重要组件,用于同时执行多个并发的执行流。它可以将一个执行流分岔成多个同时执行的执行流,并将多个执行流合并为一个执行流。与其他网关不同的是,并行网关不会解析流条件,即使顺序流中定义了流条件,也会被忽略。并行网关可以同时具有分岔和合并两种行为,允许多个执行流到达该网关时被合并,然后再随机分岔为多个执行流。因此,并行网关在处理多个并发执行流时非常灵活和强大。 同时,包含网关也可以充当并行网关的角色。包含网关网关并行网关的结合体,可以选择多于一条顺序流,并且在执行流中具有分岔和合并的行为。当包含网关作为并行网关使用时,它遵循并行网关的特性,既有分岔行为也有合并行为。与并行网关不同的是,包含网关还可以解析流条件,并根据条件选择不同的顺序流进行执行。因此,包含网关在流程中的使用非常灵活,既可以用作网关,也可以用作并行网关。 总结来说,Flowable中的并行网关是一个同时执行多个并发执行流的组件,可以实现分岔和合并的行为,而包含网关则是网关并行网关的结合体,既可以充当网关,也可以充当并行网关。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huathy-雨落江南,浮生若梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值