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

介绍

  文章主要从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调用返回流程图接口,查看申请所在位置:
红色表示当前位置

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python2.7安装和添加环境变量

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、python的下载地址二、安装步骤1.双击安装包运行安装2.添加环境变量 三、验证是否安装成功总结 前言 最近要用到python,下载安装成功&#xff0c;添加环境变…

Java 数据结构 二叉树(二)红黑树

目录 数据结构图-树 简介 规则 旋转 重新着色 红黑树构建过程 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停下脚步&#xf…

华清远见嵌入式学习——春节作业——2.4日

作业要求&#xff1a; 编写程序实现二叉树的创建&#xff0c;三种遍历自己销毁 作业答案&#xff1a; 作业代码截图 作业代码效果图 作业代码 #include "myhead.h"// 定义二叉树节点结构体 struct Tree {int value; //编号(值)struct Tree* left; //左子树stru…

9隐藏登录用户(无需接触磁盘即可修改文件内容)_Linux_Rootkit.md

Xcellerator 密码学Linux其他逆向工程 文章目录 [Linux Rootkit 第 9 部分&#xff1a;隐藏登录用户&#xff08;无需接触磁盘即可修改文件内容&#xff09;](https://xcellerator.github.io/posts/linux_rootkits_09/)终端设备UTMP用户空间工具如何解析 UTMP&#xff1f;挂钩…

如何实现冻干机和产品全生命周期的验证和监测?

为什么冻干需要工艺优化和合规性 冻干是制药和生物技术产品的关键工艺&#xff0c;需要精确控制关键的温度和压力参数。通过遵守 GMP 和 FDA 合规性等监管准则&#xff0c;您可以生产出更高质量的产品&#xff0c;避免不必要的浪费&#xff0c;并缩短产品上市时间。 要想在冻干…

[linux] kolla-ansible 部署的openstack 修改mariadb默认端口号

kolla-ansible 部署前修改global.yml #freezer_database_backend: "mariadb" database_port: 9306 mariadb_port: 9306如果已经部署成功&#xff0c;直接修改配置文件里的端口号重启是没有用的&#xff0c;怀疑内部做了缓存&#xff0c;查看openstack 使用的memcach…

零基础学编程,从入门到精通,中文编程工具下载,时间选择构件用法

零基础学编程&#xff0c;从入门到精通&#xff0c;中文编程工具下载&#xff0c;时间选择构件用法 一、前言 编程工具下载及源码文件下载路径 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件…

Unity类银河恶魔城学习记录1-11 PlayerPrimaryAttack P38

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic…

基于spring boot实现邮箱发送和邮箱验证

目录 一、邮箱发送实现1. 开通邮箱服务2. 添加邮箱依赖3.添加配置4.添加邮箱通用类5. 测试类 二、邮箱验证实现1.添加依赖2. 添加配置3.添加controller4. 测试 项目地址: https://gitee.com/nssnail/springboot-email 一、邮箱发送实现 1. 开通邮箱服务 使用qq邮箱、163邮箱都…

《计算机网络简易速速上手小册》第10章:未来网络技术趋势(2024 最新版)

文章目录 10.1 边缘计算与网络设计 - 未来网络的速度与激情10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 实现边缘计算的实时视频分析准备工作Python 脚本示例 10.1.3 拓展案例1&#xff1a;智能交通系统Python 脚本示例 - 边缘计算设备上的交通流量分析 10.1.4 拓展…

vcruntime140_1.dll 文件缺失的解决方法,简单的修复方法分享

遇到 vcruntime140_1.dll 文件缺失是一种常见的问题&#xff0c;但无需过于担心&#xff0c;因为这类问题通常有多种解决办法。接下来&#xff0c;我会为大家详细介绍如何处理 vcruntime140_1.dll 文件缺失的情况&#xff0c;以及在解决过程中应该注意的重要事项。 一.vcrunti…

Python flask 模板详解

文章目录 1 概述1.1 模板简介1.2 templates 文件1.3 简单应用 2 模板语法2.1 for 循环2.2 if 判断 3 模板的继承3.1 格式要求3.2 实现示例3.3 复用父模板的内容&#xff1a;super 1 概述 1.1 模板简介 定义&#xff1a;定义好的 html 文件&#xff0c;用于快速开发 web 页面J…

04-OpenFeign-请求超时机制

基于 2021.0.1版本 具体有以下几种超时参数设置 以下仅限2021.0.1 以前的版本&#xff0c;高于该版本的spring cloud 已修复该问题 1、默认的超时时间 默认不生效 连接超时时间10秒、读超时时间60秒&#xff0c;源码在feign.Request.Options#Options()这个方法中 2、open…

在Linux中如何理解页表和进程地址

1、进程地址是进程读取资源的窗口 2、页表决定了进程真实拥有的资源情况 3、合理的对进程地址空间页表进行资源划分&#xff0c;就可以对进程的资源进行分类 这个过程应该如何去理解呢请看下面的图 我们知道程序被加载到进程中&#xff0c;会产生相应的PCB&#xff0c;并且…

【JavaScript 漫游】【006】数据类型 array

文章简介 本文为【JavaScript 漫游】专栏的第 006 篇文章&#xff0c;记录笔者在了解 JS 数据类型 array 中摘录的知识点。 数组的本质是对象属组的 length 属性for ... in 循环和数组的遍历数组的空位类数组对象 除了上述 5 个重要知识点&#xff0c;学习数组更为重要的是掌…

CSS transition(过渡效果)详解并附带示例

CSS过渡效果&#xff08;CSS transitions&#xff09;是一种在元素属性值发生变化时&#xff0c;通过指定过渡效果来实现平滑的动画效果的方法。通过定义起始状态和结束状态之间的过渡属性&#xff0c;可以使元素的变化更加流畅和可视化。 过渡效果的基本语法如下&#xff1a;…

使用潜在向量进行检测、屏蔽和重建以进行遮挡的面部表情识别

Latent-OFER: Detect, Mask, and Reconstruct with Latent Vectors for Occluded Facial Expression Recognition 一、创新点 &#xff08;1&#xff09;提出了一种与表情相关的特征提取器&#xff0c;它使用空间注意力为特定的面部特征分配更高的权重&#xff0c;从而使我们能…

前端开发中不同语言【react-i18next】

目录 查看并设置语言 单页面&#xff1a;html lang ​编辑 浏览器 自定义翻译&#xff1a;react-i18next 设置 模块&#xff1a;staticData.ts 散(重复利用)&#xff1a;命名空间.json 应用 准备 html标签 查看并设置语言 单页面&#xff1a;html lang 英语: <…

RflySim | 定点位置控制器设计实验三

RflySim| 定点位置控制器设计实验三 01 分析实验 1.调节PD控制器的相关参数改善系统控制性能&#xff0c;并记录超调量和调节时间&#xff0c;得到满意的参数。 2.在得到满意参数后&#xff0c;对系统进行扫频以绘制Bod图&#xff0c;观察系统幅频响应、相频响应曲线&#xf…

【服务器】RAID(独立磁盘冗余阵列)

RAID&#xff08;独立磁盘冗余阵列&#xff09; 一、RAID的介绍二、RAID的分类#2-1 RAID 02-2 RAID 1#2-3 RAID 32-4 RAID 52-5 RAID 62-6 RAID 10(先做镜像&#xff0c;再做条带化)2-7 RAID 01&#xff08;先做条带&#xff0c;再做镜像&#xff09;2-8 RAID比较 三、磁盘阵列…