工作流 Flowable

news2024/11/16 0:01:02

工作流包括业务流和审批流等业务流程。

在一个流程系统中,任务间往往存在复杂的依赖关系,为保证pipeline的正确执行,就是要解决各任务间依赖的问题,这样DAG结合拓扑排序是解决存在依赖关系的一类问题的利器。DAG ( Directed Acyclic Graph),有向无环图,是指任意一条边有方向,且不存在环路的图。如果把依赖关系的问题建模成 DAG, 依赖关系成为 Graph 中的 Directed Edge, 然后通过拓扑排序,不断遍历和剔除无依赖的节点(无前置节点的节点),可以达到快速解决依赖的目的。

Flowable 工作流使用

Flowable 项目中包括 BPMN(Business Process Model and Notation)引擎、CMMN(Case Management Model and Notation)引擎、DMN(Decision Model and Notation)引擎、表单引擎(Form Engine)等模块。也有许多Flowable 应用(Flowable Modeler、Flowable Admin、Flowable IDM 与 Flowable Task),并提供了直接可用的 UI 示例。

官方文档:https://tkjohn.github.io/flowable-userguide/#_introduction

0.首先需要初始化ProcessEngine流程引擎实例。这是一个线程安全的对象,因此通常只需要在一个应用中初始化一次。 ProcessEngine由ProcessEngineConfiguration实例创建。该实例可以配置与调整流程引擎的设置。

通常使用一个配置XML文件创建ProcessEngineConfiguration,如果是springboot项目直接在yml中配置数据源即可,启动时会自动实例化到ioc容器中,无需flowable.cfg.xml文件。 ProcessEngineConfiguration所需的最小配置,是数据库JDBC连接.

比如通过xml文件创建:可以在 resources 目录下创建一个 flowable.cfg.xml 文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/flow1?allowMultiQueries=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;serverTimezone=UTC&amp;nullCatalogMeansCurrent=true" /><property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="123456" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="asyncExecutorActivate" value="false" />
    </bean>
</beans>

然后就可以直接获取流程引擎对象了: ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

Springboot集成

1.pom.xml添加依赖

  <!-- SpringBoot整合flowable -->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter</artifactId>
            <version>6.6.0</version>
        </dependency>

2.application.yml 配置数据源

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/flowable-boot?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
flowable:
  async-executor-activate: false # 关闭定时任务
  # 将databaseSchemaUpdate 设置为 true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本
  database-schema-update: true

3.配置好后直接启动,服务就会自动初始化数据库,增加需要的表。所有的Flowable服务都暴露为Spring bean

@Resource
private ProcessEngine processEngine; // // 直接注入ProcessEngine 对象
// 以下四个模块的服务接口可以直接注入使用,也可以通过ProcessEngine获取
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;

另外resources/processes目录下的任何BPMN 2.0流程定义都会被自动部署。

resources/cases目录下的任何CMMN 1.1事例都会被自动部署。

resources/forms目录下的任何Form定义都会被自动部署。

4.创建bpmn20.xml文件

在resources下创建processes目录,并在其中创建示例流程定义(命名为holiday-request.bpmn20.xml) .bpmn20.xml是文件后缀名

 开始事件:图中用细线圆圈来表示,是流程实例的开始点

 箭头:表示节点之间的流转指向。

 用户任务: 在图中用左上角有人的圆角矩形表示,这些是需要用户来操作的节点。图中有两个,第一个表示需要经理进行审批来同意或拒绝,第二个表示用户来确认销假。

 排它网关: 用叉形符号填充的菱形表示,从该图中出来的箭头往往有多个,但只有一个满足条件,流程会沿着满足条件的方向流转。

 自动化任务 :左上角有齿轮形状的的圆角矩形,表示自动执行的节点。图中上面的表示请假被经理同意后自动注册通知到外部系统,下面的表示请假被经理拒绝后自动发邮件通知给申请人。

 结束事件: 图中用粗线圆圈表示,表示流程的结束。图中上面的结束事件表示请假成功结束,下面的表示请假失败结束。

一般来说,这样的流程定义使用可视化建模工具建立,如Flowable Designer(Eclipse)或 flowable-ui-modeler(flowable-ui Web应用),保存后可得到bpmn20.xml格式文件

FlowableUI 流程设计器

Flowable 提供了几个 web 应用,用于演示及介绍 Flowable 项目提供的功能:

