Flowable的基本使用 (4常用BPMN图配置)

2023-11-05

Flowable的基本使用 (4常用BPMN图配置)

上面几篇博客我们已经介绍了BPMN是什么,有什么节点,节点直接的关系与作用,这一篇我们画几个标准一些的BPMN图

一字长蛇阵

流程只要审核了就到下个节点,不审核就一直卡住.节点都配置了权限信息,只要对应的负责人才可以审核

image-20211014153042747

给两个审批节点都加一个审批组,一个是[“departmentLeader”],一个是[“companyLeader”]

<?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:flowable="http://flowable.org/bpmn" 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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
  <process id="一字长蛇" name="一字长蛇" isExecutable="true">
    <documentation>一字长蛇</documentation>
    <startEvent id="startEvent1" name="审核开始"></startEvent>
    <userTask id="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" name="部门领导审批" flowable:candidateGroups="departmentLeader"></userTask>
    <userTask id="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" name="公司领导审批" flowable:candidateGroups="companyLeader"></userTask>
    <endEvent id="sid-4D46B174-E45F-4630-992F-518587C63AB5" name="审核结束"></endEvent>
    <sequenceFlow id="sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9" sourceRef="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" targetRef="sid-4D46B174-E45F-4630-992F-518587C63AB5"></sequenceFlow>
    <sequenceFlow id="sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B" sourceRef="startEvent1" targetRef="sid-038663FF-F468-4636-A8E2-21C191CDC8B3"></sequenceFlow>
    <sequenceFlow id="sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF" sourceRef="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" targetRef="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_一字长蛇">
    <bpmndi:BPMNPlane bpmnElement="一字长蛇" id="BPMNPlane_一字长蛇">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="410.0" y="75.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-038663FF-F468-4636-A8E2-21C191CDC8B3" id="BPMNShape_sid-038663FF-F468-4636-A8E2-21C191CDC8B3">
        <omgdc:Bounds height="80.0" width="100.0" x="375.0" y="180.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-35F42996-FBBD-4046-A5FF-5099A6D467D0" id="BPMNShape_sid-35F42996-FBBD-4046-A5FF-5099A6D467D0">
        <omgdc:Bounds height="80.0" width="100.0" x="375.0" y="322.31403942536787"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-4D46B174-E45F-4630-992F-518587C63AB5" id="BPMNShape_sid-4D46B174-E45F-4630-992F-518587C63AB5">
        <omgdc:Bounds height="28.0" width="28.0" x="411.0" y="458.6776714899466"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B" id="BPMNEdge_sid-C3FF5785-C23B-4D70-83AA-552906AA4F1B">
        <omgdi:waypoint x="425.0" y="104.94999891876283"></omgdi:waypoint>
        <omgdi:waypoint x="425.0" y="180.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9" id="BPMNEdge_sid-21E83EF7-CF4E-4A7D-A1F9-D76D13DABCE9">
        <omgdi:waypoint x="425.0" y="402.26403942536786"></omgdi:waypoint>
        <omgdi:waypoint x="425.0" y="458.6776714899466"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF" id="BPMNEdge_sid-2C2FC1F8-A2F5-454A-8E47-18438C99EBDF">
        <omgdi:waypoint x="425.0" y="259.95000000000005"></omgdi:waypoint>
        <omgdi:waypoint x="425.0" y="322.31403942536787"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

演示

因为是demo,没有做登录注册,所以用最简单的方式了,公司和角色都是用静态变量代替

image-20211014164328504

设置公司和角色,默认996,role为employee

<select id="setRole">
    <option value="employee">普通员工</option>
    <option value="departmentLeader">部门领导</option>
    <option value="companyLeader">公司领导</option>
</select>
private static  String role = "employee";

private static String companyName = "996";

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("setCompanyName")
public ResultData<String> setCompanyName(String companyName) {
  FlowableController.companyName = companyName;
  return ResultData.ofSuccess();
}

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("setRole")
public ResultData<String> setRole(String role) {
  FlowableController.role = role;
  return ResultData.ofSuccess();
}

996公司,普通员工,发起了一个一字长蛇审批流程,方法返回success,流程的id是 2b8d81ab-2ccb-11ec-b622-f26c8efdde3a

image-20211014164626916

我们查看普通员工待审批的流程,可以看见是空的

image-20211014164958613

换成部门领导就有东西了

image-20211014165024894

传入taskId,进行审批操作,返回结果是成功

image-20211014165055841

再查看待办流程,可以看见是空的,因为流程已经审核过来,下一个节点是公司领导

image-20211014165153083

公司领导查看流程

image-20211014165235911

领导审核略…

领导审核结束,流程结束,我们通过最早之前生成的流程图返回的processInstanceId来查询流程

image-20211014165458922

条件判断

