工作流程flowable

news2024/11/21 0:14:32

目录

  • Flowable
    • 工作流分类:
      • 一、会签流程
      • 二、或签流程
      • 分支流程
      • 四、并行流程
    • 第二步:源码及表结构对应关系
        • 部署一次流程
    • 第三步 流程监听器与任务监听器

Flowable

工作流分类:

参考: link

官方中文文档:网关

一、会签流程

  1. 适用场景

会签是一种联合审批的特殊审批节点,可理解为一种多人投票机制,一个任务需要多个人同时处理,然后汇总多个人的意见,决定流程下一步该如何执行。流程设计时,若会签审批节点中设置多个参与人,流程运行时,会签节点任务需要多人共同处理,然后汇总多人的处理意见,决定会签节点的处理结果。

例如:员工发起采购申请,需经过多名领导共同审批后,才决定是否可以采购,只要其中1名领导不同意,便退回申请人。

  1. 具体规则

会签分并行会签和顺序会签两种:

(1)并行会签

指同一个审批节点同时设置多个人,如ABC三人,三人会同时收到待办,需全部同意之后,审批才可到下一审批节点。

(2)顺序会签

指同一个审批设置多个人,如ABC三人,三人按顺序人依次收到待办,即A先审批,A提交后B才能审批,需全部同意之后,审批才可下一审批节点。

  1. 设置方法
    在这里插入图片描述

二、或签流程

  1. 适用场景

一个流程审批节点里有多个处理人,任意一个人处理后就能进入下一个节点。

例如:员工发起采购申请,提交给多名领导审批,只要有一名领导同意即可提交到下一节点。

  1. 具体规则

指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批待办,只要其中任意一人审批即可到下一审批节点。

  1. 设置方法
    在这里插入图片描述

分支流程

  1. 适用场景

分支流程的适用场景:流程中某个节点后有多个分支节点,根据不同条件执行不同的分支,即不同的数据会走不同的流程路径。

例如:请假申请,可根据请假天数走不同的审批路径,3天以内请假由人力资源审批,超过3天的请假由公司领导审批。

  1. 具体规则

(1)分支流程使用【排他网关】,连接在【排他网关】后面的线条,有分流作用,点击线条可设置流转条件。

(2)上一节点点击【提交】后,根据【排他网关】设置按顺序判断所有分支流转条件,出现满足流转条件时,就进入相应的分支节点。

(3)如果不设置,表示无条件限制,会直接进入该节点;如果设置了流转条件,则只有满足条件才会进入该节点;如果所有条件都不满足,则会流转到设置的默认访问;如果有多个条件满足,则会按设置的条件顺序判断,直到出现第一个满足的条件,就进入该节点。

  1. 设置方法
  2. 在这里插入图片描述

四、并行流程

  1. 适用场景

并行流程适用场景:流程中某个节点后有多个节点需要并行执行,节点的处理人需同时收到流程待办,各自处理待办,当所有分支线上的节点都执行后,流程才进入到下一个节点。

例如:员工提交请假申请,同时送部门经理和人力资源部审批,需要部门经理和人力资源全部审批通过后,才算流程审批通过。

  1. 具体规则

连接在【并行网关】后面的线条,才有并流作用;

上一节点点击【提交】后,无论线条是否设置条件,都自动进入所有的分支节点。当所有分支都执行后,才进入这些分支同时连接的下一个节点;

  1. 设置方法

在这里插入图片描述

第二步:源码及表结构对应关系

官方中文文档很详细

https://tkjohn.github.io/flowable-userguide/
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

部署一次流程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

第三步 流程监听器与任务监听器

首先创建流程监听器和任务监听器的实体类,个人比较喜欢使用Delegate Expression方式,其他两种方式也可以

流程监听器


package org.mpc.final_activiti;
 
import java.io.Serializable;
 
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.Expression;
 
/**
 * 
 * 可以使用 CLASS ,EXPRESSION,DELEGATE EXPRESSSION三种方式来创建监听器,这里使用第三种方式,其他两种方式和
 * 在servicetask中的使用方式相同
 * 
 * */
