SpringBoot整合Flowable最新教程(二)启动流程

news2024/9/8 23:11:18
介绍

  文章主要从SpringBoot整合Flowable讲起,关于Flowable是什么?数据库表解读以及操作的Service请查看SpringBoot整合Flowable最新教程(一);
  其他说明:Springboot版本是2.6.13,java版本是1.8。如果你使用的是一些开源项目如:ruoyi里面已经集成了这些无须自己手动引入。
文章代码地址(包含bpmn文件):文章源码地址
   pom文件引入

<!-- https://mvnrepository.com/artifact/org.flowable/flowable-spring-boot-starter -->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.7.2</version>
</dependency>

<!--druid-->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.2.12</version>
</dependency>

<!--mysql驱动-->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>

  因为加入flowable后项目启动时要往数据库加入流程表,所以这里就直接把druid也加上,数据库也配置上。

server:
  port: 8099

spring:
  datasource:
    druid:
      url: jdbc:mysql://localhost:3306/spring_flowable?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
      username: root
      password: 1101165230
      driver-class-name: com.mysql.cj.jdbc.Driver
      # 初始化物理链接的个数
      initial-size: 5
      # 最大连接池数量
      max-active: 30
      # 最小 连接池数量
      min-idle: 5
      # 获取连接时最大等待时间,单位毫秒 timeout链接超时
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒  检测非核心链接的时间
      #既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-eviction-runs-millis: 60000
      # 连接保持空闲而不被驱逐的最小时间
      min-evictable-idle-time-millis: 30000
      # 用来检测连接是否有效的sql,要求是一个查询语句  8小时问题 8个小时没跟mysql通信mysql会主动关闭该链接
      validation-query: SELECT 1 FROM DUAL
      # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,
      # 如果空闲时间大于min-evictable-idle-time-millis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      test-on-borrow: false
      # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      test-on-return: false
      # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,
      # 比如说oracle。在mysql下建议关闭。不是mysql端,链接端,select * from student 查询缓存
      pool-prepared-statements: true
      # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
      max-pool-prepared-statement-per-connection-size: 50
      #调优相关:基本上任何一个项目的性能瓶颈 1.io 2.cpu计算量
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计
      filters: stat,wall
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录  慢查询:增删改查
      connection-properties: druid.stat.mergeSql=true;
      filter:
        stat:
          slow-sql-millis: 1
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true
      # druid连接池监控
      stat-view-servlet:
        login-username: admin
        login-password: 1101165230
      # 排除一些静态资源,以提高效率
      web-stat-filter:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
# flowable配置
flowable:
# 请在第一次启动时使用true,之后使用false
  database-schema-update: true
  #pg用户使用指定,mysql不用
#  database-schema: spring_flowable
  activity-font-name: "宋体"
  label-font-name: "宋体"
  annotation-font-name: "宋体"
  async-executor-activate: false

2、配置Mysql连接以及druid后,启动项目

  如果启动报错请看.act_ge_property‘ doesn‘t exist

3、接着开始部署我们的bpmn文件

  在线bpmn绘制地址:bpmn在线绘制
  文章配套xml文件在最上方,请在最上方点击staff-leave.bpmn20.xml下载资源
  1.下载好文件后,在我们的resources文件夹下创建一个processes文件夹(项目启动时候会自动加载该文件夹下的xml),并将xml文件放进去。
这里我创建的流程是一个员工休假申请,如图:
员工休假申请流程
流程非常简单主要是为了让大家熟悉如何启动流程。(因为是1.0版本所以我并没有控制网关节点流向控制值,所以加入项目启动后会有一个提示说这个网关没有配置值)

