基于camunda开源流程引擎如何实现会签及会签原理解析(代码片段)

catoop catoop     2022-12-04     508

关键词:

一、背景

市场上比较有名的开源流程引擎有osworkflow、jbpm、activiti、flowable、camunda。由于jbpm、activiti、flowable这几个流程引擎出现的比较早,国内人用的比较多,大家对camunda流程引擎认识的不多,实际上camunda在功能上、稳定性、性能、轻量化方面均比jbpm、activiti、flowable优秀。中国人使用业务流程,“会签”是一个最常用的流程操作,那么如何基于camunda实现会签流程,会签背后的流程引擎执行原理是什么,笔者希望通过这篇文章给正在研究camunda的同学参考,抛砖引玉。

二、什么是会签

会签: 在流程业务管理中,任务是通常都是由一个人去处理的,而多个人同时处理一个任务,这种任务我们称之为会签任务。

1、按照会签执行的顺序:

a)串行会签:串行会签也叫顺序会签,指按照提交流程处理人的次序user1、user2、user3依次接收待办任务,并按顺序处理流程。

b) 并行会签:指user1、user2、user3同时接收到流程待办任务,并行处理。

2、按照会签通过的比例:

a) 全部通过:会签人全部审批通过表决后,会签通过。

b) 按数量通过:达到一定数量的通过表决后,会签通过。

c) 按比例通过:达到一定比例的通过表决后,会签通过。

d) 一票通过:只要有一个表决通过的,会签通过。

e) 一票否决:只要有一个表决时否定的,会签通过。

以下介绍基于camunda流程引擎如何实现会签,并详细解析流程引擎运行的原理。

三、安装camunda BPM

首先完成camunda流程引擎的部署和camunda流程设计器的部署,并新建三个用户user1、user2、user3,为设计会签流程准备。详细操作见:《Camunda流程引擎快速入门——Hello World示例》,https://lowcode.blog.csdn.net/article/details/117518828

在这里插入图片描述

四、设计会签流程图

1、画流程图,设置一个会签节点

Camunda实现会签是基于多实例任务,将节点设置成多实例,主要通过在UserTask节点的属性上配置。选则一个用户任务在下面的属性中选择Multil instance,可以看到有两种图标,分别表示串行会签和并行会签。

在这里插入图片描述

2、会签参数设置

主要参数配置说明:

  1. loop cardinality:循环基数。可选项。可以直接填整数,表示会签的人数。
  2. Collection:集合。可选项。会签人数的集合,通常为list,和loop cardinality二选一。
  3. Element variable:元素变量。选择Collection时必选,为collection集合每次遍历的元素。
  4. Completion condition:完成条件。可选。比如设置一个人完成后会签结束,那么其他人的代办任务都会消失。
    在这里插入图片描述

设置完成后,会签节点的代码片段:

 <bpmn:userTask id="Activity_1udxyrq" name="会签" camunda:assignee="$assignee">
      <bpmn:incoming>Flow_1258z36</bpmn:incoming>
      <bpmn:outgoing>Flow_0248t03</bpmn:outgoing>
      <bpmn:multiInstanceLoopCharacteristics camunda:collection="assigneeList" camunda:elementVariable="assignee" />
</bpmn:userTask>

3、配置流程处理人

需要注意的是,右侧的Assignee,Candidate Users,Candidate Groups,分别表示按照负责人/候选用户/候选组。

采用Assignee,填写上一步中的Element Variable字段的内容,即可获取当前审批人,注意是动态变量,$格式,即会签人Collection中遍历的每一个人赋值给该变量。

在这里插入图片描述

4、配置流程监听事件

为了更好的实现会签可以结合流程节点监听功能Listener处理,监听种类有Java class、Expression、Delegate expression、script,文本为了简单,使用script配置会签处理人。

如何使用groovy script,详细请参考camunda官方文档:https://docs.camunda.org/manual/latest/user-guide/process-engine/scripting/

在这里插入图片描述

设置完成后,executionListener的配置片段如下:

点击并拖拽以移动

 <bpmn:extensionElements>
        <camunda:executionListener event="start">
          <camunda:script scriptFormat="groovy">def userList = ['user1', 'user2', 'user3'];execution.setVariable("assigneeList", userList);</camunda:script>
        </camunda:executionListener>
  </bpmn:extensionElements>

5、完整的BPMN流程文件

在这里插入图片描述