Flowable IDM: 身份管理应用。为所有 Flowable UI 应用提供单点登录认证功能,并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能。

Flowable Modeler: 让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。

Flowable Task: 运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务,以及查询流程实例与任务的功能。

Flowable Admin: 管理应用。让具有管理员权限的用户可以查询 BPMN、DMN、Form 及 Content 引擎,并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过 REST API 连接至引擎,并与 Flowable Task 应用及 Flowable REST 应用一同部署。

所有其他的应用都需要 Flowable IDM 提供认证。每个应用的 WAR 文件可以部署在相同的 servlet 容器(如Apache Tomcat)中,也可以部署在不同的容器中。由于每个应用使用相同的 cookie 进行认证,因此应用需要运行在相同的域名下。

可以使用docker快速部署。

Flowable UI默认的登录用户名是 admin,默认的登录密码是 test。

resources/processes/holiday-request.bpmn20.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: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"
             xmlns:flowable="http://flowable.org/bpmn"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">

    <process id="holidayRequest" name="Holiday Request" isExecutable="true">

        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <userTask id="approveTask" name="Approve or reject request"/>
        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

        <exclusiveGateway id="decision"/>
        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${!approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>

        <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                     flowable:class="org.flowable.CallExternalSystemDelegate"/>
        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

        <userTask id="holidayApprovedTask" name="Holiday approved"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <serviceTask id="sendRejectionMail" name="Send out rejection email"
                     flowable:class="org.flowable.SendRejectionMail"/>
        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

        <endEvent id="approveEnd"/>

        <endEvent id="rejectEnd"/>
    </process>
</definitions>

(1)每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。

 (2)活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。

 (3)离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) 。当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。

 这里用作条件的表达式为${approved},这是${approved == true}的简写。变量’approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。

(4).在这个例子里,我们需要在特定的地方(当用户任务提交时,或者以Flowable的术语来说,完成(complete)时)设置这个流程变量,因为这不是流程实例启动时就能获取的数据。

相关api操作

在Flowable中,数据库事务扮演了关键角色,用于保证数据一致性,并解决并发问题。当调用Flowable API时,默认情况下,所有操作都是同步的,并处于同一个事务下。

常用的几个JAVA class类介绍:

l ProcessDefinition

 这个最好理解,就是流程的定义,也就相当于规范,每个 ProcessDefinition 都会有一个 id。

 l ProcessInstance

 这个就是流程的一个实例。简单来说,ProcessDefinition 相当于是类,而 ProcessInstance 则相当于是根据类 new 出来的对象。

 l Activity

 Activity 是流程标准规范 BPMN2.0 里面的规范,流程中的每一个步骤都是一个 Activity。

 l Execution

 Execution 的含义是流程的执行线路,通过 Execution 可以获得当前 ProcessInstance 当前执行到哪个 Activity了

 l Task

 Task 就是当前要做的工作。

5.部署流程定义(ProcessDefinition)

这里因为是放到了resources/processes目录下,所以启动项目时就自动部署了,无需在手动加载.bpmn20.xml并部署了。

将流程定义部署至Flowable引擎, 并可以通过API查询验证流程定义是否已经部署在引擎中:

@Resource
private ProcessEngine processEngine; 
  // 获取 RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // deploy()完成流程的实际部署操作,会创建一个ProcessDefinition流程定义
    Deployment deploy = repositoryService.createDeployment()
            .addClasspathResource("xxxx.bpmn20.xml")
            .name("请假流程")
            .deploy();

//删除部署的流程
 repositoryService.deleteDeployment("45001", true); // true 会将流程下的任务也一并删除



//查询流程定义是否已部署到引擎中
 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .deploymentId("35001")
            .singleResult();
// processDefinition.getDeploymentId()、getName()、getDescription()、getId()

6.启动流程实例[ProcessInstance]

启动流程实例,需要提供一些初始化流程变量。一般来说,可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API,来获取这些变量。这个流程实例使用key启动。这个key就是BPMN 2.0 XML文件中设置的id属性 

在流程实例启动后,会创建一个执行(Execution),并将其放在启动事件上。从这里开始,这个执行沿着顺序流移动到审批的用户任务,并执行用户任务行为。用户任务是一个等待状态(wait state),引擎会停止执行,返回API调用处。通过taskService.complete()来完成用户任务的执行。

  // 获取启动流程的服务
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 构建流程变量
    Map<String, Object> variables = new HashMap<>();
    variables.put("employee", "wsy");
    variables.put("nrOfHolidays", 10);
    variables.put("description", "生病了,去医院");
    // 启动流程,getActivityId() 可以查看现在在流程的哪一个步骤(Activity)中
ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables); //"holidayRequest"是.bpmn20.xml中 <process>的id
//holidayRequest.getProcessDefinitionId()、 getActivityId()、 getId()

