Flowable进阶学习(十)定时器、ServiceTask服务任务、ScriptTask脚本任务

news2024/9/29 22:50:13

文章目录

  • 一、定时器
    • 1. 流程定义定时激活
    • 2. 流程实例定时挂起
    • 3. 定时任务执行过程
  • ServiceTask 服务任务
    • 委托表达式
    • 表达式
    • 类中字段
  • ScriptTask 脚本任务
    • JS TASK

一、定时器

相关知识链接阅读:事件网关——定时器启动事件

1. 流程定义定时激活

可以通过activateProcessDefinitionsOn(date)给流程定义设置一个启动时间。这个流程就会延迟激活。在激活之前,无法启动该流程。

  1. 部署流程
@Test
void test_delayDeploy() {
    Deployment deploy = repositoryService.createDeployment()
            .addClasspathResource("process/请假Demo.bpmn20.xml")
            .name("deployName-定时启动")
            // 表示延迟1分钟激活流程定义
            .activateProcessDefinitionsOn(new Date(System.currentTimeMillis() + 1000 * 60))
            .key("deployKey-dsqd").deploy();
    System.out.println("deploy.getId() = " + deploy.getId());
}
  1. 启动测试
@Test
void startFlow(){
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROC_KEY);
    System.out.println("processInstance.getId() = " + processInstance.getId());
}

当我们在流程定义还未到时激活的时候,来启动一个流程,则会抛出异常:流程定义挂起

org.flowable.common.engine.api.FlowableException: Cannot start process instance. Process definition 请假Demo (id = qj-demo:1:d91875ee-a88c-11ed-a56b-c83dd4896099) is suspended

我们查看ACT_RU_TIMER_JOB表,可以看到表中有一条任务记录,其中DUEDATE_是处理时间(当时间到达或超过自动处理,会将ACT_RE_PROCDEF表的SUSPENSION_STATE_状态2变更为1), HANDLER_TYPE_是激活流程定义,HANDLER_CFG_ 是否包含流程实例。
在这里插入图片描述

2. 流程实例定时挂起

@Test
void test_Suspend() throws InterruptedException {
    // 设置30秒后自动挂起该流程定义与流程实例
    Date suspensionDate = new Date(System.currentTimeMillis() + 1000 * 30);
    // 这个方法是挂起流程定义的方法
    repositoryService.suspendProcessDefinitionByKey(PROC_KEY, true, suspensionDate);
    // 这个方法是流程实例的挂起方法
//        runtimeService.suspendProcessInstanceById("id001");
    Thread.sleep(30);
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY).latestVersion().singleResult();
    System.out.println("processDefinition.getName() = " + processDefinition.getName());
    System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
    List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(PROC_KEY).list();
    for (ProcessInstance instance : list) {
        System.out.println("instance.isSuspended() = " + instance.isSuspended());
    }
}

3. 定时任务执行过程

