Flowable基础
简介
Flowable 是 BPMN 的一个基于 java 的软件实现,不过 Flowable 不仅仅包括 BPMN ,还有DMN 决策表和 CMMN Case 管理引擎,并且有自己的用户管理、微服务 API 等一系列功能,是一个服务平台。官方手册: https://tkjohn.github.io/flowable-userguide/#_introduction
1.创建ProcessEngine
- Flowable流程引擎。使我们可以创建一个ProcessEngine流程引擎对象,并访问 Flowable API。
- 一个是MySQL的数据库驱动
<dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</artifactId><version>6.3.0</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version>
</dependency>
然后创建一个普通的 Java 类,添加对应的 main 方法,首先要做的是初始化ProcessEngine 流程引擎实例。这是一个线程安全的对象,因此通常只需要在一个应用中初始化一次。 ProcessEngine 由 ProcessEngineConfiguration 实例创建。该实例可以配置与调整流程引擎的设置。 通常使用一个配置 XML 文件创建 ProcessEngineConfiguration ,但是(像在这里做的一样)也可以编程方式创建它。 ProcessEngineConfiguration 所需的最小配置,是数据库 JDBC 连接:
public static void main(String[] args) {ProcessEngineConfiguration cfg = new
StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?
serverTimezone=UTC") //5.6.setJdbcUsername("root").setJdbcPassword("root").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRU
E);ProcessEngine processEngine = cfg.buildProcessEngine();
}
注意在mysql8.0中执行可能出现如下的错误
出现这种情况只需要在 mysql 的连接字符串中添加上nullCatalogMeansCurrent=true ,设置为只查当前连接的 schema 库即可。jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC&nullCatalogMeansCurrent=true
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version>
</dependency>
log4j.rootLogger=DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p
%c %x - %m%n

2.部署流程定义

- 我们假定启动流程需要提供一些信息,例如雇员名字、请假时长以及说明。当然,这些 可以单独建模为流程中的第一步。 但是如果将它们作为流程的“输入信息”,就能保证 只有在实际请求时才会建立一个流程实例。否则(将提交作为流程的第一步),用户可 能在提交之前改变主意并取消,但流程实例已经创建了。 在某些场景中,就可能影响重
- 要的指标(例如启动了多少申请,但还未完成),取决于业务目标。
- 左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。
- 第一个矩形是一个用户任务(user task)。这是流程中用户操作的步骤。在这个例子 中,经理需要批准或驳回申请
- 取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至 批准或驳回路径
- 如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定
- 通知给申请人。当然也可以改为发送邮件。
- 如果驳回,则为雇员发送一封邮件通知他。

/*** 部署流程*/@Testpublic void testDeploy(){// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new
StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRU
E);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();// 部署流程 获取RepositoryService对象RepositoryService repositoryService =
processEngine.getRepositoryService();Deployment deployment = repositoryService.createDeployment()// 创
建Deployment对象.addClasspathResource("holiday-request.bpmn20.xml") // 添
加流程部署文件.name("请求流程") // 设置部署流程的名称.deploy(); // 执行部署操作System.out.println("deployment.getId() = " +
deployment.getId());System.out.println("deployment.getName() = " +
deployment.getName());}

