一个系列搞懂自研工作流(三)-流程引擎

2,230 阅读3分钟

写在最前

前两篇文章讲述了流程定义、解析以及节点设计,接下来我们要介绍工作流中最重要的工作流引擎如何工作,如何设计节点的流转。可以先看一下前两篇文章的介绍,因为本期内容有关联性。文章-流程定义文章-流程定义解析

工作流引擎

介绍

工作流引擎其实就是设计如何让流程中的节点运转起来,在通俗一点简化之后就是这样一个执行过程

开始-》执行节点动作-》寻找连线-》执行连线动作-》寻找下一个节点 -》执行节点动作-》 ---》结束

就是这样周而复始,直到最后流程结束,其中的分离和合并节点也只不过是执行节点动作的实现不同。所以我们只要定义好了这样的流程,那我们就可以实现整个工作流引擎的运转。

执行动作

刚刚的描述中反复提到的执行动作是我们首先需要考虑的,可以发现不论是节点还是连线,都需要处理节点动作,所以我们定义一个接口,使节点和连线都has这个接口,也就是实现这个接口。


public interface Action {

    /**
     * 执行对象中包含执行上下文信息
     *
     * @param execution 执行对象
     */
    void execute(Execution execution);
}

节点对象和连线对象都实现这个接口

public abstract class NodeModel extends BaseModel implements Action
public class LineModel extends BaseModel implements Action

节点动作的实现

节点元素NodeModel定义的是抽象类,实现Action的方法,通过模板方法定义标准流程,执行前动作、执行动作、执行后动作来可扩展化节点的执行。exec()是抽象方法,让具体实现类自己实现,来区分不同节点需要执行的动作。


@Override

public void execute(Execution execution) {

    // 前置拦截器

    intercept(preInterceptorList, execution);

    // 核心执行处理

    exec(execution);

    // 后置拦截器

    intercept(postInterceptorList, execution);

}


/**
 * 具体节点模型需要完成的执行逻辑
 *
 * @param execution 执行对象
 */
protected abstract void exec(Execution execution);

连线对象执行动作

连线对象执行就比较简单了,因为一条连线有一个明确的唯一的节点,所以直接执行目标节点的动作就可以了。


@Override
public void execute(Execution execution) {
    // 不可执行,则返回
    if (!enabled || target == null) {
        return;
    }
    // 执行目标节点
    target.execute(execution);
}

如何串联

刚刚已经介绍了节点执行动作和连线执行动作,那节点如何寻找到要执行的线呢?

在节点对象里定义方法,供子类调用

/**
 * 后继执行
 *
 * @param execution 执行对象
 */
protected void runOutTransition(Execution execution) {
    // 遍历连线节点,执行连线节点动作
    for (LineModel line : getOutputs()) {
        line.setEnabled(true);
        line.execute(execution);
    }
}

这样我们就把一个基本的工作流引擎就可以运行起来了。

前、后置拦截器

NodeModel中定义的execute()方法中定义了pre、post拦截器的执行。这两个拦截器分为用于系统级别、业务级别的拦截器,系统级别的拦截器比如节点history的记录、日志的记录等。业务级别的拦截器用于为业务实现定制化的需求而设计,业务方通过选择执行类来执行特定的业务需求。

public interface EngineInterceptor {


/**
 * 从执行对象中获得上下文执行数据
 *
 * @param execution
 */
void intercept(Execution execution);

}

在具体实现类中实现intercept方法来完成系统级别和业务级别的需求。

写在最后

工作流引擎简单的实现就已经讲完了,接下来会就不同节点的exec(),即节点执行动作展开讨论。希望大家能多支持支持点个赞,更有动力把这些内容分享给大家。