← 返回文章列表

Article / 文章

SmartEngine流程引擎

背景:参与的项目使用到了流程引擎SmartEngine,文档连接,因为流程引擎,规则引擎,权限等是业务系统非常常见的基础服务平台,总结一下还是很有必要的。

基础概念:

  • 流程定义:就是一套bpmn文件,定义了流程的基本信息。有多少节点,每个节点一票还是全票等信息。
  • 流程实例:一个运行时的流程。
  • 人物:可以理解为一个审批节点,可以指派给多人,一个流程中,包含多个任务
  • 加签:在一个流程实例中,审批节点动态加一个人。
  • 会签:一个节点多个审批人,而多个人同时处理一个任务,这种任务我们称之为会签任务。

从流程引擎的核心领域来讲,大概就这几块:

  1. 流程配置域,对应流程定义的操作:创建,修改,删除流程定义。
  2. 流程启动域,对应实例的操作:启动,终止操作。
  3. 审批域,对应每个热任务的操作:同意,拒绝。

流程域

  1. 流程定义表
name status bizId bizType processDefId bpmnId version
流程名称 启动禁用 业务系统ID 业务系统类型 流程定义Id bpmn的Id 流程定义版本
  1. 流程节点定义表
processDefId version nodeOrder name type roleType empIds rule
流程定义Id 版本 顺序 节点名称 需要/无需审批 节点角色类型 节点角色类型是指定人此字段为工号
一票/全票
  1. 节点审批人快照表
processDefId version processInstanceId taskNmae empId empName
流程定义Id 版本 实例id 节点名称 工号 姓名

其中流程定义ID是我们自己生成的,作为流程定义的唯一标识,bpmnId是由smartEngine生成的,依赖smartEngine的DeploymentCommandService​,这服务是smartEngine提供的,其实就相当于,smartEngine已经做了一套流程定义的全部接口,我们只是在外面套了一层业务表,用来使用。还有就是smartEngine自带的几张引擎内使用的表,这个我们不能进行操作。

版本号的作用:当流程已经有实例并且运行中了,这个时候,流程定义有更新,如果没有版本号是区分不开,新版本和老版本的。如果有了版本号:那流程定义有更新,则影响不到老版本的运行,老版本的去查询节点配置等信息,根据版本号就很容易区分开。不会出现:流程跑着跑着,节点审批人变了的情况。

时序图:

@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
collections bpmn解析
control SmartEngine服务
database 流程引擎数据库

业务系统 -> 流程引擎服务: 新增操作,携带流程节点等信息
流程引擎服务 --> 流程引擎数据库: 存储流程定义表
流程引擎服务 --> 流程引擎数据库: 存储流程节点表
流程引擎服务 --> bpmn解析: 调用解析器生成下bpmn文件
bpmn解析 --> SmartEngine服务: bpmn自带接口调用
SmartEngine服务 --> 流程引擎数据库: 存储bpmn信息
流程引擎服务 <-- 流程引擎数据库: 返回结果
业务系统 <-- 流程引擎服务: 返回结果

hide footbox
@enduml

实例域

这里依赖,smartEngine的几个服务:

  1. processCommandService:用于流程启动
  2. repositoryCommandService:用于部署操作
  3. repositoryQueryService:用于查询流程配置

首先,查询流程定义表, 拿到最新版本配置信息,这时候我们就能拿到版本号,流程定义Id信息了,我们需要依赖repositoryQueryService的cachedProcessDefinition接口,了解到当前版本有没有部署过,没有部署过,则调用部署接口部署,部署完成后启动,

部署究竟是个什么概念?

我其实没太理解,为啥吧加载bpmn文件到内存和启动流程步骤拆开,我感觉smartEngine完全可以对使用系统屏蔽这个细节。在启动接口内部做好这个就好了。。

同步操作时序图:

@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
control SmartEngine服务
database 流程引擎数据库

业务系统 -> 流程引擎服务: 流程启动操作,携带业务系统id等参数
流程引擎服务 --> 流程引擎数据库: 查询流程定义表最新的版本信息
流程引擎服务 --> SmartEngine服务: 如果没有部署则先部署bpmn文件
流程引擎服务 --> SmartEngine服务: 启动流程
流程引擎服务 <-- SmartEngine服务: 返回结果
业务系统 <-- 流程引擎服务: 返回结果

hide footbox
@enduml

启动流程后,异步的去初始化,审批人快照表,用于展示每个节点的审批人信息,这里也有个简单的策略,根据节点的roleType来决定人是如何查询的,业务系统配置的接口 or 调用自己默认的几个角色,比如主管之类的。

异步操作时序图:

@startuml
'https://plantuml.com/sequence-diagram

autonumber

queue 消息队列
collections 流程引擎服务
collections 业务系统
database 流程引擎数据库

消息队列 -> 流程引擎服务: 异步动作启动
流程引擎服务 --> 流程引擎数据库: 查询流程节点定义信息
流程引擎服务 --> 业务系统: 查询业务系统获取每个节点的审批人信息
流程引擎服务 --> 流程引擎数据库: 存储快照表,每个节点的审批人
消息队列 <-- 流程引擎服务: 返回结果

