当前位置: 首页 > news >正文

SpringBoot整合Flowable工作流引擎框架

Flowable工作流引擎框架介绍

  • 一个Java编写的轻量级业务流程引擎,为开发人员、系统管理员和业务用户提供工作流和业务流程管理(BPM)平台。
  • 不仅包括BPMN,还有DMN决策表和CMMN Case管理引擎,并且有自己的用户管理、微服务API等一系列功能,是一个服务平台。
  • 可用于部署BPMN 2.0流程定义,创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据。
  • Flowable源自Activiti,Flowable功能比activiti更强大,Flowable很多设计与实现,与Activiti相同的。

官方手册:Flowable BPMN 用户手册 (v 6.3.0)

设计流程图

  • 下载Flowable-ui:Flowable-ui 6.7.2下载
  • 下载Tomcat:tomcat 9 下载

把flowable-ui里面wars下的两个war包拷贝到tomcat的webapps文件夹中,然后启动tomcat

运行成功在浏览器输入 http://localhost:8080/flowable-ui/,进入flowable-ui界面

初始用户名admin,初始密码test

在此图形化界面设计流程图,可以导出为.bpmn20.xml文件

快速开始

导入依赖

<!--Flowable流程引擎框架-->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.3.0</version>
</dependency>

安装插件

在IDEA安装 Flowable BPMN visualizer 插件,可以把.bpmn20.xml文件可视化的展示。

配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
    
flowable:
  standalone:
    server:
      enabled: false # standalone 模式
  async-executor-activate: false # 关闭定时任务JOB
  idm:
    enabled: false # 检测身份信息
  database-schema-update: true # 没有数据库表的时候生成数据库表

flowable数据库必须存在(数据库名称任意),当flowable里面没有表的时候,项目运行会自动创建数据库。

配置类

import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
    @Override
    public void configure(SpringProcessEngineConfiguration engineConfiguration) {
        engineConfiguration.setActivityFontName("宋体");
        engineConfiguration.setLabelFontName("宋体");
        engineConfiguration.setAnnotationFontName("宋体");
    }
}

设计流程图

在flowable-ui进行流程设计

把流程图文件下载到本地,在resources目录下创建processes目录,在此目录下防止流程图文件

SpringBoot项目中processes目录下的流程图会自动部署。

人物

  • 发起流程人:多啦A
  • 组长:多啦B
  • 老板:多啦C
  • 经理:多啦D

controller

import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class BXController {
    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    /**
     * 创建流程实例
     */
    @GetMapping("/createInstance/{username}/{money}")
    public String createInstance(@PathVariable String username, @PathVariable Integer money) {
        // 创建流程要携带的参数
        Map<String, Object> variables = new HashMap<>();
        variables.put("people", username);// 报销申请人
        variables.put("reason", "出差");// 报销原因
        variables.put("money", money);// 报销金额
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("报销申请", variables);
        // 输出相关的流程实例信息
        System.out.println("流程实例的ID:" + processInstance.getId());// 流程实例的Id --> 5001
        System.out.println("流程创建成功");
        return username + "创建流程实例成功";
    }

    /**
     * 组长同意
     */
    @GetMapping("/agree/zz/{username}")
    public String completeTaskZZ(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("zzAgree", true);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "同意请假");
        return "组长同意";
    }

    /**
     * 经理同意
     */
    @GetMapping("/agree/jl/{username}")
    public String completeTaskJL(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("jlAgree", true);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "同意请假");
        return "经理同意";
    }

    /**
     * 老板同意
     */
    @GetMapping("/agree/lb/{username}")
    public String completeTask(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("lbAgree", true);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "同意请假");
        return "老板同意";
    }

    /**
     * 组长拒绝
     */
    @GetMapping("/reject/zz/{username}")
    public String rejectTask(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("zzAgree", false);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "拒绝请假");
        return "组长拒绝";
    }

    /**
     * 经理拒绝
     */
    @GetMapping("/reject/jl/{username}")
    public String rejectTaskJL(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("jlAgree", false);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "拒绝请假");
        return "经理拒绝";
    }

    /**
     * 老板拒绝
     */
    @GetMapping("/reject/lb/{username}")
    public String rejectTaskLB(@PathVariable String username) {
        List<Task> l = taskService.createTaskQuery()
                .processDefinitionKey("报销申请")
                .taskAssignee(username)
                .list();
        Task task = l.get(0);
        Map<String, Object> variable = new HashMap<>();
        variable.put("lbAgree", false);
        // 完成任务
        taskService.complete(task.getId(), variable);
        System.out.println(username + "拒绝请假");
        return "老板拒绝";
    }
}

测试

测试样例一

创建流程实例:http://localhost:8081/createInstance/多啦A梦/400,会返回流程实例ID

根据流程实例ID查询流程执行:http://localhost:8081/processDiagram/{processId}

注意:必须设置配置类设置字体,不然流程图上的文字会展示乱码

组长同意:http://localhost:8081/agree/zz/多啦B梦

经理拒绝:http://localhost:8081/reject/jl/多啦D梦 ,流程执行结束

测试样例二

创建流程实例:http://localhost:8081/createInstance/多啦A梦/700,会返回流程实例ID

组长同意:http://localhost:8081/agree/zz/多啦B梦

老板同意:http://localhost:8081/agree/lb/多啦C梦,流程结束

相关文章:

  • 七大排序之快速排序
  • vi vim 笔记心得2209010344
  • 忘记电脑密码的解决方法——使用pe工具重置电脑密码
  • 如何避免死锁呢?
  • Fedora36启用root,并且root直接通过ssh远程连接 2209010539
  • Slipped Conditions
  • 嵌套管程锁死
  • 图解LeetCode——1475. 商品折扣后的最终价格(难度:简单)
  • Java中的锁详解说明
  • GPIO相关介绍
  • 软件工程、软件生命周期、软件定义阶段、需求的层次/特征、概要设计、详细设计
  • 台式机电源更换笔记
  • 从文件资源管理器中隐藏文件
  • # Maven错误Error executing Maven
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • 5、React组件事件详解
  • Apache Pulsar 2.1 重磅发布
  • JavaWeb(学习笔记二)
  • Next.js之基础概念(二)
  • php面试题 汇集2
  • vue自定义指令实现v-tap插件
  • Xmanager 远程桌面 CentOS 7
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 机器学习 vs. 深度学习
  • 计算机在识别图像时“看到”了什么?
  • 微信开放平台全网发布【失败】的几点排查方法
  • 小程序button引导用户授权
  • FaaS 的简单实践
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​iOS安全加固方法及实现
  • #QT(智能家居界面-界面切换)
  • (1)(1.11) SiK Radio v2(一)
  • (1)Android开发优化---------UI优化
  • (a /b)*c的值
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (二)c52学习之旅-简单了解单片机
  • (分布式缓存)Redis分片集群
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转载)利用webkit抓取动态网页和链接
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • ??javascript里的变量问题
  • @ComponentScan比较
  • [ C++ ] STL---string类的模拟实现
  • [DevEpxress]GridControl 显示Gif动画
  • [ffmpeg] 定制滤波器
  • [Geek Challenge 2023] web题解
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)
  • [jQuery]div滚动条回到最底部