4、业务与代码讲解

  整个业务流程也非常简单就是员工填写休假申请,我们就开启流程。由于我们只讲解启动的流程,所以大家不用纠结每个业务所在节点的状态。
  题外话:就拿一级审批节点来说,我启动流程后进入一级审批,这个时候的状态应该是什么?应该是一个待审核状态,只有等审核人员审核后才会变成已审核,已审核后经过网关是进入二级审批还是修改信息节点就看审核人的具体操作。其实也有特别简单的理解,就是将整个业务和流程进行一个拆分,将流程中的状态变更提取成一张表,我觉得大家就更好理解。后续我可能会出一个视频去讲解。

4.1创建factory文件夹,创建一个WorkflowService将flowable的服务类全部放进去进行统一管理

import org.flowable.engine.*;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description flowable 工作流服务类
 * @date 2024/2/4 10:13
 */
public class WorkflowService {

    /**
     * 流程引擎
     */
    @Autowired
    public ProcessEngine processEngine;

    /**
     * 流程仓库服务类
     */
    @Autowired
    public RepositoryService repositoryService;

    /**
     * 查询运行信息
     */
    @Autowired
    public RuntimeService runtimeService;

    /**
     * 查询任务信息
     */
    @Autowired
    public TaskService taskService;

    /**
     * 查询历史信息
     */
    @Autowired
    public HistoryService historyService;

}
4.2接着我们还是按照标准开发流程创建Service、实体类这些步骤

请假表单实体类:

import lombok.*;

import java.io.Serializable;
import java.util.Date;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description 申请信息入参
 * @date 2024/2/4 10:21
 */
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ApproveInfoBO implements Serializable {

    private String name;

    private Date startTime;

    private Date endTime;

    private String remarks;

}

创建service

import com.sg.flowable.entity.ApproveInfoBO;

import javax.servlet.http.HttpServletResponse;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description IStaffLeaveApproveService
 * @date 2024/2/4 10:10
 */
public interface IStaffLeaveApproveService{

    /**
     * 休假申请
     */
    String approve(ApproveInfoBO approveInfoBO);

    /**
     * 获取流程图
     * @param httpServletResponse
     * @param processId
     */
    void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception;

}

创建实现类


import com.sg.flowable.entity.ApproveInfoBO;
import com.sg.flowable.factory.WorkflowService;
import com.sg.flowable.service.IStaffLeaveApproveService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.ProcessEngineConfiguration;
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.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.List;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description StaffLeaveApproveServiceImpl
 * @date 2024/2/4 10:10
 */
@Service
public class StaffLeaveApproveServiceImpl extends WorkflowService implements IStaffLeaveApproveService {

    @Override
    public String approve(ApproveInfoBO approveInfoBO){
        //数据的id(假设这是申请数据的id)
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        //放入流程中的数据
        Map<String, Object> variables = new HashMap<>();
        variables.put("status", 1);
        variables.put("data", approveInfoBO);
        //启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("staff_leave", id, variables);
        String processInstanceId = processInstance.getId();
        System.out.println("流程启动id是:"+processInstanceId);
        return id;
    }

    /**
     * 返回流程图
     * @param httpServletResponse
     * @param processId
     */
    @Override
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0,true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

}

创建Controller

import com.sg.flowable.entity.ApproveInfoBO;
import com.sg.flowable.service.IStaffLeaveApproveService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
 * @author by Guoshun
 * @version 1.0.0
 * @description StaffLeaveApproveController
 * @date 2024/2/4 10:06
 */
@RestController
@RequestMapping("/staff_leave")
public class StaffLeaveApproveController {

    @Resource
    private IStaffLeaveApproveService iStaffLeaveApproveService;

    /**
     * 休假申请
     */
    @PostMapping("/approve")
    public String approve(@RequestBody ApproveInfoBO approveInfoBO){
        return iStaffLeaveApproveService.approve(approveInfoBO);
    }

    /**
     * 返回流程图
     * @param httpServletResponse
     * @param processId
     * @throws Exception
     */
    @GetMapping("/genProcessDiagram/{processId}")
    public void genProcessDiagram(HttpServletResponse httpServletResponse,@PathVariable("processId") String processId) throws Exception {
        iStaffLeaveApproveService.genProcessDiagram(httpServletResponse, processId);
    }
}