上面的流程比较简单,但是流程并不能砍掉,没人审核就卡住,也没有拒绝通过的说法,调用审核驳回和审核通过没有区别

我们看到拒绝和通过都是掉用complete方法,区别就是map的内容不一样,但是我们并没有用map的内容做一个条件过滤,所以两个接口效果一样

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/apply")
public ResultData<String> apply(@RequestParam String id) {
  //通过审核
  HashMap<String, Object> map = new HashMap<>();
  map.put("outcome", "通过");
  taskService.complete(id, map);
  return ResultData.ofSuccess();
}

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/reject")
public ResultData<String> reject(@RequestParam String id) {
  //拒绝审核
  HashMap<String, Object> map = new HashMap<>();
  map.put("outcome", "驳回");
  taskService.complete(id, map);
  return ResultData.ofSuccess();
}

接下来我们来整一个带条件分支的审批节点

如图所示的线节点添加表达式 {outcome}==‘通过’ 另一根线是驳回,为了方便展示审批节点名称,我改了一下
在这里插入图片描述

审批过程我跳过了,简单看一下,这个是接受996的

image-20211014185123614

这个不是不接受的,通过我们不同的选择,控制了流程的走向,这是一个非常简单的是非条件判断控制

image-20211014185541121

驳回

如图,假设部门领导审核和公司领导审核可以通过或者撤回

员工提交审核的时候默认就通过的,然后部门领导和公司领导的审核都可能会打回流程,直接打回到员工提交请假申请,让员工重新提交.

image-20211014190144447

图就不演示了
简单的说,只要一个审核打回去,我们就一朝回到解放前,只有都通过流程才能结束,非常常见的一个请假流程.钉钉上的请假流程基本也是这种方式

复杂流程

这里我使用一个项目中最复杂的流程图

  • 用户提交资料,交给财务和合规审核,可能有一个过程被打回,然后用户再重新提交
  • 财务和合规审核都通过的情况下,到领导回访,领导回访后面还有总部回访,都通过流程结束
  • 如果领导和总部回访打回,不会跑到梦开始的地方,而是跑到一个新的节点,用户有部分的信息可以重新提交修改,之前部分审核通过的数据就不能修改了

就给你们看看,flowable的上限可以多少高,你们也可以思考一下,项目中及其复杂的流程可以不可以用flowable来画出流程图

在这里插入图片描述