完整的BPMN流程模型文件:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1lsa7z1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0">
  <bpmn:process id="Process_1n6xfcx" name="测试验证流程1" isExecutable="true" camunda:versionTag="1.0">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_153mh25</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_153mh25" sourceRef="StartEvent_1" targetRef="Activity_18krv16" />
    <bpmn:sequenceFlow id="Flow_1258z36" sourceRef="Activity_18krv16" targetRef="Activity_1udxyrq" />
    <bpmn:sequenceFlow id="Flow_0248t03" sourceRef="Activity_1udxyrq" targetRef="Activity_0neq0ra" />
    <bpmn:endEvent id="Event_00b1j9n">
      <bpmn:incoming>Flow_0ucs2b7</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_0ucs2b7" sourceRef="Activity_0neq0ra" targetRef="Event_00b1j9n" />
    <bpmn:userTask id="Activity_18krv16" name="申请">
      <bpmn:extensionElements>
        <camunda:executionListener event="start">
          <camunda:script scriptFormat="groovy">def userList = ['user1', 'user2', 'user3'];execution.setVariable("assigneeList", userList);</camunda:script>
        </camunda:executionListener>
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_153mh25</bpmn:incoming>
      <bpmn:outgoing>Flow_1258z36</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:userTask id="Activity_1udxyrq" name="会签" camunda:assignee="$assignee">
      <bpmn:incoming>Flow_1258z36</bpmn:incoming>
      <bpmn:outgoing>Flow_0248t03</bpmn:outgoing>
      <bpmn:multiInstanceLoopCharacteristics camunda:collection="assigneeList" camunda:elementVariable="assignee" />
    </bpmn:userTask>
    <bpmn:userTask id="Activity_0neq0ra" name="审批" camunda:assignee="user2">
      <bpmn:incoming>Flow_0248t03</bpmn:incoming>
      <bpmn:outgoing>Flow_0ucs2b7</bpmn:outgoing>
    </bpmn:userTask>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1n6xfcx">
      <bpmndi:BPMNEdge id="Flow_0ucs2b7_di" bpmnElement="Flow_0ucs2b7">
        <di:waypoint x="690" y="117" />
        <di:waypoint x="752" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0248t03_di" bpmnElement="Flow_0248t03">
        <di:waypoint x="530" y="117" />
        <di:waypoint x="590" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1258z36_di" bpmnElement="Flow_1258z36">
        <di:waypoint x="370" y="117" />
        <di:waypoint x="430" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_153mh25_di" bpmnElement="Flow_153mh25">
        <di:waypoint x="215" y="117" />
        <di:waypoint x="270" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="179" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_00b1j9n_di" bpmnElement="Event_00b1j9n">
        <dc:Bounds x="752" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_068boyx_di" bpmnElement="Activity_18krv16">
        <dc:Bounds x="270" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_10kl1f8_di" bpmnElement="Activity_1udxyrq">
        <dc:Bounds x="430" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1duyn2a_di" bpmnElement="Activity_0neq0ra">
        <dc:Bounds x="590" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

6、发布流程

填写流程模型名称,设置Camunda REST服务地址,发布流程。
在这里插入图片描述

7、配置groovy解析包

给camunda流程引擎设置配置groovy解析包。找到camunda安装目录camunda-bpm-run-7.15.0\\configuration\\userlib,放置一个groovy-all-2.4.13.jar,否则流程引擎运行过程会报错,提示无法解析groovy脚本。Groovy包下载地址:https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all
在这里插入图片描述

8、开启java序列化

给camunda流程引擎开启java序列化,出于安全性考虑,camunda默认是关闭java序列化的,本示例涉及到会签集合流程变量的存储和解析,实际上是一个ArrayList,所以需要开启java序列化。

详细请参考camunda官方网站介绍:https://docs.camunda.org/manual/latest/reference/deployment-descriptors/tags/process-engine/#javaSerializationFormatEnabled
在这里插入图片描述

配置完成后,重启camunda流程引擎。

五、会签流程运行解析

1、登录camunda BPM

默认地址:http://127.0.0.1:8080/camunda/app/tasklist/default/#/login

默认密码: demo / demo

在这里插入图片描述

2、启动流程

点击“Start process”按钮,弹出流程模板选择框,点击要启动的流程名称。
在这里插入图片描述

流程启动后,默认在申请节点,点击Complete按钮,提交到下一步会签节点。

在这里插入图片描述
在这里插入图片描述

3、会签审批

(a)User1 登录,看到流程已经提交到会签节点了。
在这里插入图片描述

(b)通过界面查看流程变量

在这里插入图片描述

在这里插入图片描述