ManagementService方法名作用涉及表变动
moveTimerToExecutableJob(job.getId());将定时任务移动到执行ACT_RU_TIMER_JOB -> ACT_RU_JOB
moveJobToDeadLetterJob(job.getId());将任务移动到死信任务ACT_RU_TIMER_JOB -> ACT_RU_DEADLETTER_JOB
`moveDeadLetterJobToExecutableJob(job.getId(), 1)移动死信任务到执行任务ACT_RU_DEADLETTER_JOB -> ACT_RU_JOB
createTimerJobQuery()查询定时任务ACT_RU_TIMER_JOB
createDeadLetterJobQuery()查询死信任务ACT_RU_DEADLETTER_JOB

任务相关表信息

表名含义
ACT_RU_TIMER_JOB定时作业表
ACT_RU_JOB运行时作业表(进入运行时作业表的任务会被立即执行)
ACT_RU_HISTORY_JOB历史作业表
ACT_RU_DEADLETTER_JOB死信作业表(DeadLetter:死信、退件、空文,存放取消的定时作业)
ACT_RU_SUSPENDED_JOB挂起作业表
ACT_RU_EXTERNAL_JOB外部作业表
/**
 * 延迟5分钟激活
 *
 * @throws InterruptedException
 */
@Test
void test_activeProcess() throws InterruptedException {
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    // 延迟5分钟激活流程定义与实例
    Date activationDate = new Date(System.currentTimeMillis() + 5 * 60 * 1000);
    System.out.println("pd.isSuspended() = " + pd.isSuspended());
    if (!pd.isSuspended()) {
        repositoryService.suspendProcessDefinitionById(pd.getId());
    }
    repositoryService.activateProcessDefinitionById(pd.getId(), true, activationDate);
    //org.flowable.common.engine.api.FlowableException: Cannot set suspension state 'suspended' for ProcessDefinitionEntity[qj-demo:1:d91875ee-a88c-11ed-a56b-c83dd4896099]': already in state 'suspended'.
}

/**
 * 查询并立即激活
 *
 * @throws InterruptedException
 */
@Test
void queryAndActiveNow() throws InterruptedException {
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
    List<Job> list = managementService.createTimerJobQuery().processDefinitionId(processDefinition.getId()).list();
    list.forEach(job -> {
        managementService.moveTimerToExecutableJob(job.getId());
    });
    Thread.sleep(30);
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    System.out.println("pd.isSuspended() = " + pd.isSuspended());
}

/**
 * 延迟5分钟挂起
 *
 * @throws InterruptedException
 */
@Test
void test_suspendedProcess() throws InterruptedException {
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    // 延迟5分钟激活流程定义与实例
    Date activationDate = new Date(System.currentTimeMillis() + 2 * 60 * 1000);
    System.out.println("pd.isSuspended() = " + pd.isSuspended());
    if (pd.isSuspended()) {
        repositoryService.activateProcessDefinitionById(pd.getId());
    }
    repositoryService.suspendProcessDefinitionById(pd.getId(), true, activationDate);
}

/**
 * 查询并立即挂起
 *
 * @throws InterruptedException
 */
@Test
void queryAndSuspendedNow() throws InterruptedException {
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
    // 定时任务查询
    List<Job> list = managementService.createTimerJobQuery().processDefinitionId(processDefinition.getId()).list();
    list.forEach(job -> {
        managementService.moveJobToDeadLetterJob(job.getId());
    });
    Thread.sleep(60 * 1000);
    // deadLetter 死信、空文、退件
    // 从退件任务队列查询
    List<Job> deadLetterJobs = managementService.createDeadLetterJobQuery().processDefinitionId(processDefinition.getId()).list();
    deadLetterJobs.forEach(job -> {
        // 将退件任务移到执行列表
        managementService.moveDeadLetterJobToExecutableJob(job.getId(), 1);
//            managementService.moveDeadLetterJobToHistoryJob(job.getId(),1);
    });
    Thread.sleep(60 * 1000);
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(PROC_KEY)
            .latestVersion().singleResult();
    System.out.println("pd.isSuspended() = " + pd.isSuspended());
}

ServiceTask 服务任务

ServiceTask一般由系统自动完成,当系统走到这一步的时候,不会停下,会自动执行我们在ServiceTask配置的方法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e04fdfc226ca495091933b45ec8ad241.png

委托表达式

在这里插入图片描述
实现了JavaDelegate的接口,注入Spring容器,在配置中可以不写完整类名,只需要写Spring容器名称即可。首字母小写${myServiceTask}

@Component
public class MyServiceTask implements JavaDelegate {
    @Autowired
    TaskService taskService;
    @Autowired
    RuntimeService runtimeService;

    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("========MyServiceTask2==========");
        System.out.println("execution = " + execution);
//        execution.getCurrentActivityId()

    }
}

表达式

表达式可以是普通类中的一个方法${myServiceTask2.hello()}

类中字段

在这里插入图片描述

Expression userName;

@Override
public void execute(DelegateExecution execution) {
    System.out.println("========MyServiceTask2==========");
    System.out.println("execution = " + execution);
    if (userName != null) {
        System.out.println("username.getExpressionText() = " + userName.getExpressionText());
        System.out.println("username.getValue(execution) = " + userName.getValue(execution));
    }
}

ScriptTask 脚本任务

脚本任务,当流程到达该节点的时候,自动执行脚本。可以有JS(JavaScript)、Groovy、Juel脚本。

JS TASK

在这里插入图片描述
需要注意的是JS脚本不支持ES6语法。
部署流程

@Test
void doDeploy2() {
    Deployment deploy = repositoryService.createDeployment()
            .addClasspathResource("process/脚本任务demo.bpmn20.xml")
            .deploy();
    System.out.println("deploy.getId() = " + deploy.getId());
}

启动流程与查询流程变量

@Test
void jsTask() {
    Map<String, Object> variables = new HashMap<>();
    variables.put("a", 99);
    variables.put("b", 98);
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("js-task", variables);
    System.out.println("pi.getId() = " + pi.getId());
    System.out.println("pi.getActivityId() = " + pi.getActivityId());
    System.out.println("pi.getProcessVariables() = " + pi.getProcessVariables());
}

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

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

相关文章

材质笔记 - Simluate Solid Surface

光的行为 当光和物体相遇时&#xff0c;光会有三种行为&#xff1a;被物体反射、穿过物体&#xff08;物体是透明或半透明的&#xff09;或者被吸收。 高光反射和漫反射 高光反射&#xff08;Specular Reflection&#xff09;会在表面光滑且反光的物体上看到&#xff0c;比如镜…

SMART PLC时间间隔定时器应用(高速脉冲测频/测速)

高速脉冲计数测量频率,专栏有系列文章分析讲解,这里不再赘述(原理都是利用差分代替微分)。具体链接如下: 西门子SMART PLC高速脉冲计数采集编码器速度(RC滤波)_RXXW_Dor的博客-CSDN博客这篇文章主要讲解西门子 SMART PLC高速计数采集编码器脉冲信号计算速度,根据编码器脉…

鸢尾花数据集分类(PyTorch实现)

一、数据集介绍 Data Set Information: This is perhaps the best known database to be found in the pattern recognition literature. Fisher’s paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data…

[Android Studio]Android 数据存储-文件存储学习笔记-结合保存QQ账户与密码存储到指定文件中的演练

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

戴尔游匣G16电脑U盘安装系统操作教程分享

戴尔游匣G16电脑U盘安装系统操作教程分享。有用户在使用戴尔游匣G16电脑的时候遇到了系统问题&#xff0c;比如电脑蓝屏、自动关机重启、驱动不兼容等问题。遇到这些问题如果无法进行彻底解决&#xff0c;我们可以通过U盘重新安装系统的方法来解决&#xff0c;因为这些问题一般…

I.MX6ULL内核开发7:led字符设备驱动实验

目录 一、led字符设备驱动实验 二、驱动模块初始化 三、虚拟地址读写 四、自定义led的file_operation接口 五、拷贝数据 六、register_chrdev函数 七、 __register_chrdev函数 八、编译执行 一、led字符设备驱动实验 驱动模块内核模块(.ko)驱动接口(file_operations) …

Mysql 增删改查(一) —— 查询(条件查询where、分页limits、排序order by)

查询 select 可以认为是四个基本操作中使用最为频繁的操作&#xff0c;然而数据量比较大的时候&#xff0c;我们不可能查询所有内容&#xff0c;我们一般会搭配其他语句进行查询&#xff1a; 假如要查询某一个字段的内容&#xff0c;可以使用 where假如要查询前几条记录&#…

STM32----搭建Arduino开发环境

搭建Arduino开发环境前言一、Arduino软件1.软件下载2.软件安装3.软件操作二、Cortex官方内核三、烧录下载四、其他第三方内核1.Libmaple内核2.Steve改进的LibMaple 内核3.STMicroelectronics(ST)公司编写的内核总结前言 本章介绍搭建STM32搭建Arduino开发环境&#xff0c;包括…

leetcode470 用Rand7()实现Rand10()

力扣470 第一步&#xff1a;根据Rand7()函数制作一个可以随机等概率生成0和1的函数rand_0and1 调用Rand7()函数&#xff0c;随机等概率生成1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7 这时我们设置&#xff1a;生成1&#xff0c;2&a…

“深度学习”学习日记。卷积神经网络--用CNN的实现MINIST识别任务

2023.2.11 通过已经实现的卷积层和池化层&#xff0c;搭建CNN去实现MNIST数据集的识别任务&#xff1b; 一&#xff0c;简单CNN的网络构成&#xff1a; 代码需要在有网络的情况下运行&#xff0c;因为会下载MINIST数据集&#xff0c;运行后会生成params.pkl保留训练权重&…

【吉先生的Java全栈之路】

吉士先生Java全栈学习路线&#x1f9e1;第一阶段Java基础: 在第一阶段:我们要认真听讲,因为基础很重要!基础很重要!基础很重要!!! 重要的事情说三遍。在这里我们先学JavaSE路线&#xff1b;学完之后我们要去学第一个可视化组件编程《GUI》&#xff1b;然后写个《贪吃蛇》游戏耍…

微搭低代码从入门到精通05-变量定义

我们上一篇对应用编辑器有了一个整体的介绍。要想零基础开发小程序&#xff0c;就得从各种概念开始学起。 如果你是零基础学习开发&#xff0c;无论学习哪一门语言&#xff0c;第一个需要掌握的知识点就是变量。 那么什么是变量&#xff1f;变量其实就是存放数据的一个容器&a…

专题 | 防抖和节流

一 防抖&#xff1a;单位时间内&#xff0c;频繁触发事件&#xff0c;只执行最后一次 场景&#xff1a;搜索框搜索输入&#xff08;利用定时器&#xff0c;每次触发先清掉以前的定时器&#xff0c;从新开始&#xff09; 节流&#xff1a;单位时间内&#xff0c;频繁触发事件&…

Yii2模板:自定义头部脚部文件,去掉头部脚部文件

一、yii安装完成之后&#xff0c;运行结果如下图二、如何自定义头部脚部文件呢0、默认展示1、在类里定义&#xff0c;在整个类中生效2、在方法中定义&#xff0c;在当前方法中生效3、home模板介绍三、去掉头部脚部文件1、控制 $layout 的值2、把action中的render改为renderPart…

前端对于深拷贝和浅拷贝的应用和思考

浅拷贝 浅拷贝 &#xff1a; 浅拷贝是指对基本类型的值拷贝&#xff0c;以及对对象类型的地址拷贝。它是将数据中所有的数据引用下来&#xff0c;依旧指向同一个存放地址&#xff0c;拷贝之后的数据修改之后&#xff0c;也会影响到原数据的中的对象数据。最简单直接的浅拷贝就…

java ssm集装箱码头TOS系统调度模块的设计与实现

由于历史和经济体制的原因&#xff0c;国内码头物流企业依然保持大而全的经营模式。企业自己建码头、场地、经营集装箱运输车辆。不过近几年来随着经济改革的进一步深入和竞争的激烈&#xff0c;一些大型的码头物流企业逐步打破以前的经营模式&#xff0c;其中最明显的特征就是…

利用机器学习(mediapipe)进行人脸468点的3D坐标检测--视频实时检测

上期文章,我们分享了人脸468点的3D坐标检测的图片检测代码实现过程,我们我们介绍一下如何在实时视频中,进行人脸468点的坐标检测。 import cv2 import mediapipe as mp mp_drawing = mp.solutions.drawing_utils mp_face_mesh = mp.solutions.face_mesh face_mesh = mp_fac…

ubuntu 驱动更新后导致无法进入界面

**问题描述&#xff1a; **安装新ubuntu系统后未禁止驱动更新导致无法进入登录界面。 解决办法&#xff1a; 首先在进入BIOS中&#xff0c;修改设置以进行命令行操作&#xff0c;然后卸载已有的系统驱动&#xff0c;最后安装新的驱动即可。 开机按F11进入启动菜单栏&#xf…

【JavaScript 逆向】安居客滑块逆向分析

声明本文章中所有内容仅供学习交流&#xff0c;相关链接做了脱敏处理&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01;案例目标验证码&#xff1a;aHR0cHM6Ly93d3cuYW5qdWtlLmNvbS9jYXB0Y2hhLXZlcmlmeS8/Y2FsbGJhY2s9c2hpZWxkJmZyb209YW50aXNwYW0以上均做了脱敏处…

如何准备大学生电子设计竞赛

大学生电子设计竞赛难度中上&#xff0c;一般有好几个类型题目可以选择&#xff0c;参赛者可以根据自己团队的能力、优势去选择合适自己的题目&#xff0c;灵活自主空间较大。参赛的同学们可以在暑假好好学习相关内容&#xff0c;把往年的题目拿来练练手。这个比赛含金量还是有…