总结

  • BPMN的图非常灵活,甚至我们可以写出类似while,for循环的操作,BPMN可以满足业务中任何的流程
  • BPMN模型一般在部署的时候不会报错,只要格式不出问题都可以部署成功,但是运行的时候非常容易出问题,需要后端在前端上传流程图配置文件的时候进行足够的校验限制,避免流程部署的时候出错
  • 使用流程引擎来管理业务流程的时候,我们业务状态应该以流程引擎的状态为主,不要自己再加状态了.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flowable的基本使用 (4常用BPMN图配置) 的相关文章

  • Java - 因内存不足错误而关闭

    关于如何最好地处理这个问题 我听到了非常矛盾的事情 并且陷入了以下困境 OOME 会导致一个线程崩溃 但不会导致整个应用程序崩溃 我需要关闭整个应用程序 但不能 因为线程没有剩余内存 我一直认为最佳实践是让它们离开 这样 JVM 就会死掉
  • 如何使用Spring WebClient进行同步调用?

    Spring Framework in 休息模板 https docs spring io spring framework docs current javadoc api org springframework web client R
  • NoInitialContextException:heroku 战争部署

    我一直在开发一个 J2EE 项目 并且在其中使用连接池 也通过部署在 heroku 上的数据库进行访问 我使用以下代码来设置 Connection 对象 Context initContext new InitialContext Cont
  • 使用 WebDriver 单击新打开的选项卡中的链接

    有人可以在这种情况下帮助我吗 场景是 有一个网页 我仅在新选项卡中打开所有指定的链接 现在我尝试单击新打开的选项卡中的任何一个链接 在下面尝试过 但它仅单击主 第一个选项卡中的一个链接 而不是在新选项卡中 new Actions drive
  • Oracle Java 教程 - 回答问题时可能出现错误

    我是 Java 新手 正在阅读 Oracle 教程 每个部分之后都有问题和答案 我不明白一个答案中的一句话 见下面的粗体线 来源是https docs oracle com javase tutorial java javaOO QandE
  • 如何使用 JAVA 代码以编程方式捕获线程转储?

    我想通过 java 代码生成线程转储 我尝试使用 ThreadMXBean 为此 但我没有以正确的格式获得线程转储 因为我们正在使用jstack命令 请任何人提供一些帮助 他们是否有其他方式获取线程转储 使用任何其他 API 我想要的线程转
  • 如何将jscrollpane添加到jframe?

    我有以下源代码 有人可以给我建议如何将 jscrollpane 添加到 jframe 上吗 我尝试了几次将其添加到 jframe 但没有任何进展 它甚至没有显示 public class Form3 JFrame jframe new JF
  • Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?

    我创建了一个 RestController 如下所示 RestController public class GreetingController RequestMapping value greetings method RequestM
  • Android 中 localTime 和 localDate 的替代类有哪些? [复制]

    这个问题在这里已经有答案了 我想使用从 android API 获得的长值 该值将日期返回为长值 表示为自纪元以来的毫秒数 我需要使用像 isBefore plusDays isAfter 这样的方法 Cursor managedCurso
  • Spring数据中的本机查询连接

    我有课 Entity public class User Id Long id String name ManyToMany List
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • 如何使用正则表达式验证 1-99 范围?

    我需要验证一些用户输入 以确保输入的数字在 1 99 范围内 含 这些必须是整数 Integer 值 允许前面加 0 但可选 有效值 1 01 10 99 09 无效值 0 007 100 10 5 010 到目前为止 我已经制定了以下正则
  • 从直方图计算平均值和百分位数?

    我编写了一个计时器 可以测量任何多线程应用程序中特定代码的性能 在下面的计时器中 它还会在地图中填充花费了 x 毫秒的调用次数 我将使用这张图作为我的直方图的一部分来进行进一步的分析 例如调用花费了这么多毫秒的百分比等等 public st
  • 从休眠乐观锁定异常中恢复

    我有一个这样的方法 Transactional propagation Propagation REQUIRES NEW public void doSomeWork Entity entity dao loadEntity do some
  • 用于缓存的 Servlet 过滤器

    我正在创建一个用于缓存的 servlet 过滤器 这个想法是将响应主体缓存到memcached 响应正文由以下方式生成 结果是一个字符串 response getWriter print result 我的问题是 由于响应正文将不加修改地放
  • 如何从 Ant 启动聚合 jetty-server JAR?

    背景 免责声明 I have veryJava 经验很少 我们之前在 Ant 构建期间使用了 Jetty 6 的包装版本来处理按需静态内容 JS CSS 图像 HTML 因此我们可以使用 PhantomJS 针对 HTTP 托管环境运行单元
  • 源值 1.5 的错误已过时,将在未来版本中删除

    我使用 scala maven plugin 来编译包含 scala 和 java 代码的项目 我已经将源和目标设置为1 7 但不知道为什么maven仍然使用1 5 这是我在 pom xml 中的插件
  • 使用 JFreeChart 为两个系列设置不同的 y 轴

    我正在使用 JFreeChart 使用折线图绘制两个数据系列 XYSeries 复杂的因素是 其中一个数据系列的 y 值通常远高于第二个数据系列的 y 值 假设第一个系列的 y 值约为数百万数量级 而第二个数据系列的 y 值约为数百万数量级
  • 检查应用程序是否在 Android Market 上可用

    给定 Android 应用程序 ID 包名称 如何以编程方式检查该应用程序是否在 Android Market 上可用 例如 com rovio angrybirds 可用 而 com random app ibuilt 不可用 我计划从
  • 基于 Spring Boot 的测试中的上下文层次结构

    我的 Spring Boot 应用程序是这样启动的 new SpringApplicationBuilder sources ParentCtxConfig class child ChildFirstCtxConfig class sib