处于会签节点时,该task会自动生成以下几个流程变量:

  1. nrOfActiviteInstances:当前活动的实例数量,即还没有完成的实例数量
  2. loopCounter :循环计数器,办理人在列表中的索引
  3. nrOfInstances:会签中总共的实例数
  4. nrOfCompletedInstances:已经完成的实例数量

条件$nrOfInstances == nrOfCompletedInstances表示所有人员审批完成后会签结束。
条件$ nrOfCompletedInstances == 1表示一个人完成审批。

(c)填写审批意见

   每个会签人都可以填写流程意见。先填写流程意见,再提交流程,即完成会签操作。

在这里插入图片描述

(d)此时查看数据库表

查看act_ru_execution表,当前活动的实例有3条
在这里插入图片描述

查看act_ru_task表,当前待办任务有3条
在这里插入图片描述

查看act_ru_variable表,查看当前流程变量, 可以看出此时的活动实例的总数为3,未完成的实例为3,已完成的为0。
在这里插入图片描述

(e)user1提交流程,完成会签,提交给user2。
在这里插入图片描述

第一个会签处理完成后,流程变量nrOfActiviteInstances、loopCounter 、nrOfInstances、nrOfCompletedInstances的值均发生了变化。

(f)此时查看数据库表

查看act_ru_execution表,当前活动的实例有2条

在这里插入图片描述

查看act_ru_task表,当前待办任务有2条,user1的待办已经消失了。

在这里插入图片描述

查看act_ru_variable表,查看当前流程变量, 可以看出此时的活动实例的总数为3,未完成的实例为2,已完成的为1。

在这里插入图片描述

(g)按照如上操作,user1、user2、user3全部完成会签,流程即流转到了下一个节点。

在这里插入图片描述

(h)通过界面查询流程变量,跟会签控制相关流程变量全部消失了。

在这里插入图片描述

(i)查看数据库表记录

查看act_ru_execution表,会签活动实例全部消失了。

在这里插入图片描述

查看act_ru_task表,会签的待办任务全部消失了。

在这里插入图片描述

查看act_ru_variable表,查看当前流程变量, 跟会签状态控制相关的流程变量全部消失了。

在这里插入图片描述

查看act_hi_taskinst表,该表记录的是待办任务历史记录,可以看到有3条跟会签相关的历史待办任务。

在这里插入图片描述

查看act_hi_varinst表,该表记录的是流程变量历史记录。

查看act_hi_comment表,该表记录流程审批意见,可以看到user1、user2、user3三个人的审批意见均记录到该表了。

在这里插入图片描述

六、总结

以上是基于camunda流程引擎开源版本实现的会签功能,没有进行任何二次开发,目标是让读者在不写代码的情况下,快速运行和验证camunda流程引擎。在实际的业务场景中,这些是远远不够的,需要对camunda进行二次封装和扩展,包括跟企业组织用户集成,流程处理人配置,流程审批页面美化,还有流程退回、撤销、取回、跳转、加签、转办、传阅等中国特色流程功能的实现。


(END)

[13]深入浅出工作开源框架camunda:多实例并行用户任务(代码片段)

Camunda提供了多实例并行用户任务,比如下面的并行多任务流程!必须选择三条竖杠。选择之后,就可以让“并行会签预审批”任务同时由多个人处理~参考《基于camunda如何实现会签:camunda会签流程配置与原理解析... 查看详情

第十四篇camunda系列-多人会签多实例(代码片段)

多人会签MultipleInstance也叫多实例任务。1.会签说明  多实例活动是为业务流程中的某个步骤定义重复的一种方式。在编程概念中,多实例与foreach结构相匹配:它允许对给定集合中的每个项目按顺序或并行地执行某个步骤或甚... 查看详情

camunda动态增加会签(代码片段)

...在审批1种,设置了一个admin为审批人ProcessDefinitionId在Camunda界面上看一下。@ApiOperation("启动实例")@GetMapping("/start1")publicResponseEntitystart1(processDefinitionId,businessKey)//添加审批人Map<String,Object>map=newHashMap<... 查看详情

camunda动态增加会签(代码片段)

...在审批1种,设置了一个admin为审批人ProcessDefinitionId在Camunda界面上看一下。@ApiOperation("启动实例")@GetMapping("/start1")publicResponseEntitystart1(processDefinitionId,businessKey)//添加审批人Map<String,Object>map=newHashMap<... 查看详情

第十四篇camunda系列-多人会签多实例(代码片段)

