基于activiti的自研工作流设计

2,781 阅读6分钟

整体介绍

基于BPMN2.0规范设计,进行工作流自研方案的设计,参考activiti框架的整体设计进行工作流lite版本的自研方案构思。lite版本仅针对简单流程进行一个方案设计,预留一些复杂业务逻辑的实现口子,能够初步达成简单工作流的实现。

达成效果

  1. 实现简单的线性工作流方案。
  2. 实现用户任务方案的工作流自研版本。
  3. 基于JSON/XML的数据格式进行工作流流程定义.(前端的实现不在此体现)

方案介绍

流程定义描述

在工作流中,流程定义可以图形化的表达为一组节点和连接构成的集合,只是流程定义的表达方式不同,lite版本中采用json/xml的数据格式进行流程定义的描述。流程定义描述可以定义为流程元素的集合,元素可以分为两大类,节点类元素和连线表达类元素。通过节点类和连线表达类拆分来解耦节点和联结的动作,从而后续能够更加灵活的实现。

节点类

节点类是某一个动作表达的抽象表述,分为开始节点结束节点任务节点网关节点(预留类,lite版本暂不考虑)。

连线表达类

描述不同节点之间的转移关系,包含源节点、目标节点和流转规则。ps:一个连线只能有一个源头节点和一个目标节点。

实现构思

不同节点类提供统一的抽象接口类,通过以下流程实现工作流流转。

【流程启动】 -》开始节点执行 -》任务节点执行 -》根据规则和连线表达类寻找下一节点 -》下一节点执行 -》 ..... --》结束节点-》【流程结束】

【完成任务】-》完成任务 -》根据规则和连线表达类寻找下一节点 -》下一节点执行-》创建任务

扩展点在于网关节点和子流程。具体实现可参考activiti的Scope作用域来进行设计实现。

流程启动

获取json解析 --》 执行开始节点process方法 --》执行下一节点流程

完成任务(审批)

完成当前任务(taskId) --》执行下一节点流程--》创建任务

如何执行下一节点流程

根据当前节点,获取targetTransition列表,根据节点属性和规则获取下一节点。根据下一节点属性类型判断是否需要创建任务。

数据库设计

流程定义表

存放流程定义的相关信息,主要为流程定义的json数据。

关键字段:def_context--流程定义字段,描述元素以及关系的json

流程定义节点表

记录流程定义中节点的数据表,描述节点的基本信息

关键字段:

def_id -- 流程定义表主键id, node_type -- 区分节点类型,如开始、结束、活动、网关节点等

node_candidate -- 节点执行候选人, node_listener -- 节点监听器,用于后续动作的执行。

流程任务表

记录流程中任务的信息数据表。主要是任务的相关信息, 关联的任务实例id,流程定义id,当前任务的状态、执行人、操作的信息等。

process, template、task/

-- 流程定义表 存放流程定义的相关信息,主要为流程定义的json数据。
CREATE TABLE `process_template` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `biz_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务系统标识',
  `template_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程定义名称',
  `template_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '流程标识',
  `template_context` json NOT NULL COMMENT '流程上下文数据',
  `template_version` int NOT NULL COMMENT '流程定义版本',
  `enable` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '是否可用 0:不可用 1:可用',
  `created_at` datetime NOT NULL default current_timestamp COMMENT '创建时间',
  `updated_at` datetime NOT NULL default current_timestamp COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程模板表';




-- 流程实例表
CREATE TABLE `process_instance` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `template_id` bigint NOT NULL COMMENT '流程模板表ID',
  `parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父级流程ID',
  `biz_code` varchar(64)  NOT NULL COMMENT '业务编号,标识来源业务方',
  `biz_key` varchar(64)   NOT NULL COMMENT '业务标识',
  `current_status` tinyint(2) unsigned NOT NULL DEFAULT 0 COMMENT '状态:0-进行中,1-已完成,2-已取消',
  `start_time` datetime NOT NULL COMMENT '流程开始时间',
  `end_time` datetime NOT NULL COMMENT '流程结束时间',
  `duration` bigint NOT NULL COMMENT '开始结束间隔时间',
  `biz_parameters` varchar(512) comment '业务数据,json',
  `created_at` datetime NOT NULL default current_timestamp COMMENT '创建时间',
  `updated_at` datetime NOT NULL default current_timestamp COMMENT '修改时间',
  `creator` varchar(64) NOT NULL COMMENT '创建人',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程实例表';




