Activiti7工作流引擎:基础篇(四) Hello World

2023-12-18 15:10

本文主要是介绍Activiti7工作流引擎:基础篇(四) Hello World,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



知识传送门 》》》》》》》》


越是有用的东西越不值钱,你比方说粮食、水、蔬菜,能够满足我们生存的东西一点都不值钱;
而那些对我们生活不起任何作用的东西特别值钱,你比方说砖石、包包、古董、字画;
所以说你要想挣大钱你就得整那些没有用的。

一:工作流的开发步骤

  1. 定义流程:使用IDEA插件actiBPM定义流程文件.bpmn
  2. 部署流程:将.bpmn文件保存到数据库中。
  3. 启动流程:启动工作流中的第一个任务节点,即提出申请。
  4. 办理流程:审批当前任务流程,完成最后一个任务就算结束工作流。

二:示例一:负责人固定

2.1 定义流程

在这里插入图片描述

  • Id:最好不要使用默认的数字而是起个更加直观的名字,因为程序中可能要根据Id值来查询任务,如果使用数字作为查询条件会非常不直观。

  • Assignee: 表示任务负责人、办理人。
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

生成.png文件

将helloworld.bpmn文件重名为helloworld.xml文件,右键 --> Diagrams --> Show BPMN 2.0 Designer --> Export to Image File ,然后将helloworld.png放入到项目resources/bpmn/目录下, 并把xml后缀改为原来的bpmn后缀。

为什么要导出成图片呢?可以将图片放在Web系统中供其他人员了解流程审批步骤。

2.2 部署流程、启动流程、办理流程

public class HelloWorldTest {/*** 创建数据库表*/@Testpublic void testCreateDBTable() {ProcessEngines.getDefaultProcessEngine();}/*** 部署流程:将.bpmn文件保存到数据库中,.bpmn属于资源部署所以使用RepositoryService。*/@Testpublic void delopyBpmn() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();Deployment deploy = processEngine.getRepositoryService().createDeployment().addClasspathResource("bpmn/helloworld.bpmn")// 图片不是必须的,不影响审批流程.addClasspathResource("bpmn/helloworld.png").name("请假流程").deploy();// DeploymentEntity[id=1, name=请假流程]System.out.println(deploy);}/*** 启动流程实例:发起申请请求*/@Testpublic void startProcessInstance() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("helloworld");System.out.println(processInstance.getId());System.out.println(processInstance.getProcessInstanceId());System.out.println(processInstance.getProcessDefinitionId());}/*** 办理(完成)任务:zhangsan审核自己通过,并将审批交给下个流程审核*/@Testpublic void completeTask() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("helloworld").taskAssignee("zhangsan").singleResult();// 完成之前可以先添加一些历史意见JSONObject jsonObject = new JSONObject();jsonObject.put("userId", "1");jsonObject.put("suggestion", "同意");taskService.addComment(task.getId(), task.getProcessInstanceId(), "MyCustomComment", JSONObject.toJSONString(jsonObject));// 办理完成任务taskService.complete(task.getId());}/*** 办理(完成)任务:项目经理完成审批,并将任务交给下个负责人审批*/@Testpublic void completeTaskPM() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("helloworld").taskAssignee("pm").singleResult();taskService.complete(task.getId());}/*** 办理(完成)任务:人事审批通过,整个流程结束*/@Testpublic void completeTaskHR() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("helloworld").taskAssignee("hr").singleResult();taskService.complete(task.getId());}
}

Activiti打印SQL配置。

logging:level:org.activiti.engine.impl.persistence.entity: debug

请添加图片描述

三:示例二:负责人变量

负责人Assignee在实际开发过程中一般都不会写死,申请人写死难道只能这一个人能发起审批吗?所以一般负责人都是使用UEL表达式先定义一个变量,在启动实例或者其他时候给这个变量再赋值。

3.1 UEL表达式

UEL表达式类似于JSP中的ETL表达式,就是在 ${}或者#{}内可以写表达式,如引用一个变量值 $ {assignee}$ {xxx.assignee},调用方法调用${对象.方法(execution)},做一些简单的boolean条件运算,可以使用 &&|| 连接多个条件,如$ {xxx.day >= 3 || xxx.role == 'pm'}

  • 多个流程变量可以封装到一个POJO对象中,不过必须实现Serializable接口。
  • 如果使用UEL指定Assignee时,启动流程实例时必须给变量赋值,候选人列表Candidate Users需要在启动流程实例时赋值。

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

3.2 BusinessKey

业务Key:员工发起请假申请时一般都要填写请假开始时间、请假结束时间、请假理由等和具体业务相关的数据,Activiti的25张表只会保存审批流程相关的数据,不会保存具体业务的数据,具体业务的数据需要开发人员自己定义表结构,自己维护,但是Activiti提供了一个字段(外键)可以保存和业务相关的数据,这个字段叫ACT_RU_EXECUTION.BUSINESS_KEY_,通常我们会保存业务表的主键id,这样我们就可以通过BUSINESS_KEY_关联到员工的请假时间、请假原因等数据了。