7.执行任务Task

//查看流程任务Task:
    TaskService taskService = processEngine.getTaskService();
    Task task = taskService.createTaskQuery()
            .processDefinitionId("holidayRequest:1:45003") // 流程ID
            //.processDefinitionKey("holidayRequest") // 流程key
            .taskAssignee("王经理") // 任务处理人
            //.list();列出所有任务
.singleResult();
//task.getId() 、task.getAssignee()、getName()、getProcessDefinitionId()


//执行任务
 Map<String, Object> map = new HashMap<>();
    map.put("approved", true);
    // 完成任务
    taskService.complete(task.getId(), map);

8.查看历史信息

  HistoryService historyService = processEngine.getHistoryService();
    List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
            .processDefinitionId("holidayRequest:1:45003")
            .finished() // 查询的历史记录的状态是已经完成
            .orderByHistoricActivityInstanceEndTime().asc() // 指定按结束时间排序
            .list();
    for(HistoricActivityInstance history : list) {
        System.out.println(history.getActivityName()+":"+history.getAssignee()+"--"+history.getActivityId()+":"+history.getDurationInMillis()+"毫秒");
    }

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

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

相关文章

m4a怎么转mp3?m4a转mp3的几种方法教程

m4a怎么转mp3&#xff1f;M4A音频格式的全称MPEG-4 Audio&#xff0c;是一种音频压缩格式。这种格式以其卓越的音质和相对较小的文件大小而广受欢迎&#xff0c;尤其是在音乐存储、在线流媒体以及音频编辑等领域。M4A格式被广泛应用于苹果公司的产品中&#xff0c;如iPhone、iP…

深度解析离岗识别检测算法在企业管理中的价值

在现代化企业管理中&#xff0c;员工离岗问题是影响工作效率和团队协作的重要因素。传统的员工管理方式主要依靠人工监督和考勤系统&#xff0c;然而&#xff0c;这些方法存在明显的不足&#xff0c;例如耗费人力、难以实时监控等。随着人工智能和视觉分析技术的发展&#xff0…

MySQL练手 --- 1934. 确认率

题目链接&#xff1a;1934. 确认率 思路 由题可知&#xff0c;两个表&#xff0c;一个表为Signups注册表&#xff0c;另一个表为Confirmations信息确认表&#xff0c;表的关联关系为 一对一&#xff0c;且user_id作为两个表的连接条件&#xff08;匹配字段&#xff09;&#…

Arthas在线诊断案例实战整理

会一直持续更新。。。 Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时…

Wonder3D 论文学习

论文链接&#xff1a;https://arxiv.org/abs/2310.15008 代码链接&#xff1a;https://github.com/xxlong0/Wonder3D 解决了什么问题&#xff1f; 随着扩散模型的提出&#xff0c;3D 生成领域取得了长足进步。从单张图片重建出 3D 几何是计算机图形学和 3D 视觉的基础任务&am…

【MATLAB APP】建立独立桌面APP

背景&#xff1a;已有MATLAB APP的.mlapp文件&#xff0c;但客户提出需要可以直接使用的exe文件。 要求&#xff1a;点开即用&#xff0c;无需下载MATLAB。使用者无法修改APP的代码。 一、环境配置 APP创建者&#xff1a;安装MATLAB R2023a&#xff0c;配置Application Compile…

【C++笔试强训】day05

游游的you 思路 贪心&#xff1a;优先组成 you&#xff0c;最少的字母决定了you的数量。需要注意&#xff1a;如果oo剩下n个&#xff0c;那么相邻oo的个数是n-1个&#xff0c;而不是n/2个。 例如 oooooo oo oo oooo oo 6个o&#xff0c;两两组合有3对&#xff0c;掐头去尾有…

为什么样本方差(sample variance)的分母是 n-1?

样本均值与样本方差的定义 首先来看一下均值&#xff0c;方差&#xff0c;样本均值与样本方差的定义 总体均值的定义&#xff1a; μ 1 n ∑ i 1 n X i \mu\frac{1}{n}\sum_{i1}^{n} X_i μn1​i1∑n​Xi​ 也就是将总体中所有的样本值加总除以个数&#xff0c;也可以叫做总…

