Solon v3.3.0

flow - 流驱动器的组搭和定制

</> markdown

流驱动器(FlowDriver)的相关接口,主要有三个:

接口描述
FlowDriver流驱动接口定义
AbstractFlowDriver虚拟流驱动器,实现基本能力,并抽象出:脚本运行接口(Evaluation)和组件容器接口(Container)。一般做为基类使用
SimpleFlowDriver简单流驱动器。以 AbstractFlowDriver 为基础,提供 Evaluation 和 Container 组搭支持。
StatefulFlowDriver有状态流驱动接口定义。以 FlowDriver 为基础
StatefulSimpleFlowDriver有状态的简单流驱动器。以 SimpleFlowDriver 为基础定制。

有状态是指:活动节点会有等待、完成、退回、重新开始等状态(或指令)。应用场景不同。

1、SimpleFlowDriver 的默认状态

当使用默认构造时,默认会使用 LiquorEvaluation 脚本评估器和 SolonContainer 组件容器。

SimpleFlowDriver flowDriver = new SimpleFlowDriver();

流引擎,默认的驱动器就是这个状态。

2、SimpleFlowDriver 的简单组搭

可选的组搭组件(可自己定制)

组件类型描述
MapContainer组件容器基于 Map 实现的组件容器(适合无容器环境)
SolonContainer组件容器对接 solon 的组件容器
LiquorEvaluation脚本评估器基于 liquor 实现,支持完整 java 语法的条件与脚本
AviatorEvaluation脚本评估器基于 aviator 实现,支持完整 aviator 语法的条件与脚本
BeetlEvaluation脚本评估器基于 beetl 实现,支持完整 beetl 语法的条件与脚本
MagicEvaluation脚本评估器基于 magic 实现,支持完整 magic 语法的条件与脚本
  • AviatorEvaluation,需要引入包:org.noear:solon-flow-eval-aviator
  • BeetlEvaluation,需要引入包:org.noear:solon-flow-eval-beetl
  • MagicEvaluation,需要引入包:org.noear:solon-flow-eval-magic

简单组搭示例:

//构建组件容器
MapContainer container = new MapContainer();
container.putComponent("DemoCom", (ctx, node)->{
    System.out.println(node.getId());
});

//构建驱动
SimpleFlowDriver flowDriver = new SimpleFlowDriver(container);

//构建引擎
FlowEngine engine = FlowEngine.newInstance();
engine.register(flowDriver);

//----- 

//动态构建链,并执行
Chain chain = new Chain("c1");
chain.addNode(NodeDecl.activityOf("n1").task("@DemoCom"));

engine.eval(chain.getNode("n1"), new FlowContext());

3、驱动器定制参考

驱动器的定制,可以基于 SimpleFlowDriver 进行重写与扩展(比较重),也可以定制脚本执行器和组件容器进行组搭(比较轻)。

定制脚本执行器参考 AviatorEvaluation:

public class AviatorEvaluation implements Evaluation {
    @Override
    public boolean runTest(FlowContext context, String code) {
        return (Boolean) AviatorEvaluator.execute(code, context.model());
    }

    @Override
    public void runTask(FlowContext context, String code) {
        AviatorEvaluator.execute(code, context.model());
    }
}

//应用
//SimpleFlowDriver flowDriver = new SimpleFlowDriver(new AviatorEvaluation());

定制组件容器参考 SpringContainer(比如把它应用到 Spring 环境):

@Component
public class SpringContainer implements Container, ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        this.context = context;
    }

        @Override
    public Object getComponent(String componentName) {
        return context.getBean(componentName);
    }
}

//应用
//@Configuration
//public class FlowEngineConfig  {
//    @Bean
//    public FlowEngine flowEngine(SpringContainer container) {
//        FlowEngine flowEngine = FlowEngine.newInstance();
//        
//        flowEngine.register(new SimpleFlowDriver(container));
//        flowEngine.load("classpath:flow/*.yml")
//        
//        return flowEngine;
//    }
//}

