1. 定时器

1.1. 流程定义定时激活

在之前松哥给小伙伴们介绍流程定义的时候,流程都是定义好之后立马就激活了,其实在流程定义的这个过程中,我们还可以设置一个激活时间,也就是流程定义好之后,并不会立马激活(不激活就不能据此流程定义创建新流程),而是在延迟某一个固定时间之后,才会激活,代码如下:

@RestController
public class ProcessDeployController {@AutowiredRepositoryService repositoryService;@PostMapping("/deploy")public RespBean deploy(MultipartFile file,String tenantId) throws IOException {System.out.println(new Date());DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().category("javaboy的工作流分类").name("javaboy的工作流名称").addInputStream("fff.bpmn", file.getInputStream()).tenantId(tenantId).activateProcessDefinitionsOn(new Date(System.currentTimeMillis() + 1000 * 60)).key("javaboy的工作流key666");Deployment deployment = deploymentBuilder.deploy();return RespBean.ok("部署成功",deployment.getId());}
}
复制代码

.activateProcessDefinitionsOn(new Date(System.currentTimeMillis() + 1000 * 60)) 表示流程在延迟一分钟之后,才激活。

此时,我们启动项目,然后调用该接口部署一个流程,部署完成之后,如果立马调用流程启动方法去启动流程,就会抛出如下异常:

可以看到,这里也说的很明确了,这个流程定义目前是一个挂起的状态,无法启动。

这个时候,我们去查看 ACT_RU_TIMER_JOB 表,就会发现该表中多了一条定时任务执行计划:

该表有一个 DUEDATE_ 字段,这个字段描述了这个定时任务执行的具体时间,在到达时间后,定时任务会自动执行,将 ACT_RE_PROCDEF 表中,流程的状态字段 SUSPENSION_STATE_ 由 2 改为 1。

1.2. 流程实例定时挂起

除了流程定义可以定时挂起外,流程实例也可以定时挂起。方式如下:

@Autowired
RepositoryService repositoryService;
@Test
void test23() {repositoryService.suspendProcessDefinitionByKey("UserTaskDemo", true, new Date(System.currentTimeMillis() + 120 * 1000));
}
复制代码

这个执行完成后,也会在 ACT_RU_TIMER_JOB 表中添加一条定时任务,在两分钟之后,会自动挂起这个流程定义以及与之相对应的流程。实际上就是将对应表中的 SUSPENSION_STATE_ 字段值由 1 改为 2。

1.3. 定时任务执行过程

前面两个小节,松哥都和大家提到,ACT_RU_TIMER_JOB 表中会保存定时任务信息,时间到了就会自动执行。

但是小伙伴们注意,定时任务每次执行的时候,其实并不是去 ACT_RU_TIMER_JOB 表中查询数据,而是去 ACT_RU_JOB 表中查询数据并执行。

当定时的时间到了后,Flowable 会自动将数据从 ACT_RU_TIMER_JOB 表中移动到 ACT_RU_JOB 表中,然后定时器查询到 ACT_RU_JOB 表中的数据之后,就立马自动执行了。大致上就是这样一个流程。

我给大家手动演示一个。

我现在的流程定义和流程实例都挂起了,我想要在 4 分钟之后,将之全部启动,代码如下:

@Test
void test24() {repositoryService.activateProcessDefinitionByKey("UserTaskDemo", true, new Date(System.currentTimeMillis() + 240 * 1000));
}
复制代码

当这行代码执行之后,4 分钟之后,流程定义和流程实例就全部都启动了。但是我现在忽然就不想等四分钟了,我想立马执行,那么我们可以去 ACT_RU_TIMER_JOB 表中找到这个定时任务的 ID,然后执行如下代码:

@Autowired
ManagementService managementService;
@Test
void test25() {managementService.moveTimerToExecutableJob("b7e9501d-5075-11ed-9706-acde48001122");
}
复制代码