测试调用
接口调用
输出实例id
使用控制台实例id调用返回流程图接口,查看申请所在位置:
红色表示当前位置

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

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

相关文章

4. 树(二叉树、二叉查找树/二叉排序树/二叉搜索树、平衡二叉树、平衡二叉B树/红黑树)

树 1. 二叉树1.1 概述1.2 特点1.3 二叉树遍历方式1.3.1 前序遍历(先序遍历)1.3.2 中序遍历1.3.3 后序遍历1.3.4 层序遍历 2. 二叉查找树&#xff08;二叉排序树、二叉搜索树&#xff09;2.1 概述2.2 特点 3. 平衡二叉树3.1 概述3.2 特点3.3 旋转3.3.1 左旋3.3.2 右旋 3.4 平衡二…

指针的学习2

目录 数组名的理解 使用指针访问数组 一维数组传参的本质 冒泡排序 二级指针 指针数组 指针数组模拟二维数组 数组名的理解 数组名是数组首元素的地址 例外&#xff1a; sizeof(数组名),sizeof中单独放数组名&#xff0c;这里的数组名表示整个数组&#xff0c;计算的…

EasyCVR智能视频监控平台云台降低延迟小tips

TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&…

彻底学会系列:一、机器学习之线性回归

1.基本概念 线性回归&#xff1a; 有监督学习的一种算法。主要关注多个因变量和一个目标变量之间的关系。 因变量&#xff1a; 影响目标变量的因素&#xff1a; X 1 , X 2 . . . X_1, X_2... X1​,X2​... &#xff0c;连续值或离散值。 目标变量&#xff1a; 需要预测的值: t…

智慧未来已至:人工智能与数字孪生共筑城市新纪元

随着科技的飞速发展&#xff0c;人工智能与数字孪生技术正逐步成为智慧城市建设的核心驱动力。 这两项技术的结合&#xff0c;不仅将彻底改变城市的传统面貌&#xff0c;更将引领我们走向一个更加高效、便捷、绿色的未来。 一、智慧城市的新内涵 智慧城市&#xff0c;是指在城…

DDoS攻击:分布式拒绝服务攻击的威胁与对策

DDoS攻击&#xff1a;分布式拒绝服务攻击的威胁与对策 随着互联网的快速发展&#xff0c;网络安全威胁也在不断增加。其中&#xff0c;分布式拒绝服务攻击&#xff08;DDoS&#xff09;是一种常见且具有破坏性的攻击方式&#xff0c;给个人用户、企业和组织的网络基础设施带来了…

爬虫工作量由小到大的思维转变---<第四十五章 Scrapyd 关于gerapy遇到问题>