public class ExectuionListenerDemo implements Serializable, ExecutionListener {
 
	/**
	 * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么)
	 */
	private static final long serialVersionUID = 8513750196548027535L;
	private Expression message;
 
	public Expression getMessage() {
		return message;
	}
 
	public void setMessage(Expression message) {
		this.message = message;
	}
 
	@Override
	public void notify(DelegateExecution execution) throws Exception {
		System.out.println("流程监听器" + message.getValue(execution));
	}
 
}

任务监听器

package org.mpc.final_activiti;
 
import java.io.Serializable;
 
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.TaskListener;
 
/**
 * 
 * 任务监听器,实现TaskListener接口
 * 
 * */
public class TaskListenerDemo implements Serializable, TaskListener {
	private Expression arg;
 
	public Expression getArg() {
		return arg;
	}
 
	public void setArg(Expression arg) {
		this.arg = arg;
	}
 
	@Override
	public void notify(DelegateTask delegateTask) {
		System.out.println("任务监听器:" + arg.getValue(delegateTask));
	}
 
}

这两个监听器只是简单的表明了自己的身份,并打印出在流程中注入给他们的值

接着是流程定义图

展示一下配置结果的xml文件,特别注意一下加注释的地方

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="myProcess" name="My process" isExecutable="true">
    <extensionElements>
      <activiti:executionListener event="start" delegateExpression="${myprocessListener}">
        <activiti:field name="message">
          <activiti:string><![CDATA[流程启动]]></activiti:string>
        </activiti:field>
      </activiti:executionListener>
      <activiti:executionListener event="end" delegateExpression="${myprocessListener}">
        <activiti:field name="message">
          <activiti:string><![CDATA[流程结束]]></activiti:string>
        </activiti:field>
      </activiti:executionListener>
    </extensionElements>
    <startEvent id="startevent1" name="Start"></startEvent>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway">
      <extensionElements>
        <activiti:executionListener event="start" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[排他网关开始]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
        <activiti:executionListener event="end" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[排他网关结束]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
      </extensionElements>
    </exclusiveGateway>
    <sequenceFlow id="flow3" sourceRef="startevent1" targetRef="exclusivegateway1"></sequenceFlow>
    <userTask id="usertask2" name="User Task" activiti:assignee="${user}">
      <extensionElements>
        <activiti:taskListener event="create" delegateExpression="${mytaskListener}">
          <activiti:field name="arg">
            <activiti:string><![CDATA[任务启动]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
        <activiti:taskListener event="assignment" delegateExpression="${mytaskListener}">
          <activiti:field name="arg">
            <activiti:string><![CDATA[分配人员]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
        <activiti:taskListener event="complete" delegateExpression="${mytaskListener}">
          <activiti:field name="arg">
            <activiti:string><![CDATA[任务完成]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
        <!-- 在可视化工具中无法给usertask加上流程监听器,但是,我们在xml中可以自己敲进去· -->
              <activiti:executionListener event="start" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[流程启动任务]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
        <activiti:executionListener event="end" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[流程关闭任务]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
        <!-- ........................................................................................................................................ -->
      </extensionElements>
    </userTask>
    <sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="usertask2">
      <extensionElements>
        <activiti:executionListener event="take" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[从排他网关到用户任务,好长的一段路]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
      </extensionElements>
    </sequenceFlow>
    <intermediateThrowEvent id="noneintermediatethrowevent1" name="NoneThrowEvent">
      <extensionElements>
        <activiti:executionListener event="start" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[中间事件开始]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
        <activiti:executionListener event="end" delegateExpression="${myprocessListener}">
          <activiti:field name="message">
            <activiti:string><![CDATA[中间事件结束]]></activiti:string>
          </activiti:field>
        </activiti:executionListener>
      </extensionElements>
    </intermediateThrowEvent>
    <sequenceFlow id="flow5" sourceRef="usertask2" targetRef="noneintermediatethrowevent1"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow6" sourceRef="noneintermediatethrowevent1" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
    <bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="160.0" y="180.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="240.0" y="130.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="325.0" y="123.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="noneintermediatethrowevent1" id="BPMNShape_noneintermediatethrowevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="475.0" y="133.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="555.0" y="133.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="195.0" y="197.0"></omgdi:waypoint>
        <omgdi:waypoint x="260.0" y="170.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="280.0" y="150.0"></omgdi:waypoint>
        <omgdi:waypoint x="325.0" y="150.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="430.0" y="150.0"></omgdi:waypoint>
        <omgdi:waypoint x="475.0" y="150.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="510.0" y="150.0"></omgdi:waypoint>
        <omgdi:waypoint x="555.0" y="150.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述

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

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

相关文章

【C语言】循环语句详解

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 目录 1.什么是循环结构&#xff1f; 2.while循环 while流程图 while语句中的break和continue break continue 3.for循环 for流…

Ubuntu 20.04.5 怎么安装微信

这是我的ubutun版本号 在这个系统装桌面版微信很多功能不健全。搜索了很多方法&#xff0c;这个算是不错的一个法子。 1.添加仓库 首次使用时&#xff0c;你需要运行如下一条命令将移植仓库添加到系统中。 wget -O- https://deepin-wine.i-m.dev/setup.sh | sh 2.应用安装 …

无代码:软件开发从代码语言到业务语言的拐点

在互联网巨头和中小企业纷纷追求移动互联和“上云”的今天&#xff0c;业务在线已成为众多企业数字化转型的必经之路。然而&#xff0c;传统的软件重装开发模式已经无法满足企业快速变化的需求&#xff0c;同时IT专业人才的成本也在不断攀升&#xff0c;使得企业的IT交付能力面…

ACL 访问控制 过滤数据 维护网络安全(第七课)

一 ACL 简介 ACL是Access Control List&#xff08;访问控制列表&#xff09;的缩写&#xff0c;是一种用于控制文件、目录、网络设备等资源访问权限的方法。ACL可以对每个用户或用户组设置不同的访问权&#xff0c;即在访问控制清单中为每个用户或用户组指定允许或禁止访问该…

十年网络安全工程师整理:渗透测试工具使用方法介绍

渗透测试&#xff0c;是为了证明网络防御按照预期计划正常运行而提供的一种机制。 渗透人员在不同的位置&#xff08;比如从内网、从外网等位置&#xff09;利用各种手段对某个特定网络进行测试&#xff0c;以期发现和挖掘系统中存在的漏洞&#xff0c;然后输出渗透测试报告&a…

RT-Thread 内核对象模型

静态对象和动态对象 RTT内核采用面向对象的设计思想进行设计&#xff0c;系统级的基础设施都是一种内核对象&#xff0c;例如线程&#xff0c;信号量&#xff0c;互斥量&#xff0c;定时器等。 内核对象分为两类&#xff1a;静态内核对象和动态内核对象&#xff0c;静态内核对…

Walmart电商促销活动即将开始,如何做促销活动?需要注意什么?

近日&#xff0c;沃尔玛官宣Baby Days优惠活动将于9月1日正式开始&#xff01;卖家可以把握机会&#xff0c;通过设置促销定价&#xff0c;以最优惠的婴儿相关产品价格吸引消费者&#xff0c;包括汽车座椅、婴儿车、尿布袋、家具、床上用品、消耗品、婴儿服装、孕妇装等。注意本…

一文了解评估 K8s 原生存储产品需要关注的关键能力

近些年&#xff0c;越来越多的企业使用 Kubernetes&#xff08;K8s&#xff09;支持生产环境关键业务。这些业务往往对存储性能和稳定性具有更高的要求&#xff0c;传统存储方案难以充分满足&#xff0c;因此不少用户开始关注更契合 K8s 环境的 K8s 原生存储方案。 不过&#…

VSAN硬盘出现resetremoved

原创作者&#xff1a;运维工程师 谢晋 VSAN硬盘出现reset&removed 客户环境有8台服务器dell R740和R740XD服务器组成了一套VSAN集群&#xff0c;但R740那四台的物理机老是出现硬盘故障需进行硬盘更换&#xff0c;后发现刚换完的硬盘没过几天又坏了&#xff0c;先开始怀疑…

shell超基础入门(超详细)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

财报解读:“百亿生态”成效初显,拼多多跨越S型曲线?

电商江湖再起变化&#xff0c;掀起浪潮者仍然是拼多多。 在这充满挑战与机遇的商业环境中&#xff0c;企业的发展轨迹正如S型曲线般&#xff0c;充满起伏和曲折&#xff0c;而拼多多的最新财报数据无疑已经展现出了与S曲线理论相契合的发展轨迹。它不仅在发展中不断进行战略调…

c++:QT day2 信号和槽

1.多态&#xff1a; 静态多态&#xff1a;函数的重载 动态多态&#xff1a;程序运行 多态的实现:父类的指针或引用&#xff0c;指向或初始化子类的对象&#xff0c;调用子类对父类重写的函数&#xff0c;进而展开子类的功能 2.虚函数&#xff1a;用virtua关键字修饰的函数是虚函…

信息技术04--初/高中--教学设计知识点梳理

文章目录 第一章 信息技术基础1.1 信息概念与特征1.1.1 信息的概念1.1.2 信息的特征 1.2 信息技术概述1.2.1 信息技术概念1.2.2 信息技术五次革命 1.3 信息的获取1.3.1 信息获取的过程&#xff1a;1.3.2 搜索引擎1.3.3 引擎符号 1.4 信息的表示和编码1.4.1 进制分类1.4.2 二进制…

字符函数和字符串函数(1)

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组 中。字符串常量适用于那些对它不做修改的字符串函数。 目录 函数介绍 strlen strcpy strcat strcmp strncpy strncat strncmp s…

LINQ详解(查询表达式)

什么是LINQ&#xff1f; LINQ(语言集成查询)是将查询功能直接集成到C#中。数据查询表示简单的字符串&#xff0c;在编译时不会进行类型检查和IntelliSense(代码补全辅助工具)支持。 在开发中&#xff0c;通常需要对不同类型的数据源了解不同的查询语句&#xff0c;如SQL数据库…

⚠️ WinRAR 中的趋势漏洞 CVE-2023-38831

在漏洞区域 WinRAR 是一种流行的数据压缩程序。网络犯罪分子已经利用 CVE-2023-38831攻击交易者。 经纪账户面临风险 利用 CVE-2023-38831 漏洞&#xff0c;攻击者会创建 ZIP 压缩文件来传播各种恶意软件系列&#xff0c;如 DarkMe、GuLoader、Remcos RAT&#xff0c;并将其…

Zabbix --- Snmp Trap监控详细教程

一、zabbix服务器安装snmptrapd服务 1、安装服务 yum -y install net-snmp net-snmp-agent-libs net-snmp-devel net-snmp-libs net-snmp-perl net-snmp-utils 注&#xff1a;使用perl脚本解析trap信息并进行格式化&#xff0c;net-snmp-perl 2、zabbix启用snmptrap进程&…

react轮播图

这里 我用的是组件&#xff1a; 网址&#xff1a;Collapse 折叠面板 - Ant Design Mobile 1.首先 先声明一个变量 2、把需要的数据存存进去 3、组件内容复制过来&#xff08;这里用到的是map循环&#xff09; 然后图片就出来了 就是这个简单 哈哈哈哈&#xff01;&#xff01…

【Unity-Cinemachine相机】虚拟相机(Virtual Camera)的本质与基本属性

我们可以在游戏进行时修改各个属性&#xff0c;但在概念上&#xff0c;最好将Virtual Camera 当作一种相机行为的“配置文件”&#xff0c;而不是一个组件。 我们的相机有几种行为就为它准备几种虚拟相机&#xff0c;比如角色移动就为它第三人称相机&#xff0c;瞄准就准备一个…

Linux——守护进程

简述 不受用户登录、注销影响的进程称为守护进程 特点 后台运行&#xff1a;守护进程在后台默默地执行任务&#xff0c;不与用户交互。它不会向终端输出信息&#xff0c;也不会从终端接收输入。 无终端关联&#xff1a;守护进程通常与任何终端会话&#xff08;比如SSH会话&…