为什么要做自研工作流
工作流作为企业数字化不可或缺的一部分,在企业生产中举足轻重。随着钉钉、飞书等企业app的飞速发展,线上审批也走进了大家的工作中,很多企业为了业务定制化会自己开发工作流平台。绝大多数企业会采用市场上现有的工作流方案,如activiti5/6/7、Camunda等开源框架,但是过重的框架会让整体工作流平台过于臃肿,许多功能其实在现有业务中根本用不到。所以,自研工作流就是为了更加贴合自身业务,更加轻量级的开发。
特点
- 轻量级
- 符合大多数简单的业务场景
- 标准化流程,遵循BMPN规范
如何做
在网上搜索了许多文章,大多数是对于activi的解析以及如何使用,对于自研工作流的方案确是少之又少。这就是我写这个系列的文章的目的,通过自身对自研工作流的实际开发和理解,用文字的形式帮助更多的人在开发中得到更多的灵感。
概念理解
首先需要先去了解BMPN规范,知道工作流的流程图是长什么样子的,里面的关键节点有什么.具体可以看我的另一篇文章简单工作流设计
如图所示
将流程定义可以抽象成节点和连线
节点包含开始节点、任务节点、结束节点、网关节点等。连线则是表示节点关系的对象。正是这两个对象元素组成了流程定义。
本篇文章着重讲述如何定义元素来解析流程
BaseModel
定义节点和连线的基础属性如标识的id和名称
public class BaseModel implements Serializable {
/**
* 元素ID
*/
private String id;
/**
* 元素显示名称
*/
private String displayName;
}
NodelModel
NodelModel是node节点的抽象对象,是对所有节点的一个对象声明。节点的子类包括:开始节点、任务节点、结束节点、网关节点等。NodelModel包含的元素主要分为两部分:基础属性(所有节点共有的属性)和节点行为(执行节点动作)。
- 基础属性:类型、进线对象list、出线对象list、回退节点
- 节点行为:前置拦截器、后置拦截器、方法execute()。
public abstract class NodeModel extends BaseModel {
/**
* 输入节点连线list
*/
private List<LineModel> inputs = new ArrayList<>();
/**
* 输出节点连线list
*/
private List<LineModel> outputs = new ArrayList<>();
/**
* 节点类型
*/
private String type;
/**
* 前置局部拦截器实例集合
*/
private List<SmartFlowInterceptor> preInterceptorList = new ArrayList<>();
/**
* 后置局部拦截器实例集合
*/
private List<SmartFlowInterceptor> postInterceptorList = new ArrayList<>();
/**
* rollback target 目标节点
*/
private NodeModel rollbackTarget;
@Override
public void execute(Execution execution) {
// 前置拦截器
intercept(preInterceptorList, execution);
// 核心执行处理
exec(execution);
// 后置拦截器
intercept(postInterceptorList, execution);
}
}
连线
将流程定义分为节点和连线,刚刚已经定义了节点,现在来定义一下连线。将这两个元素定义完之后就可以进行流程解析了。
- 来源节点:一个连线仅有一个来源节点
- 目标节点:一个连线仅有一个目标节点.如此就可以通过获取目标节点,执行节点动作来完成流程流转。
public class LineModel extends BaseModel {
/**
* source 来源节点
*/
private NodeModel source;
/**
* target 目标节点
*/
private NodeModel target;
/**
* 是否可执行|默认false
*/
private boolean enabled = false;
@Override
public void execute(Execution execution) {
// 不可执行,则返回
if (!enabled || target == null) return;
// 重要步骤,放入执行对象中,在后续动作执行中取出使用。
execution.setCurrentExecutionNode(target);
target.execute(execution);
}
}
后续
下一篇文章将介绍如何解析json字符串来获取流程对象。 一个系列搞懂自研工作流(二)流程定义解析