前言: 本章主要是解决一些gerapy遇到的问题,会持续更新这篇! 正文: 问题1: 1400 - build.py - gerapy.server.core.build - 78 - build - error occurred (1, [E:\\项目文件名\\venv\\Scripts\\python.exe, setup.py, clean, -a, bdist_uberegg, -d, C:\\Users\\Administrat…

React进阶 - 15(React 中 ref 的使用)

本章内容 目录 一、e.target 获取事件对应“元素”的DOM节点二、ref三、ref 和 setState 合用 上一节我们了解了 React中的”虚拟DOM“中的”Diff算法““ &#xff0c;本节我们来说一说 React中 ref的使用 一、e.target 获取事件对应“元素”的DOM节点 打开之前工程中的 To…

elasticsearch重置密码操作

安装es的时候需要测试这个url&#xff1a;http://127.0.0.1:9200/ 出现弹窗让我输入账号和密码。我第一次登录&#xff0c;没有设置过账号和密码&#xff0c; 解决方法是&#xff1a;在es的bin目录下打开cmd窗口&#xff0c;敲命令&#xff1a;.\elasticsearch-reset-password…

给mysql设置时区

每次重启MySQL服务器后&#xff0c;使用IDEA的database navigator连接都会出现这种情况 解决方式就是 命令行登录后 set global time_zone 8:00;嘿嘿把之前自家简书文章 给mysql设置时区 搬运过来了&#xff0c;方便查阅

Zookeeper相关面试准备问题

Zookeeper介绍 Zookeeper从设计模式角度来理解&#xff0c;是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它负责存储和管理大家都关心的数据&#xff0c;然后接受观察者的注册&#xff0c;一旦这些数据的状态发生了变化&#xff0c;Zookeeper就负责通知已经在Zoo…

【lesson37】自己设计用户级缓冲区

文章目录 自己设计用户级缓冲区简易MyFILE_的结构fopen_的实现fputs_的实现fclose_的实现fflush_的实现 完整版代码 自己设计用户级缓冲区 因为用户缓冲区在FILE中&#xff0c;所以我们直接模仿C语言提供的文件操作接口&#xff0c;顺便实现缓冲区。 使用文件系统的框架&#…

C++ 图(三十八)【第四篇】

接下来&#xff0c;我们先学习一个概念&#xff0c;带有权值的图&#xff0c;其实就是每条边上有一个自己独立的值了&#xff0c;接下来我们来进行一个深入的了解吧。 1.带权值得的图的概念 在前面的课程中&#xff0c;图中的边都只是用来表示两个点之间是否存在关系&#xff…

SQL注入其他方法

此次实验因为环境问题很多无法复现&#xff0c;在此只讨论过程和方法 一、SQL注入之outfile注入 mysql的outfile的作用是导出文件&#xff0c;使用此方法的必要条件&#xff1a;&#xff08;此方法成功率极低&#xff09; 1、知道目标网站的物理路径&#xff1b; 2、%secur…

Python算法题集_螺旋矩阵

Python算法题集_螺旋矩阵 题目54&#xff1a;螺旋矩阵1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【检测4个方向】2) 改进版一【检测2个方向】3) 改进版二【可读性改进】 4. 最优算法 题目54&#xff1a;螺旋矩阵 本文为Python算法题集之一…

《Pandas 简易速速上手小册》第9章:Pandas 数据可视化(2024 最新版)

文章目录 9.1 Pandas 内置可视化工具9.1.1 基础知识9.1.2 重点案例&#xff1a;销售数据分析9.1.3 拓展案例一&#xff1a;产品评价统计9.1.4 拓展案例二&#xff1a;员工满意度分布 9.2 与 Matplotlib 和 Seaborn 集成9.2.1 基础知识9.2.2 重点案例&#xff1a;销售趋势分析9.…

「递归算法」:验证二叉搜索树

一、题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff…

vulhub中Apache APISIX 默认密钥漏洞复现(CVE-2020-13945)

Apache APISIX是一个高性能API网关。在用户未指定管理员Token或使用了默认配置文件的情况下&#xff0c;Apache APISIX将使用默认的管理员Token edd1c9f034335f136f87ad84b625c8f1&#xff0c;攻击者利用这个Token可以访问到管理员接口&#xff0c;进而通过script参数来插入任意…

110.乐理基础-五线谱-五线谱的速度

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;五线谱的附点、休止符、连线、延音线-CSDN博客 上一个内容里练习的答案&#xff1a; 五线谱里的情绪与速度也是跟简谱里一样&#xff0c;详情看&#xff1a;音乐的速度 专栏里的内容&#xff0c;根据创建时间&…

CNN应用Keras Tuner寻找最佳Hidden Layers层数和神经元数量

介绍&#xff1a; Keras Tuner是一种用于优化Keras模型超参数的开源Python库。它允许您通过自动化搜索算法来寻找最佳的超参数组合&#xff0c;以提高模型的性能。Keras Tuner提供了一系列内置的超参数搜索算法&#xff0c;如随机搜索、网格搜索、贝叶斯优化等。它还支持自定义…