多人会签MultipleInstance也叫多实例任务。1.会签说明  多实例活动是为业务流程中的某个步骤定义重复的一种方式。在编程概念中,多实例与foreach结构相匹配:它允许对给定集合中的每个项目按顺序或并行地执行某个步骤或甚... 查看详情

camunda工作流并行子流程工作流会签或签加签比例签跳转节点(代码片段)

如下图为一个流程图,其需求过程如下:1、某业务员发起一个登记单2、领导审批3、领导选择多个部门进行阅办,每个部门并行进行4、部门内有两个审批环节(环节一:部门经理或经理助理或签,环节二&#... 查看详情

camunda工作流并行子流程工作流会签或签加签比例签)(代码片段)

...途为子流程环节增加实例的代码如下://RuntimeService为camunda内置的对象,可以直接注入使用@AutowiredprivateRuntimeServiceruntimeService;@Testpublic 查看详情

activiti6.0动态改变流程节点类型(普通->会签)

...点转换为会签节点实现思路:中间表:用户保存被转换的流程以及被转换的节点实现接口继承接口实现抽象类:com.oldguy.example.modules.workflow.service.activiti.impls.AbstractMultiWorkFLowService实现类:测试例子将“测试节点”普通->会签并... 查看详情

flowable会签结束,会签变量没有更新。bug

...一票通过:只有一个同意时,会签通过Flowable实现会签是基于多实例任务的,将节点设置成多实例,通过在userTask节点的属性配置。3、多实例类型可以选择并行会签(parallel)、顺序会签(sequential),其中并行会签的意思是多个人... 查看详情

工作流activiti怎么实现会签

...行方式nrOfActiveInstances变量始终是1.loopDataInputRef指定一个流程变量的引用,该变量是一个List,可以在发起或这执行任务之前作为流程变量放到引擎中,该list中的每一个元素将创建一个任务。元素的值通过inputDataItem元素的指定的... 查看详情

activiti动态自定义流程(包含会签流程)

 后台加入工作流步骤(这个不重要,自己实现)1packagecom.blk.integrated.pojo;23importjava.io.Serializable;4importjava.util.Date;56importjavax.persistence.Column;7importjavax.persistence.Entity;8importjavax.persistence. 查看详情

开源流程引擎camunda技术架构

参考技术ACamunda是一个基于Java的框架,支持用于工作流和流程自动化的BPMN、用于案例管理的CMMN和用于业务决策管理的DMN。本篇文章我们仅考虑BPMN流程引擎,先不涉及CMMN和DMN引擎。就流程引擎而言,Camunda是一个灵活的工作流框... 查看详情

winform开发框架中工作流模块之审批会签操作

...笔介绍了请假申请单和报销申请单两个不同的业务表单的流程处理,一个是单表信息,一个包含明细的主从表信息,后者包含了条件流程的处理,在流程审批中,一般还有一种流程处理就是会签的操作,会签处理是几个审批步骤... 查看详情

2021-05-21camunda基础操作及数据对应

参考技术A流程部署有两种方式,第一种是项目启动直接找resouces目录下的bmpn文件,另一种方式是外部部署,通过api直接部署到项目中。(其中“南方尽调流程V3.bpmn”是没有部署过的新的流程文件)关联表:关联表:关联表:此... 查看详情

开源流程引擎camunda

开源流程引擎Camunda文章作者:智星1.简介Camunda是一个轻量级的商业流程开源平台,是一种基于Java的框架,持久层采用Mybatis,可以内嵌集成到Java应用、SpringBooot应用中,也可以独立运行,其支持BPMN,用... 查看详情

camunda开源流程引擎的数据库表结构介绍

Camundabpm流程引擎的数据库由多个表组成,表名都以ACT开头,第二部分是说明表用途的两字符标识。本文以Camunda7.11版本为例,共47张表。ACT_RE_*:\'RE’表示流程资源存储,这个前缀的表包含了流程定义和流程静态资源(图片,规则... 查看详情

activiti6.0实现会签的加减签功能

参考技术A前置知识:实现思路:测试流程图:加签任务:com.oldguy.example.modules.workflow.commands.AddMultiInstanceExecutionCmd减签:com.oldguy.example.modules.workflow.commands.DeleteMultiInstanceExecutionCmd抽象父类:com.oldguy.example.modules.workflow.commands.AbstractCo... 查看详情

activiti7工作流引擎:进阶篇会签(代码片段)

之前的任务负责人Assignee都是一个,而任务可以有多个人有权限审批,只要其中有一部分人完成审批任务就算整个任务完成。同一个任务需要多个负责人来完成被称之为“会签”。会签就是一种投票,满足投票人数就... 查看详情