3.3 流程定义ProcessDefinition和流程实例ProcessInstance

  • 流程定义是定义.bpmn文件(相当于定义一个Java实体类文件Studeng.class),对应于act_re_procdef。
  • 流程实例是根据流程定义文件发起一个具体的申请(相当于创建一个实例对象 Student zhangsan = new Student(“张三”) 对应于act_ru_execution中的is_scope_ = 1 的那条记录。
    在这里插入图片描述
/*** 启动流程实例:发起申请请求*/
@Test
public void startProcessInstance() {// 业务KeyString businessKey = "666";// 变量:注意实际情况下候选人Assignee的值一般是用户的id而不是账号或者姓名。Map<String, Object> variables = new HashMap<>();variables.put("creator", "zhangsan");variables.put("pm", "狗经理");variables.put("hr", "小姐姐");ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("helloworld", businessKey, variables);System.out.println(processInstance.getId());System.out.println(processInstance.getProcessInstanceId());System.out.println(processInstance.getProcessDefinitionId());
}

四:数据库分析

4.1 创建表结构分析

ProcessEngines.getDefaultProcessEngine() 创建表的时候就会往act_ge_property中插入4个属性。
在这里插入图片描述

4.2 部署流程分析

部署流程时会保存3张表:act_re_deployment、act_re_procdef、act_re_bytearray。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.3 启动流程

  • act_ru_execution:流程实例和执行流,每发起一次申请就会生成两条记录,zhangsan和lisi分别发起就是4条数据。
    • 插入第一条记录(流程实例),is_scope_ = 1 ,确定流程实例Id值。
    • 插入第二条记录(第一个UserTask)被称为执行流。
  • act_ru_task
  • act_ru_identitylink
  • act_ru_variable
    在这里插入图片描述
    启动流程时第一个任务就开始了。
    在这里插入图片描述
    同时第一个任务的负责人也将被记录下来。
    在这里插入图片描述
    当开始第一个任务的时候就会记录下来所有变量。
    在这里插入图片描述

4.4 zhangsan完成流程

在完成任务之前可以先记录一些值。
在这里插入图片描述

当第一个任务完后就会卸磨杀驴被删除掉,同时下一个任务即将上位。
在这里插入图片描述
开始第二个任务,同时记录第二个任务的负责人。注意:第一个任务的执行人并没有删除。
在这里插入图片描述
开始第二个任务,第一个zhangsan的执行流被删除了,pm的执行流insert进来了。
在这里插入图片描述

历史表:zhangsan的任务已经完成结束了,要记录下来,同时第二个任务也已经开始了,但还没完成,所以没有结束时间。
在这里插入图片描述
act_ru_actinst相比于act_ru_taskinst数据更全一些,为记录工作流中的所有活动(包括开始、任务、结束等)。
在这里插入图片描述
第一个负责人和第二个负责人同时也被记录在历史上。
在这里插入图片描述
第一个任务完成后就会将所有的变量记录在历史中。
在这里插入图片描述

4.5 pm完成任务

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

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

4.6 hr完成任务

任务完成,一切运行时的数据都将清空。
在这里插入图片描述
一切结束的任务也将完整的记录在历史中。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


知识传送门 》》》》》》》》


这篇关于Activiti7工作流引擎:基础篇(四) Hello World的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/508853

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

工作常用指令与快捷键

Git提交代码 git fetch  git add .  git commit -m “desc”  git pull  git push Git查看当前分支 git symbolic-ref --short -q HEAD Git创建新的分支并切换 git checkout -b XXXXXXXXXXXXXX git push origin XXXXXXXXXXXXXX

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

嵌入式方向的毕业生,找工作很迷茫

一个应届硕士生的问题: 虽然我明白想成为技术大牛需要日积月累的磨练,但我总感觉自己学习方法或者哪些方面有问题,时间一天天过去,自己也每天不停学习,但总感觉自己没有想象中那样进步,总感觉找不到一个很清晰的学习规划……眼看 9 月份就要参加秋招了,我想毕业了去大城市磨练几年,涨涨见识,拓开眼界多学点东西。但是感觉自己的实力还是很不够,内心慌得不行,总怕浪费了这人生唯一的校招机会,当然我也明白,毕业

c++基础版

c++基础版 Windows环境搭建第一个C++程序c++程序运行原理注释常亮字面常亮符号常亮 变量数据类型整型实型常量类型确定char类型字符串布尔类型 控制台输入随机数产生枚举定义数组数组便利 指针基础野指针空指针指针运算动态内存分配 结构体结构体默认值结构体数组结构体指针结构体指针数组函数无返回值函数和void类型地址传递函数传递数组 引用函数引用传参返回指针的正确写法函数返回数组

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是