act_re_procdef :流程定义表,部署每个新的流程定义都会在这张表中增加一条记录
act_ge_bytearray :流程资源表,流程部署的 bpmn文件和png图片会保存在该表中
/*** 查看流程定义*/@Testpublic void testDeployQuery(){// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new
StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRU
E);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();// 部署流程 获取RepositoryService对象RepositoryService repositoryService =
processEngine.getRepositoryService();// 获取流程定义对象
输出结果为:
3.启动流程实例
现在已经在流程引擎中部署了流程定义,因此可以使用这个流程定义作为“模板”启动流
程实例。
要启动流程实例,需要提供一些初始化流程变量。一般来说,可以通过呈现给用户的表
单,或者在流程由其他系统自动触发时通过REST API,来获取这些变量。在这个例子里,我
们简化直接在代码中定义了,我们使用RuntimeService启动一个流程实例。ProcessDefinition processDefinition =
repositoryService.createProcessDefinitionQuery().deploymentId("2501").singleResult();System.out.println("processDefinition.getId() = " +
processDefinition.getId());System.out.println("processDefinition.getName() = " +
processDefinition.getName());System.out.println("processDefinition.getDeploymentId() = " +
processDefinition.getDeploymentId());System.out.println("processDefinition.getDescription() = " +
processDefinition.getDescription());}
processDefinition.getId() = holidayRequest:2:2503processDefinition.getName() = Holiday RequestprocessDefinition.getDeploymentId() = 2501processDefinition.getDescription() = null
3.启动流程
要启动流程实例,需要提供一些初始化 流程变量 。一般来说,可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API ,来获取这些变量。在这个例子里,我们简化直接在代码中定义了,我们使用RuntimeService 启动一个 流程实例 。
/*** 启动流程实例*/@Testpublic void testRunProcess(){// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new
StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRU
E);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();// 启动流程实例通过 RuntimeService 对象RuntimeService runtimeService =
processEngine.getRuntimeService();// 构建流程变量Map<String,Object> variables = new HashMap<>();variables.put("employee","张三") ;// 谁申请请假variables.put("nrOfHolidays",3); // 请几天假variables.put("description","工作累了,想出去玩玩"); // 请假的原因// 启动流程实例,第一个参数是流程定义的idProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest",
variables);// 启动流程实例// 输出相关的流程实例信息System.out.println("流程定义的ID:" +
processInstance.getProcessDefinitionId());System.out.println("流程实例的ID:" + processInstance.getId());System.out.println("当前活动的ID:" +
processInstance.getActivityId());}
流程定义的 ID : holidayRequest:2:2503流程实例的 ID : 5001当前活动的 ID : null
对应的流程实例ID为:5001
4.查看任务
/*** 查看任务*/@Testpublic void testQueryTask(){// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().processDefinitionKey("holidayRequestNew").taskAssignee("lisi").list();for (Task task : list) {System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());System.out.println("task.getId() = " + task.getId());System.out.println("task.getAssignee() = " + task.getAssignee());System.out.println("task.getName() = " + task.getName());}}
task.getProcessDefinitionId() = holidayRequestNew:1:10003task.getId() = 12508task.getAssignee() = lisitask.getName() = Approve or reject request
5.完成任务
/*** 完成任务*/@Testpublic void testCompleteTask() {// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = newStandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("holidayRequestNew").taskAssignee("lisi").singleResult();// 添加流程变量Map<String, Object> variables = new HashMap<>();variables.put("approved", false); // 拒绝请假// 完成任务taskService.complete(task.getId(), variables);}
6.流程的删除
@Testpublic void testDeleteProcess() {// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = newStandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();RepositoryService repositoryService =processEngine.getRepositoryService();// 删除流程定义,如果该流程定义已经有了流程实例启动则删除时报错// repositoryService.deleteDeployment("1");// 设置为TRUE 级联删除流程定义,及时流程有实例启动,也可以删除,设置为false非级联删除操作。repositoryService.deleteDeployment("2501", true);}
7.查看历史信息
只选择一个特定流程实例的活动只选择已完成的活动结果按照结束时间排序,代表其执行顺序。
/*** 查看历史*/@Testpublic void testQueryHistory() {// 配置数据库相关信息 获取 ProcessEngineConfigurationProcessEngineConfiguration cfg = newStandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowablelearn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 获取流程引擎对象ProcessEngine processEngine = cfg.buildProcessEngine();HistoryService historyService =processEngine.getHistoryService();List<HistoricActivityInstance> list =historyService.createHistoricActivityInstanceQuery().processDefinitionId("holidayRequestNew:1:10003").finished().orderByHistoricActivityInstanceEndTime().asc().list();for (HistoricActivityInstance historicActivityInstance : list) {System.out.println(historicActivityInstance.getActivityId()+ " took "+ historicActivityInstance.getDurationInMillis() + "milliseconds");}}
相关文章:

Flowable基础
简介 Flowable 是 BPMN 的一个基于 java 的软件实现,不过 Flowable 不仅仅包括 BPMN ,还有 DMN 决策表和 CMMN Case 管理引擎,并且有自己的用户管理、微服务 API 等一系列功能, 是一个服务平台。 官方手册: https://…...

力扣热门100题之合并区间【中等】
题目描述 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 1: 输入:interv…...
机会成本:隐形的手,驱动你的选择
机会成本这个词不知道你有没有听说过。 机会成本是指在面临多方案择一决策时,被舍弃的选项中的最高价值者。换句话说,机会成本是一种失去的收益,不是实际支付的成本。 机会成本是经济学中一个非常重要的概念,它可以帮助我们更好地…...

win10日程怎么同步到安卓手机?电脑日程同步到手机方法
在如今快节奏的生活中,高效地管理时间变得至关重要。而对于那些经常在电脑上安排日程的人来说,将这些重要的事务同步到手机上成为了一个迫切的需求。因为目前国内使用win10系统电脑、安卓手机的用户较多,所以越来越多的职场人士想要知道&…...

7月31日每日两题
第一题:再解炸弹人 小哼最近爱上了“炸弹人”游戏。你还记得在小霸王游戏机上的炸弹人吗?用放置炸弹的方法来消灭敌人。需将画面上的敌人全部消灭后,并找到隐藏在墙里的暗门才能过关。 现在有一个特殊的关卡如下。你只有一枚炸弹,但是这枚炸弹威力超强(杀伤距离超长,可…...

首期华为云ROMA Connect《企业集成战略与华为数字化之道》高研班在东莞圆满举办
7月25日,首期华为云ROMA Connect《企业集成战略与华为数字化之道》高研班在东莞华为制造业数字化转型中心圆满举办。 20多家东莞精密机械、电子、环保等领域的先进企业董事长、总经理、CIO、总监等高管参加培训。 本次高研班邀请到华为数字化转型专家陈劲、马兵东…...
JS语法知识点
变量声明: 使用 var 关键字声明的变量具有函数作用域,可以在函数内部访问。使用 let 或 const 关键字声明的变量具有块级作用域,只在声明的块内有效。 数据类型: 字符串(String):表示文本数据&a…...
【设计模式】 策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,使它们可以相互替换,让客户端代码和算法的具体实现解耦。这样,客户端可以根据不同的需求选择不同的算…...

Redis优惠券秒杀超卖问题
Redis秒杀超卖问题 前言一、出现秒杀超卖的原因二、超卖解决方案使用乐观锁解决超卖问题程序中进行解决 前言 这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖比较全。 黑马redis视频链接:B站黑马redis教学视频 本文参考黑马redi…...

14个最强大的建筑设计AI工具
在整个行业中,建筑师在他们的创造性追求中正在拥抱一个新的合作伙伴:AI。 一旦受到重复和单调的困扰,建筑工人发现自己正处于数字革命的风口浪尖,其中比特和字节掌握着自动化和曾经难以想象的可能性的关键。 推荐:用 …...

Ueditor 百度强大富文本Springboot 项目集成使用(包含上传文件和上传图片的功能使用)简单易懂,举一反三
Ueditor 百度强大富文本Springboot 项目集成使用 首先如果大家的富文本中不考虑图片或者附件的情况下,只考虑纯文本且排版的情况下我们可以直接让前端的vue来继承UEditor就可以啦。但是要让前端将那几个上传图片和附件的哪些功能给阉割掉! 然后就是说如…...
【NLP】一个使用PyTorch实现图像分类的迁移学习实例
一个使用PyTorch实现图像分类的迁移学习实例 1. 导入模块2. 加载数据3. 模型处理4. 训练及验证模型5. 微调6. 其他代码 在特征提取中,可以在预先训练好的网络结构后修改或添加一个简单的分类器,然后将源任务上预先训练好的网络作为另一个目标任务的特征提…...

【wsl-windows子系统】安装、启用、禁用以及同时支持docker-desktop和vmware方案
如果你要用docker桌面版,很可能会用到wsl,如果没配置好,很可能wsl镜像会占用C盘很多空间。 前提用管理员身份执行 wsl-windows子系统安装和启用 pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper…...

使用docker部署springboot微服务项目
文章目录 1. 环境准备1. 准备好所用jar包项目2.编写相应的Dockerfile文件3.构建镜像4. 运行镜像5. 测试服务是否OK6.端口说明7.进入容器内8. 操作容器的常用命令 1. 环境准备 检查docker是否已安装 [rootlocalhost /]# docker -v Docker version 1.13.1, build 7d71120/1.13.…...

uniapp兼容微信小程序和支付宝小程序遇到的坑
1、支付宝不支持v-show 改为v-if。 2、v-html App端和H5端支持 v-html ,微信小程序会被转为 rich-text,其他端不支持 v-html。 解决方法:去插件市场找一个支持跨端的富文本组件。 3、导航栏处有背景色延伸至导航栏外 兼容微信小程序和支…...

LeetCode208.Implement-Trie-Prefix-Tree<实现 Trie (前缀树)>
题目: 思路: tire树,学过,模板题。一种数据结构与算法的结合吧。 代码是: //codeclass Trie { private:bool isEnd;Trie* next[26]; public:Trie() {isEnd false;memset(next, 0, sizeof(next));}void insert(strin…...

第1章 JavaScript简史
JavaScript的起源 JavaScript是Netscape公司与Sun公司合作开发的在JavaScript诞生之前游览器就是显示超文本文档的简单的软件,JavaScript为此增加了交互行为ECMAScript是JavaScript的标准化,本质上是同一个语言JavaScript是一门脚本语言通常只能运行在游…...

DevOps-GitHub/GitLab
DevOps-GitHub/GitLab GitHub是一个开源代码托管平台。基于web的Git仓库,提供共有仓库和私有仓库(私有仓库收费)。 GitLab可以创建免费私有仓库。 GitHub 为了快速操作,这里对创建仓库以及注册不做说明。 首先再GitHub上创建一…...

redis群集(主从复制)
---------------------- Redis 主从复制 ---------------------------------------- 主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的…...

F5 LTM 知识点和实验 5-健康检测
第五章:健康检测 监控的分类: 地址监控(3层)服务监控(4层)内容监控(7层)应用监控(7层)性能监控(7层)路径监控(3、4、7层)三层监控: 三层监控可以帮助bipip系统通过检查网络是否可达监视资源。比如使用icmp echo,向监控节点发送icmp_echo报文,如果接收到响应…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...