一、背景

市场上比较有名的开源流程引擎有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进行二次封装和扩展,包括跟企业组织用户集成,流程处理人配置,流程审批页面美化,还有流程退回、撤销、取回、跳转、加签、转办、传阅等中国特色流程功能的实现。camunda流程引擎有免费的测试体验环境http://www.yunchengxc.com,大家可以直接体验感受。

基于camunda开源流程引擎如何实现会签及会签原理解析的更多相关文章

  1. Camunda开源流程引擎快速入门——Hello World

    市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.由于jbpm.activiti.flowable这几个流程引擎出现的比较早,国内人用的 ...

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

    Camunda bpm流程引擎的数据库由多个表组成,表名都以ACT开头,第二部分是说明表用途的两字符标识.本文以Camunda7.11版本为例,共47张表. ACT_RE_*: 'RE'表示流程资源存 ...

  3. 开源流程引擎camunda如何扩展

    ​  市场上基于Java语言的开源工作流引擎有:osworkflow.jbpm.activiti.flowable.camunda等,其中osworkflow.jbpm流程引擎已经过时,目前主流的开源 ...

  4. 开源流程引擎osworkflow、jbpm、activiti、flowable、camunda哪个好?

    市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.其中:Jbpm4.Activiti.Flowable.camunda四个框架同宗同源, ...

  5. 基于开源流程引擎开发BPM或OA有哪些难点

    前言     如何基于开源流程引擎开发OA系统?开源流程引擎哪个好?把它整合到自己的产品里难不难,有没有啥风险?这是大家经常遇到的问题.笔者从2006年开始参与流程引擎开发,经历了三代流程引擎研发,支 ...

  6. 开源流程引擎Camunda BPM如何扩展数据库表

    前言 在使用开源流程引擎(如:JBPM.Activiti.Flowable.Camunda等)的时候,经常会遇到这样的需求,我们需要按照业务需求增加一张数据库的表,而且这张表是跟工作流引擎有交互的(注 ...

  7. 开源流程引擎该如何选择flowable还是camunda

    市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.现在国内用的最多的是activiti.flowable.camunda,下面主要从功能 ...

  8. Fixflow引擎解析(一)(介绍) - Fixflow开源流程引擎介绍

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  9. 基于laravel的有偿开源流程引擎

    系统主要文档已经编写完成,具体请前往查看[系统文档](https://www.kancloud.cn/lijianlin/jishullin_workflow_engine/1894424 " ...

随机推荐

  1. java——封装

    java--封装 java--封装1 封装的理解和好处2 封装的事项实现步骤3 将构造器和setXx结合4 this和super区分 1 封装的理解和好处 隐藏实现细节:[方法(连接数据库)<- ...

  2. conn username/password@servicename

    conn username/password 方式连接的时候,会碰到这样的错误问题 oracle@prd:/home/oracle/impdir$sqlplus /nolog SQL*Plus: Re ...

  3. gin框架使用【5.路由分组】

    package mainimport ( "github.com/gin-gonic/gin")func main() { router := gin.Default() v1Ro ...

  4. Flex 的 多种对齐属性

    1. html 结构 <div id="container"> <div class="item item-1"> <h3> ...

  5. ElasticSearch7.3学习(十九)---- deep paging

    1.什么是deep paging 根据相关度评分倒排序,所以分页过深,协调节点会将大量数据聚合分析. 2.deep paging 性能问题 1消耗网络带宽,因为所搜过深的话,各 shard 要把数据传 ...

  6. Go汇编语法和MatrixOne使用介绍

    目录 MatrixOne数据库是什么? Go汇编介绍 为什么使用Go汇编? 为什么不用CGO? Go汇编语法特点 操作数顺序 寄存器宽度标识 函数调用约定 对写Go汇编代码有帮助的工具 avo tex ...

  7. Spring Retry 在SpringBoot 中的应用

    Spring Boot中使用Spring-Retry重试框架 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始 ...

  8. HCNP Routing&Switching之端口隔离

    前文我们了解了组播路由协议稀疏模式中的RP相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16154347.html:今天我们来聊一聊二层交换机中有关v ...

  9. Windows下使用 Docker 部署 RabbitMQ

    安装 Docker 首先进入 https://docs.docker.com/desktop/windows/install/ 下载最新版 Docker,下载好后,双击进行安装,此处不对安装进行说明. ...

  10. Django-----cookie&session

    cookie 保存在用户浏览器端的一个键值对(别人给的凭证) 服务端可以向用户浏览器写cookie 客户端每次发请求会携带cookie去(放在请求头里面) 淘宝的cookie  京东的cookie(h ...