Flowable工作流引擎的使用3(task审批节点的接受与使用)

2023-11-06

BPMN task节点

节点介绍

image-20211014133529840

task节点是和业务最贴切的节点,表示一次审批

除了id,name,inComingFlows,outGoingFlows这些属性以外,还有一些权限信息.用于区分一个任务哪些人可以审核的

flowable自带一个ui配置界面,很多的数据库表设计都是和ui界面挂钩的,所以数据库会有很多我们不是很理解的字段,官方文档说明

public class UserTask extends Task {
    protected String assignee;
    protected String owner;
    protected String priority;
    protected String formKey;
    protected String dueDate;
    protected String businessCalendarName;
    protected String category;
    protected String extensionId;
    protected List<String> candidateUsers = new ArrayList<>();
    protected List<String> candidateGroups = new ArrayList<>();
    protected List<FormProperty> formProperties = new ArrayList<>();
    protected List<FlowableListener> taskListeners = new ArrayList<>();
    protected String skipExpression;
}

其中有很多属性,form表单,候选组候选人,待办人等等,非常多的概念

image-20211014134002205

实际项目中,我们肯定是走自己的权限系统,不会走flowable里的权限系统,所以,我们在配置BPMN的时候,可以使用一些取巧的方式.

flowable的这么多属性最终会保存到数据库中的,我们只需要将我们的业务id存储进来,然后不同的业务员通过自己的员工id,能够查询到待审批的流程即可.可以不用关心这些属性值在flowable究竟是什么意义,对我们而言就是一个塞业务id的一个列而已.

  • owner 表示流程的拥有者

  • candidateGroups 候选组, 当一个userTask节点同时存在owner和candidateGroups的时候,owner会变为空

  • assignee 表示任务受让人,当我们不指定的时候为空

  • skipExpression 表示跳过表达式,如果多级审批人都是同一个人,可以考虑跳过同一个人的下面几个审批,解决烦人的多次审核问题

借助owner和candidateGroups这两点,我们基本上可以完成我们审批人权限数据的填入了.

example

前端先获取机构人员id的下拉框,然后塞进流程引擎的candidateGroups里面,传给后端

image-20211014134320800

查询待办的时候,通过当前系统登录人员工id来查询即可

image-20211014134757616

  • 如果业务中,我们的一个节点只能是一个人审核,那么我们直接给owner赋值一个业务id即可

  • 如果可以是多个人进行审核,那么我们就把多个id权限字段存储到一个List’<‘String’>'里,然后传入candidateGroups里

  • 如果一个字段不够用,可以用 : 进行字符串拼接 , 比如 {公司id}:{部门id}:{员工id}

  • 如果我们的流程需要让另一个小哥进行审核,比如原员工跑路了,那么我们可以把这个受让人属性设置为新的审批人权限id

伪代码如下