这个代码表示将 ID 为 b7e9501d-5075-11ed-9706-acde48001122 的记录由 ACT_RU_TIMER_JOB 表移动到 ACT_RU_JOB 表中,移动完成后,这个任务就会被立马执行。

当一个定时任务开启了,还能不能取消呢?当然可以!我们将这个定时任务放到私信队列表即可,私信队列表是 ACT_RU_DEADLETTER_JOB,具体操作方式如下:

@Test
void test27() {managementService.moveJobToDeadLetterJob("6b95dc62-5081-11ed-a00f-acde48001122");
}
复制代码

上面这个方法执行的参数是 ACT_RU_TIMER_JOB 表中的任务 ID,执行完成后,ACT_RU_TIMER_JOB 表中对应的记录就会被移动到 ACT_RU_DEADLETTER_JOB 表中,所以定时任务就不会被执行了。

对于已经移动到私信队列的定时任务,也可以再通过如下方法移动回 ACT_RU_JOB 表中被立马执行(即使时间没到也会立马执行),如下:

@Test
void test26() {managementService.moveDeadLetterJobToExecutableJob("6b95dc62-5081-11ed-a00f-acde48001122", 10);
}
复制代码

参数就是任务 ID。

好啦,几个简单的例子和小伙伴们分享了下 Flowable 中定时器的玩法。

2. 实时流程图

在之前的文章中,松哥和大家展示过 Flowable 中的一个功能,就是我们可以绘制一张图片,来实时展示某一个流程走到哪一步了。不过当时没有跟大家详细介绍这个图片到底是如何绘制出来的,现在我们就来聊一聊这个话题。

2.1. 效果图

首先我们先来看一下绘制出来的效果图,如下:

已经执行的节点和连线用红色标记出来。大致上就是这么一个效果,今天就跟大家聊一聊这里的实现细节。

2.2. 实践

将一个流程图绘制成图片,相关的 API 在 flowable 中其实都是有提供的,流程图片的绘制,是根据流程的定义来绘制的,所以只需要提供一个流程定义的 ID 即可,如下:

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("ExclusiveGatewayDemo01").latestVersion().singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId());
DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
InputStream inputStream = generator.generatePngDiagram(bpmnModel, 1.0, true);
FileUtils.copyInputStreamToFile(inputStream, new File("/Users/sang/Downloads/1.png"));
复制代码

这五行代码应该都好理解:

  1. 查找到流程定义对象。
  2. 根据流程定义对象,获取到一个 BpmnModel 对象。
  3. 创建一个图片生成器对象 DefaultProcessDiagramGenerator。
  4. 调用 generatePngDiagram 方法生成这个流程定义所对应的图片,参数有三个,分别是:前面查询到的 bpmnModel 对象;缩放因子以及是否在绘制流程图的时候,在连线上加上描述文字,generatePngDiagram 方法的返回值则是一个输入流。
  5. 最后将这个输入流打印出来,就是一张图片了。

上面这个方法执行结果如下:

可以看到,这就是普通的流程图,没有高亮。

如果希望已经执行的节点变成高亮的,那么可以使用如下方法:

这个方法参数比较多,我们挨个来说下:

  1. 流程的 bpmnModel 对象。
  2. 生成的图片类型。
  3. 高亮的活动节点。
  4. 高亮的连线。
  5. 缩放因子。
  6. 是否在绘制连线的时候添加文字描述。

这里的关键就是第三个和第四个参数。这个流程图中哪些节点哪些连线需要高亮,我们将之列出来即可。

根据我们之前文章中的介绍,小伙伴们知道,一个流程在执行过程中的活动信息,都是保存在 ACT_RU_ACTINST 表中,所以我们只需要根据流程实例的 ID 在 ACT_RU_ACTINST 表中查询到即可,如下:

@Test
void test01() throws IOException {ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("ExclusiveGatewayDemo01").latestVersion().singleResult();BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId());ProcessInstance pi = runtimeService.createProcessInstanceQuery().singleResult();List<String> highLightedActivities = new ArrayList<>();List<String> hightLightedFlows = new ArrayList<>();double scaleFactor = 1.0;boolean drawSqquenceFlowNameWithNoLabelDI = true;if (pi == null) {return;}List<ActivityInstance> list = runtimeService.createActivityInstanceQuery().list();for (ActivityInstance ai : list) {if (ai.getActivityType().equals("sequenceFlow")) {hightLightedFlows.add(ai.getActivityId());} else {highLightedActivities.add(ai.getActivityId());}}DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();InputStream inputStream = generator.generateDiagram(bpmnModel, "PNG", highLightedActivities, hightLightedFlows, scaleFactor, drawSqquenceFlowNameWithNoLabelDI);FileUtils.copyInputStreamToFile(inputStream, new File("/Users/sang/Downloads/1.png"));
}
复制代码

小伙伴们看到,我们这里使用 highLightedActivitieshightLightedFlows 两个集合,分别存一个流程已经执行的活动 ID 和连线的 ID。

通过 runtimeService.createActivityInstanceQuery().list(); 来查询到所有已经执行的活动,然后遍历,遍历的时候注意区分是不是 sequenceFlow,如果是 sequenceFlow 则将之添加到 hightLightedFlows 集合中,否则将之添加到 highLightedActivities 结合中。

最终,执行生成的图片就是本文已开始大家看到的图片。

按照上面这种方式,对于一个已经执行完毕的流程来说,似乎就画不出来流程图了,因为当一个流程执行完毕之后,ACT_RU_ACTINST 表中的数据就会自动清空。

不过。。。根据我们前面文章的介绍,执行完毕的活动信息还可以去 ACT_HI_ACTINST 表中进行查询,因此,我们这个流程图还可以这样画:

@Test
void test05() throws IOException {ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("ExclusiveGatewayDemo01").latestVersion().singleResult();BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId());HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().singleResult();if (hpi == null) {return;}List<String> highLightedActivities = new ArrayList<>();List<String> hightLightedFlows = new ArrayList<>();double scaleFactor = 1.0;boolean drawSqquenceFlowNameWithNoLabelDI = true;List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(hpi.getId()).list();for (HistoricActivityInstance hai : list) {if (hai.getActivityType().equals("sequenceFlow")) {hightLightedFlows.add(hai.getActivityId());} else {highLightedActivities.add(hai.getActivityId());}}DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();InputStream inputStream = generator.generateDiagram(bpmnModel, "PNG", highLightedActivities, hightLightedFlows, scaleFactor, drawSqquenceFlowNameWithNoLabelDI);FileUtils.copyInputStreamToFile(inputStream, new File("/Users/sang/Downloads/1.png"));
}
复制代码

可以看到,当一个流程实例执行完毕的时候,我们可以去历史表中查询这个流程实例,同时也去历史表中查询这个流程实例所执行过的活动 ID,找到之后,还是按照之前的办法,填充给 hightLightedFlowshighLightedActivities 两个变量。最终绘制出来的结果如下图:

好啦,绘制流程图差不多就这些内容,小伙伴们快去试试吧~

