Flowable初体验

news2024/12/27 12:53:49

创建一个普通Maven项目

 目录结构

 

 一、依赖、配置

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>clowable_0811</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>clowable_0811</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--    flowable-->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-engine</artifactId>
            <version>6.8.0</version>
        </dependency>

        <!--    mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

        <!--    测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <!--    日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.36</version>
        </dependency>
    </dependencies>
</project>

log4j.properties

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

二、定义的流程

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:flowable="http://flowable.org/bpmn"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">

    <process id="holidayRequest" name="Holiday Request" isExecutable="true">

        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <userTask id="approveTask" name="同意或拒绝请假" flowable:assignee="zhangsan"/>
        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

        <exclusiveGateway id="decision"/>
        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${!approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>

        <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                     flowable:class="org.flowable.CallExternalSystemDelegate"/>
        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

        <userTask id="holidayApprovedTask" name="Holiday approved"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <serviceTask id="sendRejectionMail" name="Send out rejection email"
                     flowable:class="org.flowable.SendRejectionMail"/>
        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

        <endEvent id="approveEnd"/>

        <endEvent id="rejectEnd"/>

    </process>

</definitions>

三、流程操作

SendRejectionMail.java
package org.flowable;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class SendRejectionMail implements JavaDelegate {
    /**
     * flowable触发器
     *
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("拒绝了任务");
    }
}
package org.minos;

import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Unit test for simple App.
 */
public class AppTest {

    private ProcessEngineConfiguration configuration;

    /**
     * 获取流程引擎对象
     */
    @Test
    public void testProcessEngine() {
        //获取ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
        //配置相关数据库的连接信息
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC");
        //如果书库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        //通过ProcessEngineConfiguration构建ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
    }

    ProcessEngineConfiguration configurati = null;

    @Before
    public void before() {
        //获取ProcessEngineConfiguration对象
        configuration = new StandaloneProcessEngineConfiguration();
        //配置相关数据库的连接信息
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC");
        configuration.setActivityFontName("宋体");
        configuration.setLabelFontName("宋体");
        configuration.setAnnotationFontName("宋体");
        //如果书库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    }

    /**
     * 流程部署
     */
    @Test
    public void testDeploy() {
        //1.获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3.完成流程部署操作
        Deployment deployed = repositoryService.createDeployment()
                .addClasspathResource("demo.bpmn20.xml")
                .name("请假流程")
                .deploy();

        System.out.println("deployed.getId()=" + deployed.getId());

        System.out.println("deployed.getName()=" + deployed.getName());
    }

    /**
     * 查询流程定义信息
     */
    @Test
    public void testDeployQuery() {
        ProcessEngine processEngine = configuration.buildProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId("1")
                .singleResult();

        System.out.println("processDefinition.getId() = " + processDefinition.getId());
        System.out.println("processDefinition.getName() = " + processDefinition.getName());
        System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());
    }

    /**
     * 删除部署流程
     */
    @Test
    public void testDeleteDeploy() {
        ProcessEngine processEngine = configuration.buildProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();
        //删除部署ID为1的流程,如果已经启动,删除失败
        //repositoryService.deleteDeployment("1");
        //删除部署ID为1的流程,如果已经启动,启动实例也删除
        repositoryService.deleteDeployment("2501", true);
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testRunProcess() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //构建流程变量
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("employee", "zhangsan");
        variables.put("nrOfHolidays", 3);
        variables.put("desciption", "work hard");
        //启动流程实例
        ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables);

        System.out.println("holidayRequest.getProcessDefinitionId() = " + holidayRequest.getProcessDefinitionId());
        System.out.println("holidayRequest.getActivityId() = " + holidayRequest.getActivityId());
        System.out.println("holidayRequest.getId() = " + holidayRequest.getId());
    }

    /**
     * 查询任务
     */
    @Test
    public void testQueryProcess() {
        ProcessEngine processEngine = configuration.buildProcessEngine();

        TaskService taskService = processEngine.getTaskService();

        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest")//指定查询的流程key
                .taskAssignee("zhangsan")//查询任务的处理人
                .list();

        for (Task task : list) {
            System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());
            System.out.println("task.getName() = " + task.getName());
            System.out.println("task.getAssignee() = " + task.getAssignee());
            System.out.println("task.getDescription() = " + task.getDescription());
            System.out.println("task.getId() = " + task.getId());
        }
    }

    /**
     * 完成当前任务
     */

    @Test
    public void testCompleteTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();

        TaskService taskService = processEngine.getTaskService();

        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest")
                .taskAssignee("zhangsan")
                .list();
        //创建流程变量
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("approved", false);
        for (Task task : list) {
            taskService.complete(task.getId(), variables);
        }
    }

    /**
     * 获取流程任务的历史数据
     */
    @Test
    public void testHistroy() {
        ProcessEngine processEngine = configuration.buildProcessEngine();

        HistoryService historyService = processEngine.getHistoryService();

        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId("holidayRequest:1:7503")
                .finished() //查询的历史记录的状态已完成
                .orderByHistoricActivityInstanceEndTime().asc() //指定排序字段和顺序
                .list();
        for (HistoricActivityInstance item : list) {
            System.out.print("item.getActivityName() = " + item.getActivityName());
            System.out.print("item.getAssignee() = " + item.getAssignee());
            System.out.print("item.getActivityId() = " + item.getActivityId());
            System.out.println("item.getDurationInMillis() = " + item.getDurationInMillis() + "毫秒");
        }
    }

}

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

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