List<String> auditors = new ArrayList<>();
//有代理人,代理人就是审批人
if(userTask.getAssignee() != null){
   auditors.add(userTask.getAssignee());
}
//没有代理人,但是候选组不为空,所有候选组的人都是待审核的人
if(CollectionUtils.isNotEmpty(userTask.getCandidateGroups()){
  auditors.addAll(userTask.getCandidateGroups());
}
else{
  //审批人只有一个人
  auditors.add(userTask.getOwner());
}

还有一种方式

image-20211014135158101

  • 如果觉得这样改flowable数据库表的用法不太好,我们可以跳出flowable,自己先创建一个权限关系表,绑定好flowable的流程,先通过权限关系表拿到这个人可以审核的流程的一些信息,再结合这些进行去查询流程,查询到的待审批的任务就是我们的当前登录人可以审批的任务节点了

  • 流程引擎的这些权限主要还是针对于查询,实际上我们调用推动流程的方法时,流程引擎并不会去校验权限,只要有taskId,processsId调用推动流程API即可,所以对于非Sass系统,非权限系统,仅限于一个简单的流程配置给一个系统使用,userTask的这些owner,assignee,candidateGroups这些属性都可以为空.那么我们查询流程都通过流程id来查询即可

介绍完userTask的一些属性,我们结合例子来说明一下,如何在实际项目开发中使用到这些属性

BPMN配置userTask节点

这里用官方的绘图工具,下载以及启动可以参考这一篇博客链接

先绘制一个最简单的流程

image-20211014104446442

给流程设置审批组

image-20211014110328192

身份存储需要先从flowable的权限系统注册一个审批人信息,太重了.

我们这边直接使用固定值的形式,添加两个候选人名字的字符串

image-20211014110047034

添加好了保存,然后导出bpmn20.xml文件,该编辑器详细界面参考这篇博文链接

image-20211014111120111

得到bpmn图,这里id和name属性都会自动生成

<?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="key" name="demo" isExecutable="true">
    <documentation>demo</documentation>
    <!-- 开始节点	-->
    <startEvent id="startEvent1" flowable:initiator="sponsor" flowable:formFieldValidation="true"></startEvent>
    <!-- 第一个审核节点 有jakt和jack两个候选人	-->
    <userTask id="sid-AD4D3CCF-4705-4F03-A381-269C354AB992" flowable:candidateGroups="jakt,jack" flowable:formFieldValidation="true"></userTask>
    <userTask id="sid-3FBBAF8C-F882-49B8-9723-3A3D163B6E8B" flowable:formFieldValidation="true"></userTask>
    <endEvent id="sid-F95597D2-838C-46BD-95D2-4CD0C7B41A17"></endEvent>
    <sequenceFlow id="sid-1D4DE32E-2FE6-4E4B-A95F-82265E6893B1" sourceRef="startEvent1" targetRef="sid-AD4D3CCF-4705-4F03-A381-269C354AB992"></sequenceFlow>
    <sequenceFlow id="sid-5FF980E1-87E8-4F72-A5B6-6D549367C797" sourceRef="sid-3FBBAF8C-F882-49B8-9723-3A3D163B6E8B" targetRef="sid-F95597D2-838C-46BD-95D2-4CD0C7B41A17" skipExpression="{outcome}=='通过'"></sequenceFlow>
    <sequenceFlow id="sid-295254FA-B051-423E-B3EE-091421844E7B" sourceRef="sid-AD4D3CCF-4705-4F03-A381-269C354AB992" targetRef="sid-3FBBAF8C-F882-49B8-9723-3A3D163B6E8B" skipExpression="{outcome}=='通过'"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_key">
    <bpmndi:BPMNPlane bpmnElement="key" id="BPMNPlane_key">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="90.0" y="175.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-AD4D3CCF-4705-4F03-A381-269C354AB992" id="BPMNShape_sid-AD4D3CCF-4705-4F03-A381-269C354AB992">
        <omgdc:Bounds height="80.0" width="100.0" x="300.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-3FBBAF8C-F882-49B8-9723-3A3D163B6E8B" id="BPMNShape_sid-3FBBAF8C-F882-49B8-9723-3A3D163B6E8B">
        <omgdc:Bounds height="80.0" width="100.0" x="603.5" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-F95597D2-838C-46BD-95D2-4CD0C7B41A17" id="BPMNShape_sid-F95597D2-838C-46BD-95D2-4CD0C7B41A17">
        <omgdc:Bounds height="28.0" width="28.0" x="915.0" y="176.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-295254FA-B051-423E-B3EE-091421844E7B" id="BPMNEdge_sid-295254FA-B051-423E-B3EE-091421844E7B">
        <omgdi:waypoint x="399.95000000000005" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="603.4999999998836" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-1D4DE32E-2FE6-4E4B-A95F-82265E6893B1" id="BPMNEdge_sid-1D4DE32E-2FE6-4E4B-A95F-82265E6893B1">
        <omgdi:waypoint x="119.94999969544602" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="300.0" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-5FF980E1-87E8-4F72-A5B6-6D549367C797" id="BPMNEdge_sid-5FF980E1-87E8-4F72-A5B6-6D549367C797">
        <omgdi:waypoint x="703.4499999999911" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="915.0" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

我们将BPMN文件导入项目,然后再导出看看

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/loading")
public ResultData<String> loading() throws FileNotFoundException {
  //先部署流程模板
  Deployment deployment = repositoryService
    .createDeployment()
    .tenantId(companyName)
    .addInputStream("demo.bpmn20.xml", new FileInputStream(ResourceUtils.getFile("classpath:demo.bpmn20.xml")))
    .deploy();
//再查看流程对象
  ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
    .processDefinitionKey("key")
    .processDefinitionTenantId(companyName)
    .singleResult();
  BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
  System.out.println(bpmnModel);
  return ResultData.ofSuccess();
}

这里我偷懒了,直接打断点了,可以看到我们配置的信息都生效了

bpmnModel ==> processes ==> flowElementList ==> userTask ==> candidateGroups=> {‘jack’,‘jakt’}

image-20211014113401277

我们现在开启这个流程,然后再查询流程进度

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/createTaskByKey")
public ResultData<String> createTaskByKey(@RequestParam String id) {
  //设置发起人
  Authentication.setAuthenticatedUserId("jakt");
  ProcessInstance processInstance = runtimeService.startProcessInstanceByKeyAndTenantId(key, companyName);
  ResultData<String> stringResultData = ResultData.ofSuccess(processInstance.getId());
  Authentication.setAuthenticatedUserId(null);
  return stringResultData;
}

先不设置查询条件,直接全表查询

@CrossOrigin(origins = "*", maxAge = 3600)
@GetMapping("/queryAllTask")
public ResultData<String> queryAllTask(String id) {
  //全查再说
  System.out.println(taskService.createTaskQuery().list());
  return ResultData.ofSuccess();
}

我们目前有一个任务task,然后owner是空的,因为我们确实没设置

image-20211014114046162

接下里我们加个查询条件

jakt是属于候选人(jakt,jack)中的,我们加一个条件试试,确实拿到了

image-20211014114145055

我换一个查询条件,嗯没有数据了.

通过这candidateGroups字段,我们就可以实现最简单的数据权限了

image-20211014114156550

总结

  • 设置一个task节点的数据权限,然后我们结合我们业务系统的权限id来查询流程就可以实现审批人权限控制了
  • flowable的userTask对象的很多属性都是适配于其自带的模型的一些功能而定制的如果我们只是用flowable的后台API接口的话,可以稍加修改就可以适配我们现有的代码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flowable工作流引擎的使用3(task审批节点的接受与使用) 的相关文章

随机推荐

  • 专治机器学习面试:机器学习各个算法的优缺点!

    今天有朋友聊起来 机器学习算法繁多 各个算法有各个算法的特点 以及在不同场景下 不同算法模型能够发挥各自的优点 今天呢 我把常见的 常用的算法模型进行了一个大概的总结 包括其分支以及各分支的优缺点 涉及到的算法有 回归 正则化算法 集成算法
  • 关于驱动和设备的相关的注册表键的位置,和相关信息

    关于驱动和设备的相关的注册表键的位置 和相关信息 MSDN上有了 https msdn microsoft com en us library windows hardware ff549815 v vs 85 aspx 下面是大概翻译整理
  • kettle-记录集连接(可实现左、右、全、内连接)

    连接前需先排序 记录连接集控件设置 结果 以左连接为例 连接前的两个数据源 连接后
  • 如何让input框中的值不被用户修改

    1 最常用的disabled 被禁用的 input 元素 不可编辑 不可复制 不可选择 不能接收焦点 后台也不会接收到传值 设置后文字的颜色会变成灰色 EP disabled 属性无法与 一起使用 2 readonly unselectab
  • 20220722_使用Element UI写html页面

    Element官网component资源点击这里 结构图 element ui自行下载复制到一致路径 第一个html div div
  • AES加密,128-192-256,方案二

    与方案一对比 方案二要简洁很多 看代码 package com xiao aes util import java security NoSuchAlgorithmException import javax crypto Cipher i
  • 计算机视觉应用(二)疲劳识别

    疲劳识别一度是热门 在疲劳驾驶 疲劳加班熬夜 学生上课打瞌睡等方面都得到了应用 很多刚入门的AI学子是用把疲劳图像进行分类 和正常状态做区分 这种分类方式往往会误检 这是由于这类属于细粒度分类 类外差距小 不打瞌睡和打瞌睡 类内差距大 不同
  • WIN10系统运行CE缺失hhctrl.ocx的解决方法

    高级版本的WIN10系统会缺少这个文件 网上只能找到32位 但是需要的却是64位的 这里直接提供2个版本 链接 https pan baidu com s 1DJ7U2wLqRreLKhafOFC8jA 提取码 xg7u
  • 一个启动U盘装多系统引导,无需反复格式化,ISO/WIM等文件拷贝到U盘即可启动

    想做一个可以有很多系统的启动U盘 把PE linux windows都装进去 系统启动U盘制作倒是非常简单 遍地是老毛桃 大白菜 U启通等工具 那么如何使用一个U盘装多个系统呢 找到一个非常好用的东西 使用Ventoy就无需反复地格式化U盘
  • 1 后端开发基础-Tomcat

    Tomcat 1 1 Web知识概述 Web 互联网总称 Java Web 是用Java技术来解决相关web互联网领域的技术总和 通俗的说 将编写好的代码 发布到互联网 可以让所有用户都访问到 1 1 1 软件架构 网络中有很多的计算机 它
  • python怎么读取txt文件并统计其字数-python文件读取失败怎么处理

    在读取文件时候比如读取 xxx csv 时候 可能报编码错误 类似于 xxx codec can t decode byte 0xac in position 211 illegal multibyte sequen id list wit
  • python实现火车票查询_Python 实现火车票查询工具

    一 实验简介 本课程使用 Python3 抓取 12306 网站信息提供一个命令行的火车票查询工具 通过该项目的实现 可以熟悉 Python3 基础及网络编程 以及 docopt requests prettytable 等库的使用 课程教
  • Spark 将 MySQL 数据同步到 Elasticsearch

    使用 Spark 将 MySQL 数据同步到 Elasticsearch 需要使用 Spark 提供的 Elasticsearch Hadoop 库和 JDBC 数据源 以下是大致的步骤 首先 需要在 Spark 中创建一个 JDBC 数据
  • 【STM32】启动流程分析

    在面试的时候 我遇到一个提问 单片机上电之后都做了些什么 那么STM32上电之后都做了些啥呐 可以配合起来看 单片机启动文件分析 三种启动模式 简而言之就是根据启动模式决定0x0000 0000重映射到下图哪个地址 那么当单片机开始执行的时
  • 密码算法学习

    密码学算法分三大类 1 对称算法 使用同一个密钥 常见的对称加密算法 DES 3DES DESX Blowfish IDEA RC4 RC5 RC6和AES 优点 加解密的高速性和当使用长密钥时的难解性 缺点 当需要密钥的数量多时 密钥的生
  • Python-数据类型转换

    当涉及数据类型转换时 Python提供了多种内置函数来执行不同类型之间的转换 以下是每个方法的详细说明和示例案例 整数和浮点数转换 int x base 10 将给定的参数x转换为整数 x可以是一个整数 浮点数或字符串 如果x是字符串 则可
  • 获取网页标签图标favicon

    想要获取网页标签图标 首先要了解favicon有哪几种 1 像这种favicon ico图标可以直接用 window location protocol window location host favicon ico 获取 2 像这种图标
  • 郭律: 论机器学习平台与人工智能的关系

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯云AI中心发表于云 社区专栏 郭律 腾讯高级产品经理 腾讯云AI基础产品中心高级产品经理 解决方案架构师 主导腾讯智能钛TI ONE 可视化机器学习平台 和TI S 自动机
  • 【华为OD机试】乘坐保密电梯(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • Flowable工作流引擎的使用3(task审批节点的接受与使用)

    BPMN task节点 节点介绍 task节点是和业务最贴切的节点 表示一次审批 除了id name inComingFlows outGoingFlows这些属性以外 还有一些权限信息 用于区分一个任务哪些人可以审核的 flowable自