Flowable定时器与实时流程图相关推荐

  1. Flowable定时器与实时流程图江南一点雨

    1. 定时器 1.1. 流程定义定时激活 在之前松哥给小伙伴们介绍流程定义的时候,流程都是定义好之后立马就激活了,其实在流程定义的这个过程中,我们还可以设置一个激活时间,也就是流程定义好之后,并不会立 ...

  2. Qt中利用定时器QTimer实时显示当前日期和时间

    Qt中利用定时器QTimer实时显示当前日期和时间 时显示当前日期和时间.下面说明方法: 1. 在工程中声明一个全局QTimer对象 QTimer *timer; 2. 在构造函数中定义QTimer, ...

  3. Flowable流程追踪获取流程图时中文乱码

    Flowable流程追踪获取流程图时中文乱码 总结下最近遇到的一个BUG,需求是查询当前流程进度的一个流程图,但是生成的流程图里面的中文乱码,于是乎去查看设计流程时的流程图是正常的,有点奇怪,接下来就 ...

  4. Flowable工作流之Flowable UI画工作流程图

    目录 1. `Flowable` 简介 2. 绘制工作流程图 2.1. `Flowable UI` 的安装部署 2.2. 启动服务 2.3. 用户管理 2.4. 工作流程效果图 2.5. 绘制工作流程 ...

  5. vue定时器(实时刷新列表)

    直接加载定时器,对页面列表进行实时刷新 在(打开新页面对列表数据进行增删改或)对列表数据进行操作后,实时刷新列表(这里会出现一个小问题,比起reload不会页面变白刷新页面,因为是定时器,所以在列表上 ...

  6. java 定时器 数据库,java定时器和实时查询数据库

    第一次写,还有缺陷,待改进 定时器: Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { / ...

  7. Flowable工作流入门

    Flowable工作流入门 本文链接:https://blog.csdn.net/qq_37059838/article/details/83576097 原作者:吕小小布 下载地址:Flowable ...

  8. 基于Atmega16的定时器实验

    一.实验目的 1. 理解单片机定时器的工作原理. 2. 掌握定时器溢出中断实现定时的编程方法. 二.实验内容 1. 验证课堂例题 编译下载运行课堂例题--"T/C0溢出中断"(T0 ...

  9. c语言编程流水灯与交通灯实验,C51单片机实验报告_流水灯_交通灯_定时器_双机交互_时钟.doc...

    C51单片机实验报告_流水灯_交通灯_定时器_双机交互_时钟 学 号: 班 级: 自动化10班 姓 名: 张 指导老师: 胡 2012.12 单片机核心板实验要求 流水灯实验 实验目的: 简单I/O引 ...

最新文章

  1. Python数据处理篇之Matplotlib系列(六)---plt.hist()与plt.hist参数详解
  2. 是你写程序时的样子吗? | 每日趣闻
  3. 数据结构(Java)——迭代器和列表的实例
  4. 前端开发——移动端及响应式布局解决办法总结(适配)
  5. 苹果宣布加入CNCF;华为要求美国运营商支付专利费;微软删除最大的公开人脸识别数据集...
  6. 使用caffemodel模型(由mnist训练)测试单张手写数字样本
  7. centos php编译,深入讲解CentOS PHP安装编译
  8. git cherry-pick 多个commit_Git使用爬坑记录
  9. Alfresco安装与配置图解
  10. PIC单片机(PIC16F15323)的环境搭建
  11. 零一块学计算机二级题库,2017年计算机二级office题库及答案
  12. 将html导出为PDF文件(为PDF加盖章)
  13. 手机编程软件推荐(C/C++、JAVA篇)
  14. mysql复制表的两种方法
  15. 腹有诗书气自华——记环宇通软CEO骆永华 1
  16. soul网关mysql8_Dubbo学习系列之十七(微服务Soul网关)
  17. ftp 发生意外错误 0x8ffe2740
  18. 恶意软件的历史和应对措施
  19. Scikit-learn实战之最近邻算法
  20. 支付狙击战落败,教育分期问题缠身,度小满“困局”何解?

热门文章

  1. 选择恐惧症终极自救指南
  2. AES加解密效率测试(纯软件AES128/256)--以嵌入式Cortex-M0与M3 平台为例
  3. 使用阿里云的短信服务进行登录实现登录拦截的功能(前后端分离) ---- (Session存储验证码用户信息)
  4. 心里元宇宙火热招幕中
  5. 大数据基础编程第二版(林子雨)官网,代码与软件资源
  6. 夏普MX-M2658N复印机显示请放入载体组件
  7. day16 初识面向对象编程(类与对象、构造函数与对象,类与类)
  8. Pandas Cut 与dataframe随机抽取(sample)替换(replace)应用案例
  9. DNS Query Types
  10. PIM-SM(ASM模型)