工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求
前言
大家好,我是老马。
最近想设计一款审批系统,于是了解一下关于流程引擎的知识。
下面是一些的流程引擎相关资料。
工作流引擎系列
工作流引擎-00-流程引擎概览
工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求
工作流引擎-02-BPM OA ERP 区别和联系
工作流引擎-03-聊一聊流程引擎
工作流引擎-04-流程引擎 activiti 优秀开源项目
工作流引擎-05-流程引擎 Camunda 8 协调跨人、系统和设备的复杂业务流程
工作流引擎-06-流程引擎 Flowable、Activiti 与 Camunda 全维度对比分析
工作流引擎-07-流程引擎 flowable-engine 入门介绍
工作流引擎-08-流程引擎 flowable-engine 优秀开源项目
工作流引擎-09-XState 是一个 JavaScript 和 TypeScript 的状态管理库,它使用状态机和状态图来建模逻辑
Activiti 基础介绍
主页:http://activiti.org
是什么
在解释activiti之前我们看一下什么是工作流。
workflow-工作流
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。
我的理解是,工作流将一套大的业务逻辑分解成业务逻辑段, 并统一控制这些业务逻辑段的执行条件,执行顺序以及相互通信。
实现业务逻辑的分解和解耦。
Activiti
Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求。
Activiti Cloud 现在是新一代的业务自动化平台,提供一组旨在在分布式基础架构上运行的云原生构建块。
BPMN即业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)。
快速开始
开始方式
可以基于云,也可以基于 java api 进行实现。
我们这里进行 java 的入门学习,java core api。
Activiti Core Runtime API 入门
创建新 API 的目的很明确,旨在满足以下要求:
-
为我们的云方法提供清晰的路径
-
隔离内部和外部 API 以提供向前的向后兼容性
-
通过遵循单一职责方法提供模块化的未来路径
-
减少旧版本 API 的混乱
-
将安全和身份管理作为一等公民
-
减少常见用例的价值实现时间,在这些用例中您希望依赖流行框架提供的约定
-
提供底层服务的替代实现
-
使社区能够在尊重既定合同的同时进行创新
我们尚未弃用旧 API,因此您仍然可以自由使用它,但我们强烈建议使用新 API 以获得长期支持。
此 API 处于测试阶段,这意味着我们可能会在 GA 发布之前对其进行更改和完善。我们将感谢我们从社区用户那里获得的所有反馈,如果您想参与该项目,请与我们联系。
是时候让我们接触几个示例项目了。
任务运行时 API
如果您正在构建业务应用程序,为您组织中的用户和组创建任务可能会很方便。
TaskRuntime API 可以帮助您。
你可以从 GitHub 克隆这个例子:https://github.com/Activiti/activiti-examples
本节的代码可以在 activiti-api-basic-task-example maven 模块中找到。
如果您在 Spring Boot 2 应用程序中运行,您只需要添加 activiti-spring-boot-starter 依赖项和一个 DB 驱动程序,您可以使用 H2 进行内存存储。
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/pom.xml#L45
maven 引入
<dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId>
</dependency>
我们建议使用我们的 BOM
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/pom.xml#L30
<dependencyManagement><dependencies><dependency><groupId>org.activiti.dependencies</groupId><artifactId>activiti-dependencies</artifactId><version>7.1.0.M5</version><scope>import</scope><type>pom</type></dependency></dependencies>
</dependencyManagement>
现在让我们切换到我们的 DemoApplication.class:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L25
TaskRuntime
然后你就可以使用 TaskRuntime:
@Autowired
private TaskRuntime taskRuntime;
例如,您可以通过执行以下操作来创建任务:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L45
taskRuntime.create(TaskPayloadBuilder.create().withName("First Team Task").withDescription("This is something really important").withGroup("activitiTeam").withPriority(10).build());
此任务仅对属于 activitiTeam 的用户和所有者(当前登录的用户)可见。
您可能已经注意到,您可以使用 TaskPayloadBuilder 以流畅的方式参数化将要发送到 TaskRuntime 的信息。
为了处理安全性、角色和组,我们依赖 Spring Security 模块。
因为我们在 Spring Boot 应用程序中,所以我们可以使用 UserDetailsService 来配置可用用户及其各自的组和角色。
我们目前正在 @Configuration
类中执行此操作:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplicationConfiguration.java#L26
这里需要注意的重要一点是,为了作为用户与 TaskRuntime API 交互,您需要具有角色:ACTIVITI_USER (Granted Authority: ROLE_ACTIVITI_USER) 。
在与 REST 端点交互时,授权机制将设置当前登录的用户,但为了示例,我们使用了一个实用程序类(SecurityUtil.java#L26) 允许我们在上下文中设置手动选择的用户。
请注意,除非您正在尝试并且想在不通过 REST 端点的情况下更改用户,否则您永远不应该这样做。
查看“网络”示例以查看更多根本不需要此实用程序类的真实场景。
示例中要强调的最后一件事是任务事件侦听器的注册:
DemoApplication.java#L89
@Bean
public TaskRuntimeEventListener taskAssignedListener() {return taskAssigned-> logger.info(">>> Task Assigned: '"+ taskAssigned.getEntity().getName()+"' We can send a notification to the assignee: "+ taskAssigned.getEntity().getAssignee());
}
您可以根据需要注册任意数量的 TaskRuntimeEventListener。
这将使您的应用程序能够在服务触发运行时事件时收到通知。
进程运行时 API
以类似的方式,如果您想开始使用 ProcessRuntime API,您需要包含与以前相同的依赖项。
我们的目标是在未来提供更多的灵活性和独立的运行时,但现在同一个 Spring Boot Starter 提供 TaskRuntime 和 ProcessRuntime API。
本节的代码可以在“activiti-api-basic-process-example”maven 模块中找到。
接口
public interface ProcessRuntime {ProcessRuntimeConfiguration configuration();ProcessDefinition processDefinition(String processDefinitionId);Page processDefinitions(Pageable pageable);Page processDefinitions(Pageable pageable,GetProcessDefinitionsPayload payload);ProcessInstance start(StartProcessPayload payload);Page processInstances(Pageable pageable);Page processInstances(Pageable pageable,GetProcessInstancesPayload payload);ProcessInstance processInstance(String processInstanceId);ProcessInstance suspend(SuspendProcessPayload payload);ProcessInstance resume(ResumeProcessPayload payload);ProcessInstance delete(DeleteProcessPayload payload);void signal(SignalPayload payload);...
}
与 TaskRuntime API 类似,为了与 ProcessRuntime API 交互,当前登录的用户需要具有“ACTIVITI_USER”角色。
自动装配
首先,让我们自动装配我们的 ProcessRuntime:
DemoApplication.java#L32
@Autowired
private ProcessRuntime processRuntime;@Autowired
private SecurityUtil securityUtil;
和以前一样,我们需要我们的 SecurityUtil 助手来定义我们正在与我们的 API 交互的用户。
现在我们可以开始与 ProcessRuntime 交互:
DemoApplication.java#L47
Page processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
logger.info("> Available Process definitions: " +processDefinitionPage.getTotalItems());
for (ProcessDefinition pd : processDefinitionPage.getContent()) {logger.info("\t > Process definition: " + pd);
}
流程定义需要放在 /src/main/resources/processes/ 中。
对于本示例,我们定义了以下流程:
我们正在使用 Spring 调度功能每秒启动一个进程,从数组中获取随机值以进行处理:
DemoApplication.java#L67
@Scheduled(initialDelay = 1000, fixedDelay = 1000)
public void processText() {securityUtil.logInAs("system");String content = pickRandomString();SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yy HH:mm:ss");logger.info("> Processing content: " + content+ " at " + formatter.format(new Date()));ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("categorizeProcess").withProcessInstanceName("Processing Content: " + content).withVariable("content", content).build());logger.info(">>> Created Process Instance: " + processInstance);
}
和以前一样,我们使用 ProcessPayloadBuilder 以流畅的方式参数化我们想要启动哪个流程以及使用哪些流程变量。
现在,如果我们回顾流程定义,您会发现 3 个服务任务。
为了提供这些服务任务的实现,您需要定义连接器:
DemoApplication.java#L81
@Bean
public Connector processTextConnector() {return integrationContext -> {Map inBoundVariables = integrationContext.getInBoundVariables();String contentToProcess = (String) inBoundVariables.get("content")// Logic Here to decide if content is approved or notif (contentToProcess.contains("activiti")) {logger.info("> Approving content: " + contentToProcess);integrationContext.addOutBoundVariable("approved",true);} else {logger.info("> Discarding content: " + contentToProcess);integrationContext.addOutBoundVariable("approved",false);}return integrationContext;};
}
这些连接器使用 Bean 名称自动连接到 ProcessRuntime,在本例中为“processTextConnector”。
这个 bean 名称是从我们流程定义中的 serviceTask 元素的 implementation 属性中提取的:
categorize-content.bpmn20.xml#L22
<bpmn:serviceTask id="Task_1ylvdew" name="Process Content" implementation="processTextConnector">
这个新的连接器接口是 JavaDelegates 的自然演变,新版本的 Activiti Core 将尝试通过将它们包装在连接器实现中来重用你的 JavaDelegates:
public interface Connector {IntegrationContext execute(IntegrationContext integrationContext);
}
连接器接收带有流程变量的 IntegrationContext 并返回修改后的 IntegrationContext 以及需要映射回流程变量的结果。
在前面的示例中,连接器实现正在接收“内容”变量并根据内容处理逻辑添加“已批准”变量。
在这些连接器中,您可能会包含系统到系统调用,例如 REST 调用和基于消息的交互。 这些交互往往变得越来越复杂,因此我们将在未来的教程中看到如何从 ProcessRuntime(云连接器)上下文之外运行中提取这些连接器,以解耦此类外部交互的责任。 ProcessRuntime 范围。
检查 maven 模块 activiti-api-spring-integration-example 以获得更高级的示例,使用 Spring Integrations 基于文件轮询器启动进程。
相关文章:
工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求
前言 大家好,我是老马。 最近想设计一款审批系统,于是了解一下关于流程引擎的知识。 下面是一些的流程引擎相关资料。 工作流引擎系列 工作流引擎-00-流程引擎概览 工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&#x…...
时序数据库IoTDB的分片与负载均衡策略深入解析
一、引言 随着数据库服务的业务负载增加,扩展服务资源成为必然需求。扩展方式主要分为纵向扩展和横向扩展。纵向扩展通过增加单台机器的能力(如内存、硬盘、处理器)来实现,但受限于单台机器的硬件能力。而横向扩展则通过增加更多…...

NVM安装使用及问题解决
目录 一、前言 二、NVM安装 三、配置下载源 四、nvm使用 五、安装nvm list available没有的版本 六、问题解决 一、前言 如果你开发 Node.js 项目,可能会遇到这些问题: ①新项目需要 Node.js 18,但老项目只能用 Node.js 14,…...

C++学习之STL学习:string类使用
在之前的学习中,我们初步了解到了STL的概念,接下来我们将深入学习STL中的string类的使用,后续还会结合他们的功能进行模拟实验 目录 为什么要学习string类? 标准库中的string类 string类(了解) auto和范围…...
基于 STC89C52 的养殖场智能温控系统设计与实现
摘要 本文提出一种基于 STC89C52 单片机的养殖场环境温度智能控制系统,通过集成高精度温度传感器、智能执行机构及人机交互模块,实现对养殖环境的实时监测与自动调控。系统具备温度阈值设定、超限报警及多模式控制功能,可有效提升养殖环境稳定性,降低能耗与人工成本。 一…...
redis哨兵服务
配置主机Host67为master服务器配置主机host68为 slave服务器配置主机host69运行哨兵服务测试配置 IP地址主机名192.168.10.167redis167192.168.10.168redis168192.168.10.169redis169 步骤一:配置主机Host67为master服务器 [rootredis169 ~]# vim /etc/redis.c…...

5月24日day35打卡
模型可视化与推理 知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 作业:调整模型定义时的超参数&#x…...
嵌入式<style>设计模式
每天分享一个web前端开发技巧。 今天分享的主题是,如何提升前端代码的内聚性。我们在写<style></style>的时候,往往把大量无关联的样式写在同一个<style>下,而且离相关的html元素很远,这样导致每次想修改某个元…...
Kotlin 中该如何安全地处理可空类型?
在 Kotlin 中,可空类型(如 String?)是语言设计的核心特性之一,旨在从编译时避免 NullPointerException(NPE)。 1 核心处理方式 1.1 安全调用操作符(?.) 直接调用可空对象的方法…...
基于大模型预测的视神经脊髓炎技术方案
目录 一、术前评估与预测1. 数据采集与预处理2. 大模型构建与训练3. 术前风险评估与预测二、术中监测与决策支持1. 实时数据采集与传输2. 术中决策支持系统三、术后管理与康复1. 术后早期预警与监测2. 康复效果预测与个性化方案四、并发症风险预测与防控1. 并发症风险预测模型2…...
使用防火墙禁止程序联网(这里禁止vscode)
everything搜一下Code.exe的安装路径:D:\downloadApp1\vscode\Microsoft VS Code\Code.exe 方法:使用系统防火墙(推荐) Windows 通过防火墙阻止 VS Code: 打开 Windows Defender 防火墙(控制面板 > 系统…...

Linux(7)——进程(概念篇)
目录 一、基本概念 二、描述进程——PCB 1.task_struct——PCB的一种 2.task_struct的内容分类 三、查看进程 1.通过系统目录查看 2.通过ps命令查看 四、通过系统调用获取进程的PID和PPID 五、通过系统调用创建进程 1.fork函数创建子进程 2.使用if来引出问题 六、L…...

前端流行框架Vue3教程:24.动态组件
24.动态组件 有些场景会需要在两个组件间来回切换,比如 Tab 界面 我们准备好A B两个组件ComponentA ComponentA App.vue代码如下: <script> import ComponentA from "./components/ComponentA.vue" import ComponentB from "./…...

Unity3D仿星露谷物语开发48之显示树桩效果
1、目标 砍完橡树之后会露出树桩,然后树桩可以用斧头收割,并将创建一个新的砍树桩的粒子效果。 这里有:一种作物收获后创造另一种作物的逻辑。 2、分析 在SO_CropDetailsList中,Harvested Transform Item Code可以指定收获后生…...

[Datagear] 实现按月颗粒度选择日期的方案
在使用 Datagear 构建数据分析报表时,常常会遇到一个问题:如果数据的目标颗粒度是“月”,默认的日期控件却是精确到“日”的,这在用户交互和数据处理层面会带来不必要的复杂度。本文将分享两种解决方案,帮助你更好地控制日期控件的颗粒度,实现以月为单位的日期筛选功能。…...

漏洞检测与渗透检验在功能及范围上究竟有何显著差异?
漏洞检测与渗透检验是确保系统安全的重要途径,这两种方法各具特色和功效,它们在功能上有着显著的差异。 目的不同 漏洞扫描的主要任务是揭示系统内已知的安全漏洞和隐患,这就像是对系统进行一次全面的健康检查,看是否有已知的疾…...

DB-GPT扩展自定义Agent配置说明
简介 文章主要介绍了如何扩展一个自定义Agent,这里是用官方提供的总结摘要的Agent做了个示例,先给大家看下显示效果 代码目录 博主将代码放在core目录了,后续经过对源码的解读感觉放在dbgpt_serve.agent.agents.expand目录下可能更合适&…...
基于SamOutV8的序列生成模型实现与分析
项目概述 本项目实现了基于SamOutV8架构的序列生成模型,核心组件包括MaxStateSuper、FeedForward和DecoderLayer等模块。通过结合自注意力机制与状态编码策略,该模型在处理长序列时表现出良好的性能。 核心组件解析 1. MaxStateSuper(状态编…...

家政维修平台实战09:推送数据到多维表格
目录 1 API调试2 创建云函数3 前端调用整体效果总结 上一篇我们搭建了服务分类的后台功能,对于分类的图标通过集成TOS拿到了可以公开访问的地址,本篇我们将写入的数据推送至多维表格中。 1 API调试 要想推送多维表格的数据,首先要利用官方的…...

前端框架token相关bug,前后端本地联调
今天我搭建框架的时候,我想请求我自己的本地!然后我自己想链接我自己的本地后端,我之前用的前端项目,都是链别人的后端,基本上很少情况会链接自己的后端!所以我当时想的是,我前后端接口一样&…...
PyQt学习系列05-图形渲染与OpenGL集成
PyQt学习系列笔记(Python Qt框架) 第五课:PyQt的图形渲染与OpenGL集成 一、图形渲染概述 1.1 为什么需要图形渲染? PyQt默认基于2D绘图(QPainter),但某些场景需要高性能3D图形或复杂视觉效果…...

卷积神经网络(CNN)可视化技术详解:从特征学到演化分析
在深度学习领域,卷积神经网络(CNN)常被称为“黑箱”,其内部特征提取过程难以直接观测。而 可视化技术 是打开这一“黑箱”的关键工具,通过可视化可直观了解网络各层学到了什么、训练过程中如何演化,以及模型…...
第十天的尝试
目录 一、每日一言 二、练习题 三、效果展示 四、下次题目 五、总结 一、每日一言 哈哈,十天缺了两天,我写的文章现在质量不高,所以我可能考虑,应该一星期或者三四天出点高质量的文章,同时很开心大家能够学到知识&a…...
WHAT - 兆比特每秒 vs 兆字节每秒
文章目录 Mbps 解释Mbps 和 MB/s(兆字节每秒)换算总结网络场景1. 在路由器设置中的 Mbps2. 在游戏下载时的 Mbps / MB/s总结 Mbps 解释 首先,Mbps 是一个常见的网络带宽单位,意思是: Megabits per second(…...
业务场景中使用 SQL 实现快速数据更新与插入
一、业务背景 在气象数据处理系统中,我们经常需要对分钟级的降水数据进行更新和插入操作。具体场景如下: • 数据源会定期发送分钟级的降水数据,包括降水值(PRECA)和质控码(PRECA_QC2)。 • …...

QT之INI、JSON、XML处理
文章目录 INI文件处理写配置文件读配置文件 JSON 文件处理写入JSON读取JSON XML文件处理写XML文件读XML文件 INI文件处理 首先得引入QSettings QSettings 是用来存储和读取应用程序设置的一个类 #include "wrinifile.h"#include <QSettings> #include <QtD…...

微信小程序调用蓝牙API “wx.writeBLECharacteristicValue()“ 报 errCode: 10008 的解决方案
1、问题现象 问题:在开发微信小程序蓝牙通信功能时,常常会遇到莫名其妙的错误,查阅官方文档可能也无法找到答案。如在写入蓝牙数据时,报了这样的错误: {errno: 1500104, errCode: 10008, errMsg: "writeBLECharacteristicValue:fail:system error, status: UNKNOW…...

【Java基础笔记vlog】Java中常见的几种数组排序算法汇总详解
Java中常见的几种排序算法: 冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort)希尔排序(Shell Sort)归并排序(Merge Sort)…...

WebRTC与RTSP|RTMP的技术对比:低延迟与稳定性如何决定音视频直播的未来
引言 音视频直播技术已经深刻影响了我们的生活方式,尤其是在教育、医疗、安防、娱乐等行业中,音视频技术成为了行业发展的重要推动力。近年来,WebRTC作为一种开源的实时通信技术,成为了音视频领域的重要选择,它使得浏览…...

spring cloud alibaba Sentinel详解
spring cloud alibaba Sentinel详解 spring cloud alibaba Sentinel介绍 Sentinel 是阿里巴巴开源的一款动态流量控制组件,主要用于保障微服务架构中的服务稳定性。它能够对微服务中的各种资源(如接口、服务方法等)进行实时监控、流量控制、…...