相关文章

动力节点|深入浅出Vue框架学习教程,带你快速掌握前端开发核心技能

Vue是一款流行的JavaScript前端框架&#xff0c;最初由华人开发者尤雨溪创建&#xff0c;并在GitHub上开源发布&#xff0c;它采用MVVM模型的设计思维&#xff0c;专注于UI项目的开发&#xff0c;能够方便地组织和管理页面上的各个组件&#xff0c;大大提高了前端开发的效率。 …

基于Java+SpringBoot+vue前后端分离卓越导师双选系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

通讯协议039——全网独有的OPC HDA知识一之聚合(七)实际时间最大值

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…

Win10使用Guest和空密码访问共享的完整步骤

目录 前言 启动Guest 给予Guest网络权限 允许空密码登陆 启用不安全的来并登陆 总结 前言 我们经常需要使用空密码和guest账户访问Windows共享&#xff0c;因为某些设备不支持输入密码等&#xff0c;那么该如何设置呢&#xff0c;因为步骤比较固定而且繁琐&#xff0c;于…

IDEA常用设置与maven项目部署

目录 前言 一、Idea是什么 二、Idea的优点 三、Idea的常用设置 主题设置 设置鼠标悬浮提示 忽略大小写提示 自动导包 取消单行显示Tabs 设置字体 配置类文档注释信息模版 设置文件编码 设置自动编译 水平或者垂直显示代码 快捷方式改成eclipse 设置默认浏览器…

世微 AP5160 DC-DC降压恒流IC 大功率LED电源手电筒车灯驱动芯片 SOT23-6

产品描述 AP5160 是一款效率高&#xff0c;稳定可靠的 LED 灯恒流驱动芯片&#xff0c;内置高精度比较器&#xff0c;固定关断时 间控制电路&#xff0c;恒流驱动电路等&#xff0c;特别适合大功率 LED 恒流驱动。 AP5160 采用SOT23-6 封装&#xff0c;通过调节外置电流检测电…

电脑运行慢怎么办?四招教你优化速度

电脑运行慢怎么办&#xff1f;电脑运行缓慢是很多人常遇到的问题&#xff0c;而其中一个主要原因是电脑内堆积了过多的垃圾文件。因此&#xff0c;定期清理电脑垃圾是保持电脑流畅运行的重要步骤。 本文将介绍四种有效的方法&#xff0c;帮助你清理电脑垃圾&#xff0c;让电脑…

如何从cpu改为gpu,pytorch,cuda

1.cmd输入nvcc -V 2.得到 cuda版本后&#xff0c;去pytorch官网 3.根据自己的cuda进行选择 4.复制上述链接&#xff0c;进入cmd 5.cmd中输入activate XXX,这里的"XXX"指代自己在工程中用到的环境 6.进入后&#xff0c;将刚才链接粘贴&#xff0c;回车等待下载结束 …

java 解析p12证书 (获取公钥、私钥、序列号)