-- 流程任务表
CREATE TABLE `process_task` (
  `id` bigint NOT NULL,
  `process_instance_id` bigint NOT NULL COMMENT '流程实例id',
  `node_code` bigint NOT NULL COMMENT '节点code',
  `task_name` varchar(255) NOT NULL COMMENT '任务名称',
  `assign_strategy` tinyint(1) unsigned not null default 1 comment '通过策略,1-或签,2-会签,3-按数量,4-按比例',
  `assign_strategy_ext` varchar(64) comment '通过策略扩展字段,当类型为按数量和按比例是填入',
  `assign_user` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行人 多个使用,分割',
  `assign_org` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行人部门',
  `task_status` tinyint(2) unsigned NOT NULL default 1 COMMENT '任务状态:1-进行中,2-已完成,3-已取消',
  `source_task_id` bigint DEFAULT NULL COMMENT '来源任务id',
  `start_time` datetime DEFAULT NULL COMMENT '任务开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '任务结束时间',
  `created_at` datetime NOT NULL default current_timestamp COMMENT '创建时间',
  `updated_at` datetime NOT NULL default current_timestamp COMMENT '修改时间',
  `creator` varchar(64) NOT NULL COMMENT '创建人',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程任务表';


create table process_task_detail
(
	id bigint auto_increment comment '主键id',
	task_id bigint not null comment '任务实例id',
	user_id varchar(64) not null comment '用户id',
	assign_result tinyint(1) unsigned default 0 not null comment '审批结果,0-待确认,1-通过,2-拒绝',
	is_valid tinyint(1) unsigned default 1 not null comment '是否有效,1-有效,0-无效。',
	remark varchar(255) null comment '审批意见',
	created_at datetime default current_timestamp not null comment '创建时间',
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='流程任务明细表';


# 流转历史表
-- process_node_history: table
CREATE TABLE `process_node_history`
(
    `id`                  bigint(20)  NOT NULL AUTO_INCREMENT COMMENT '主键id',
    `template_id`         bigint(20)  NOT NULL COMMENT '模板id',
    `process_instance_id` bigint(20)  NOT NULL COMMENT '流程实例id',
    `node_code`           varchar(64) NOT NULL COMMENT '节点code',
    `task_id`             bigint(20)  NULL COMMENT '任务id',
    `node_name`           varchar(64) NULL COMMENT '节点名称',
    `node_type`           varchar(64) NULL COMMENT '节点类型',
    `start_time`          datetime    NOT NULL COMMENT '开始时间',
    `end_time`            datetime    NULL COMMENT '结束时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT ='节点历史表';

后续方案设想

关于表单

一张表记录流程定义中需要设置的表单信息

一张表记录流程实例中填入的表单数据

一张表记录运行中的流程实例表数据 -- 用于在流程中的表单数据的变更

关于网关和子流程

可借鉴activiti的设计想法,引入ExecutionEntity的概念,大致设计就是进入子流程和网关时,挂起原ExecutionEntity,新建ExecutionEntity代表新的子流程或者网关链路,待子流程结束完成新建ExecutionEntity的状态,然后重新激活原ExecutionEntity。

关于各业务方自己的实现

通过mq消息系统,解耦工作流,业务方自行消费消息进行业务实现。 具体细节实现方案,可看接下来的详解文章 --自研工作流详解方案