定制流驱动器参考 StatefulSimpleFlowDriver(框架已内置):

public class StatefulSimpleFlowDriver extends SimpleFlowDriver implements FlowDriver, StatefulFlowDriver {
    private final StateRepository stateRepository;
    private final StateController stateController;

    public StatefulSimpleFlowDriver(StateRepository stateRepository, StateController stateController, Evaluation evaluation, Container container) {
        super(evaluation, container);
        this.stateRepository = (stateRepository == null ? new InMemoryStateRepository() : stateRepository);
        this.stateController = (stateController == null ? new BlockStateController() : stateController);
    }

    /**
     * 获取状态仓库
     */
    @Override
    public StateRepository getStateRepository() {
        return stateRepository;
    }

    /**
     * 获取状态控制器
     */
    @Override
    public StateController getStateController() {
        return stateController;
    }

    /**
     * 提交处理任务
     *
     * @param context 流上下文
     * @param task    任务
     */
    @Override
    public void postHandleTask(FlowContext context, Task task) throws Throwable {
        super.handleTask(context, task);
    }

    /**
     * 处理任务
     *
     * @param context 流上下文
     * @param task    任务
     */
    @Override
    public void handleTask(FlowContext context, Task task) throws Throwable {
        String instanceId = context.getInstanceId();

        if (Utils.isNotEmpty(instanceId)) {
            //有实例id,作有状态处理
            if (stateController.isAutoForward(context, task.getNode())) {
                //自动前进
                StateType state = getStateRepository().getState(context, task.getNode());
                if (state == StateType.UNKNOWN || state == StateType.WAITING) {
                    //添加状态
                    stateRepository.putState(context, task.getNode(), StateType.COMPLETED);

                    //发送提交变更事件
                    stateRepository.onPostActivityState(context, task.getNode(), StateType.COMPLETED);

                    //确保任务只被执行一次
                    postHandleTask(context, task);
                } else if (state == StateType.TERMINATED) {
                    //终止
                    context.stop();
                }
            } else {
                //控制前进
                StateType state = getStateRepository().getState(context, task.getNode());
                List<StatefulNode> nodeList = context.computeIfAbsent(StatefulNode.KEY_ACTIVITY_LIST, k -> new ArrayList<>());
                boolean nodeListGet = context.getOrDefault(StatefulNode.KEY_ACTIVITY_LIST_GET, false);

                if (state == StateType.UNKNOWN || state == StateType.WAITING) {
                    //检查是否为当前用户的任务
                    if (stateController.isOperatable(context, task.getNode())) {
                        //记录当前流程节点(用于展示)
                        StatefulNode statefulNode = new StatefulNode(task.getNode(), StateType.WAITING);
                        context.put(StatefulNode.KEY_ACTIVITY_NODE, statefulNode);
                        nodeList.add(statefulNode);

                        if (nodeListGet) {
                            context.interrupt();
                        } else {
                            context.stop();
                        }
                    } else {
                        //阻断当前分支(等待别的用户办理)
                        StatefulNode statefulNode = new StatefulNode(task.getNode(), StateType.UNKNOWN);
                        context.put(StatefulNode.KEY_ACTIVITY_NODE, statefulNode);
                        nodeList.add(statefulNode);

                        context.interrupt();
                    }
                } else if (state == StateType.TERMINATED) {
                    //终止
                    StatefulNode statefulNode = new StatefulNode(task.getNode(), StateType.TERMINATED);
                    context.put(StatefulNode.KEY_ACTIVITY_NODE, statefulNode);
                    nodeList.add(statefulNode);

                    if (nodeListGet) {
                        context.interrupt();
                    } else {
                        context.stop();
                    }
                }
            }
        } else {
            //没有实例id,作无状态处理 //直接提交处理任务
            postHandleTask(context, task);
        }
    }
}