1. p12文件放在resources目录下 2. P12InfoVo import lombok.Builder; import lombok.Data;import java.io.Serializable; import java.security.PrivateKey; import java.security.PublicKey;/*** p12证书VO*/ Data Builder public class P12InfoVo implements Serializable{/…

最强自动化测试框架Playwright(17)- 模拟接口

模拟接口 介绍 Web API 通常作为 HTTP 终结点实现。Playwright提供了API来模拟和修改网络流量&#xff0c;包括HTTP和HTTPS。页面所做的任何请求&#xff0c;包括 XHR 和获取请求&#xff0c;都可以被跟踪、修改和模拟。使用Playwright&#xff0c;您还可以使用包含页面发出的…

生信豆芽菜-单基因与HRD评分的关系

网址&#xff1a;http://www.sxdyc.com/panCancerHRDScore 该工具主要用于查看单基因在泛癌中与HRD评分的相关性 提交后等待运行成功即可

Qt4/5升级到Qt6吐血经验总结V202308

00&#xff1a;直观总结 增加了很多轮子&#xff0c;同时原有模块拆分的也更细致&#xff0c;估计为了方便拓展个管理。把一些过度封装的东西移除了&#xff08;比如同样的功能有多个函数&#xff09;&#xff0c;保证了只有一个函数执行该功能。把一些Qt5中兼容Qt4的方法废弃…

IDEA项目实践——JavaWeb简介以及Servlet编程实战

系列文章目录 IDEA项目实践——创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介 IDEWA项目实践——mybatis的一些基本原理以及案例 IDEA项目实践——动态SQL、关系映射、注解开发 IDEA项目实践——Spring框架简介,以及IOC注解 IDEA项目实践——Spring当…

利用ViewModel和LiveData进行数据管理

利用ViewModel和LiveData进行数据管理 1. 引言 在当今移动应用开发的世界中&#xff0c;数据管理是一个至关重要的方面。随着应用的复杂性不断增加&#xff0c;需要有效地管理和维护应用中的数据。无论是从服务器获取数据、本地数据库存储还是用户界面的状态&#xff0c;数据…

Python方式实现射后不管导弹的简易制导系统

1 问题 对QN-506上的S570智能反坦克制导导弹的射后不管产生了浓厚的兴趣&#xff0c;想用Python简易还原一下。 2 方法 之前查阅资料时了解到使用pygame库制作的贪吃蛇&#xff0c;是否有一种方法能让“贪吃蛇”一直跟着鼠标走呢&#xff1f;鼠标模拟行进中的坦克&#xff0c;“…

劝你入行嵌入式的五个理由

嵌入式技术作为一个备受瞩目的领域&#xff0c;已经吸引了越来越多的人才。如果您还在考虑是否要进入该领域&#xff0c;我建议您听听以下五个理由&#xff1a; 一、市场需求旺盛 随着科技的迅猛发展&#xff0c;嵌入式系统已经广泛渗透到我们生活的各个方面。从智能家居到智能…

rabbitmq的持久化

目录 队列实现持久化 如何删除队列​编辑 消息实现持久化 不公平分发 如何保障当 RabbitMQ 服务停掉以后消息生产者发送过来的消息不丢失。默认情况下 RabbitMQ 退出或由于某种原因崩溃时&#xff0c;它忽视队列和消息&#xff0c;除非告知它不要这样做。确保消息不会丢失需…

浅析前端请求登录与后台对接

首先确保前后端接口参数一致&#xff0c;我这里使用的是ant design Pro 前端框架 小技&#xff1a;shiftf6&#xff0c;全局重构&#xff0c;当接口不一致时很方便 前&#xff1a; 后&#xff1a; 前后端交互&#xff1a;前端需要向后端发送请求&#xff0c;前端ajax来请求后…

Ubuntu虚拟机增加交换内存

接下来增加交换内存。配置交换内存&#xff0c;需要用户根据自己的实际情况进行配置。这里举例分配 5G 交换内存。 在开始之前&#xff0c;使用命令检查一下您的 ubuntu 的 swap 分区&#xff0c;可以看到交换分区为 2G &#xff0c;如下图所示&#xff1a; sudo swapon …

【ChatGPT 指令大全】怎么使用ChatGPT来辅助知识学习

目录 概念解说 简易教学 深度教学 教学与测验 解释一个主题的背后原理 总结 在当今信息时代&#xff0c;互联网的快速发展为我们获取知识提供了前所未有的便利。而其中&#xff0c;人工智能技术的应用也为我们的学习和交流带来了新的可能性。作为一种基于自然语言处理的人…