随机推荐

  • MyBatis查询时间格式转换yyyy-MM-dd HH:mm:ss

    MyBatis查询时间格式转换yyyy MM dd HH mm ss 一 通过配置model model private Date createTime JsonFormat pattern yyyy MM dd HH mm ss priv
  • 爬虫第六课:爬取携程酒店数据

    首先打开携程所有北京的酒店http hotels ctrip com hotel beijing1 简简单单 源代码中包含我们需要的酒店数据 你以为这样就结束了 携程的这些数据这么廉价地就给我们得到了 事实并不是如此 当我们点击第二页的时候
  • 怎么使用LINQ方法来比较自定义类型对象

    LINQ提供了方便的语法和很多操作对象集合的有用的方法 但是 要让LINQ比较方法如Distinct或Intersect能正确处理 类型必须要满足一些条件 让我们看看Distinct方法 它从集合中返回所有的不重复对象 List
  • 【我的面试-前端】以下是我在参加面试过程中被问到的问题以及答案

    JavaScript 数据类型 面试中经常被问到 JavaScript 数据类型都有哪些 有些时候面试者因为紧张连这最基础的题目都回答不出来或者回答不够全面 下面我们来具体了解下 JavaScript 数据类型吧 首先 需要答出 JavaS
  • 颜值超高的简单计算器(HTML+CSS+JS)

    先来看一下效果吧
  • k8s通过nfs-provisioner配置持久化存储

    一 nfs client provisioner简介 Kubernetes集群中NFS类型的存储没有内置 Provisioner 但是你可以在集群中为NFS配置外部Provisioner Nfs client provisioner是一个开
  • vue项目实现路由按需加载(路由懒加载)的3种方式

    vue项目实现按需加载的3种方式 转自 https segmentfault com a 1190000011519350 vue异步组件 es提案的import webpack的require ensure 1 vue异步组件技术 异步加
  • 修改本地host文件

    在有些时候可能因为访问一些网址的时候 可能因为浏览器对部分网站的签名不认可导致无法访问 根据浏览器不同 有时候可以选择高级选项允许访问 有时候只能停留在报错页 这时候可以通过设置本地的host文件 允许浏览器访问 首先我们找到目录C Win
  • VSCode HTML代码中怎么导入其他文件夹中的内容

    在标签下插入 link rel stylesheet href css xxx css 其中 css xxx css 为路径标签 意思是在一个叫做css的文件夹中有的一个叫xxx css的css样式文件
  • sqli-labs第二十六二十六a关

    这关油条加你的可以试试linux搭建sqlilabs这样比较简单 需要注意的 本关可能有的朋友在 windows 下无法使用一些特殊的字符代替空格 此处是因为 apache 的解析的问题 这里请更换到 linux 平台下 本关结合 25 关
  • 智能合约(一)————智能合约入门

    1 智能合约的基本组成 1 1 程序版本 1 2 合约声明 1 3 状态变量 1 4 合约方法 在这里constant相当于他声明这个局部变量不能更改 但是他并没有实际作用 实际就只是警示作用 2 地址adress address bala
  • GDB忽略SIGPWR和SIGCPU这两个信号

    用GDB 调试Java程序 陈皓 http blog csdn net haoel 背景 想要使用GDB调试程序 就需要用GNU的编译器编译程序 如 用GCC编译的C C 的程序 才能用GDB调试 对于Java程序也是一样的 如果想要用GD
  • 【嵌入式】7段数码管电路原理

    电路原理说明 中间的是F 小数点是G 上面的对应具体管 下面的代表各个大管 两两对应 上面4个为一个字节 有两个字节 下面直接为一个字节 要让某个数字亮起必须满足两个逻辑条件 对应的 LED SEL 必须为 0 低电频 代表对应笔画的 LE
  • 无符号整形和有符号整形的比较

    对无符号整形比较的错误认知 整形数据存储形式 进制的转换 原码 反码 补码 转换原理 代码演示 总结 整形数据存储形式 在计算机内存里 整数以补码形式存储 正数的补码即原码 进制的转换 原码 反码 补码 正数的原码 正数的反码 正数的补码
  • 从进程中操作WPF窗体的显示隐藏

    一 问题描述 如何在一个进程中 打开另一个进程中的wpf已经隐藏的窗体 二 解决方案 1 在WPF进程中 获取该窗体的句柄 并保存到某个文件 这个文件可以是内存映射文件 也可以是普通的xml文件 在WPF的MainWindow中 添加 pr
  • Manjaro 根据连接速度排序配置源地址

    一 引言 使用 Manjaro 已经有一段时间了 一开始按照某一篇博客手动配置了国内源 最近公司搬了新的办公室 发现升级系统时出现连接不到更新服务器的问题 sudo pacman Syu 一定是源访问出现了问题 那么怎么办呢 二 解决 通过
  • (Leetcode) 寻找数组的中心索引- Python实现

    题目 给定一个整数类型的数组 nums 请编写一个能够返回数组 中心索引 的方法 我们是这样定义数组中心索引的 数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和 如果数组不存在中心索引 那么我们应该返回 1 如果数组有多个中心索引
  • Vue项目优化——通过 externals 加载外部 CDN 资源

    1 发现项目中存在的问题 为了直观地发现项目中存在的问题 我们可以在打包时生成报告 我们可以通过VueCli可视化的UI面板运行bulid直接查看报告 而在报告中我们发现了有这么一个文件 体积比较大 这样可能会造成我们较长时间的请求 2 那
  • JAV学习Object类

    Obj类 首先我们要认识到 Object类是我们所有类的顶层父类 所有类都是直接或者间接的继承自他 我们可以将它new出来也就是格式 Object obj new Object 我们罗列出来objct类的常用方法然后再一一介绍 方法名 ob
  • Flowable的基本使用 (4常用BPMN图配置)

    Flowable的基本使用 4常用BPMN图配置 上面几篇博客我们已经介绍了BPMN是什么 有什么节点 节点直接的关系与作用 这一篇我们画几个标准一些的BPMN图 一字长蛇阵 流程只要审核了就到下个节点 不审核就一直卡住 节点都配置了权限信