让你的程序有记忆功能。

目录 环境 代码 环境 大语言模型&#xff1a; gpt-40-mini Mem0: Empower your AI applications with long-term memory and personalization OpenAPI-Key: Mem0-Key&#xff1a; 代码 import osfrom dotenv import load_dotenv from openai import OpenAI from m…

UE5.4内容示例(1)- 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例&#xff0c;可以用此示例熟悉一遍UE5的功能 模型与材质部分 StaticMeshes FBX_Import_Options Material_Advanced Material_Decals Material_Instances Material_N…

免费好用!还在用Stable Diffusion生艺术字?阿里AI艺术字生成工具,推荐试试!(附详细教程)

大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 曾经那个口口声声对X小鹿说&#xff0c;「自己不太适合写文章…

【VUE】个人记录:父子页面数据传递

1. 父传子 在父页面中&#xff0c;调用子页面的组件位置处&#xff0c;通过“&#xff1a;”进行参数传递 <child-component :childData"parentData"></child-component>parentData对象&#xff0c;需要在父页面的data中进行初始化声明 在子页面中&am…

深入探索PHP框架:Symfony框架全面解析

1. 引言 在现代Web开发领域&#xff0c;PHP作为一种广泛使用的服务器端脚本语言&#xff0c;其框架的选择对于项目的成功至关重要。PHP框架不仅能够提高开发效率&#xff0c;还能确保代码的质量和可维护性。本文将深入探讨Symfony框架&#xff0c;这是一个功能强大且灵活的PHP…

Java 序列流:Java 对象的序列化和反序列化详解

1.概念 序列化是指将一个对象转换为一个字节序列&#xff08;包含对象的数据、对象的类型和对象中存储的属性等信息&#xff09;&#xff0c;它可以将多个InputStream对象串联起来&#xff0c;使得它们可以被当作一个单一的输入流来处理&#xff0c;以便在网络上传输或保存到文…

【反证法】932. 漂亮数组

本文涉及知识点 分治 数学 反证法 LeetCode932. 漂亮数组 如果长度为 n 的数组 nums 满足下述条件&#xff0c;则认为该数组是一个 漂亮数组 &#xff1a; nums 是由范围 [1, n] 的整数组成的一个排列。 对于每个 0 < i < j < n &#xff0c;均不存在下标 k&#x…

ChatGPT的原理和成本

ChatGPT就是人机交互的一个底层系统&#xff0c;某种程度上可以类比于操作系统。在这个操作系统上&#xff0c;人与AI之间的交互用的是人的语言&#xff0c;不再是冷冰冰的机器语言&#xff0c;或者高级机器语言&#xff0c;当然&#xff0c;在未来的十来年内&#xff0c;机器语…

CSRF(Cross-site request forgery)

一、概述 1、CSRF定义 CSRF是一个web安全漏洞&#xff0c;该漏洞通过引诱用户来执行非预期的操作。该漏洞使得攻击者能够绕过同源策略&#xff0c;同源策略是一种用来阻止不同网站相互干扰的一种技术。 CSR跨站请求伪造&#xff0c;攻击者利用服务器对用户的信任&#xff0c…

MySQL练手 --- 1174. 即时食物配送 II

题目链接&#xff1a;1174. 即时食物配送 II 思路&#xff1a; 题目要求&#xff1a;即时订单在所有用户的首次订单中的比例。保留两位小数 其实也就是 即时订单 / 首次订单 所以&#xff0c;先求出首次订单&#xff0c;在首次订单的基础上寻找即时订单即可 解题过程&#x…

Mysql explain 优化解析

explain 解释 select_type 效率对比 MySQL 中 EXPLAIN 语句的 select_type 列描述了查询的类型,不同的 select_type 类型在效率上会有所差异。下面我们来比较一下各种 select_type 的效率: SIMPLE: 这是最简单的查询类型,表示查询不包含子查询或 UNION 操作。 这种查询通常是…

SpringCloud注册中心

SpringCloud注册中心 文章目录 SpringCloud注册中心1、注册中心原理2、Nacos注册中心2.1、部署nacos 3、服务注册4、服务发现 1、注册中心原理 在大型微服务项目中&#xff0c;服务提供者的数量会非常多&#xff0c;为了管理这些服务就引入了注册中心的概念。注册中心、服务提…