hide footbox
@enduml

审批域

通过/拒绝

这里涉及到如下的表:

  1. 审批结果记录表
name status bizId bizType processDefId bpmnId version taskStatus
流程名称 启动禁用 业务系统ID 业务系统类型 流程定义Id bpmn的Id 流程定义版本 任务状态

点审批后,以审批通过为例,需要先拿到当前审批人在此实例下task对象,然后提交task驱动当前节点前进

这里依赖,smartEngine的几个服务:

  1. variableQueryService: 根据实例Id查询实例的一些变量信息
  2. taskQueryService:对实例中的task做查询操作
  3. taskCommandService:对实例中的task做驱动操作

时序图:

@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
control SmartEngine服务
业务系统 --> 流程引擎服务: 审批通过
流程引擎服务 --> SmartEngine服务: 根据实例id查询流程定义信息variableQueryService
流程引擎服务 --> SmartEngine服务: 查询操作人的任务信息taskQueryService,幂等操作
流程引擎服务 --> SmartEngine服务: 驱动task走流程taskCommandService
流程引擎服务 --> 流程引擎服务: 审批结果记录表记录节点状态
业务系统 <-- 流程引擎服务: 返回


hide footbox
@enduml

流程中加签

加签的业务语义就是,当前节点到一个人了,这个人想让另一个人先看看,看对方的想法是同意还是拒绝

@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
collections 权限服务
control SmartEngine服务
database 流程引擎数据库

业务系统 -> 流程引擎服务: 当前节点加签
流程引擎服务 --> SmartEngine服务: 更新当前流程变量,打个标记有加签节点
流程引擎服务 --> SmartEngine服务: 新增一个加签节点task,使用taskInstanceStorage存储
流程引擎服务 --> SmartEngine服务: taskCommandService的addTaskAssigneeCandidate关联审批人
流程引擎服务 --> 流程引擎数据库: 存储审批记录表,新增加签节点
业务系统 <-- 流程引擎服务: 返回
hide footbox
@enduml

一键审批

当一个审批节点很长的时候,或者特殊情况,特别着急,想快速走完审批流程,等等这些都是使用中常见的场景,因此从业务中抽象出来了一键审批的这样的功能,而往往一键审批功能仅仅对部分人开放,比如大领导,系统管理员等角色。

这里依赖,smartEngine的几个服务:

  1. ProcessEngineConfiguration:引擎初始化的配置类
  2. RelationShipDatabaseInstanceStorage:使用update操作,用于直接更新流程状态
  3. ProcessQueryService:查询流程实例对象
@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
collections 权限服务
control SmartEngine服务
database 流程引擎数据库

业务系统 -> 流程引擎服务: 一键审批调用
流程引擎服务 --> 权限服务: 权限校验,是否能一键审批
流程引擎服务 --> 流程引擎数据库: 更新审批记录表,审批结束,类型为一键审批
流程引擎服务 --> SmartEngine服务: 直接更新当前流程实例状态为结束
业务系统 <-- 流程引擎服务: 返回
hide footbox
@enduml

展示域

任务展示

依赖SmartEngine的TaskAssigneeDispatcher​接口,实现其必要的方法可以做到,可参考文档

依赖下面的一张表

  1. 审批结果记录表
name status bizId bizType processDefId bpmnId version taskStatus
流程名称 启动禁用 业务系统ID 业务系统类型 流程定义Id bpmn的Id 流程定义版本 任务状态

当smartEngine每次实例任务节点开启的时候,会回调当前实现类其时序图,如下所示:

@startuml
'https://plantuml.com/sequence-diagram

autonumber
control SmartEngine服务
collections 流程引擎服务
collections 业务系统
database 流程引擎数据库


SmartEngine服务 --> 流程引擎服务: 节点启动回调TaskAssigneeDispatcher实现类
流程引擎服务 --> 业务系统: 查询当前节点审批人信息
流程引擎服务 --> 流程引擎数据库: 初始化节点审批信息到:审批结果记录表
流程引擎数据库 --> SmartEngine服务: 返回

hide footbox
@enduml

当查询待审批,已完成,拒绝等任务的作展示的时候,可以用此业务表即可实现。

审批详情展示

通过两张业务表实现

  1. 审批结果记录表
name status bizId bizType processDefId bpmnId version taskStatus
流程名称 启动禁用 业务系统ID 业务系统类型 流程定义Id bpmn的Id 流程定义版本 任务状态
  1. 节点审批人快照表
processDefId version processInstanceId taskNmae empId empName
流程定义Id 版本 实例id 节点名称 工号 姓名

依赖两张业务表来展示,审批节点详情信息

@startuml
'https://plantuml.com/sequence-diagram

autonumber

collections 业务系统
collections 流程引擎服务
业务系统 --> 流程引擎服务: 查询审批详情
流程引擎服务 --> 流程引擎服务: 查询审批记录表
流程引擎服务 --> 流程引擎服务: 查询快照表
流程引擎服务 --> 流程引擎服务: 组装审批节点展示信息
业务系统 <-- 流程引擎服务: 返回

hide footbox
@enduml

查看全部文章 →