solon-flow
此插件也可用于非 solon 生态。具体开发学习,可参考:《学习 / Solon Flow 开发》
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-flow</artifactId>
</dependency>
1、描述
(v3.0.7 后支持)基础扩展插件,为 Solon Flow 开发提供基础的流引擎能力(可用于业务规则、决策处理、计算编排、流程审批等...)。提供有 “开放式” 驱动定制支持,像 jdbc 有 mysql 或 pgsql 等驱动。
可用于:
- 决策型的场景(替代一堆的 if/else)
- 编排型的场景
- 审批型(有状态、可中断)的场景(比如办公审批。需要定制驱动器)
主要元素:
- 链、节点(可带任务)、连接(可带条件)
- 链上下文、链驱动器、任务组件接口(TaskComponent)、条件组件接口(ConditionComponent)
- 流引擎
主要定义(就像用工具画图):
- 一个链(Chain),会有多个节点(Node)组成。
- 一个节点(Node),会有多个连接(Link,也叫“流出连接”)连向别的节点。
- 连接向其它节点,称为:流出连接。被其它节点连接,称为:流入连接。
- 一个链“必须有且只有”一个 start 类型的节点,且从 start 节点开始,顺着连接(Link)流出。
- 链的流转过程,可以有上下文参数(ChainContext),可以被中断(可支持有状态的审批模式)
通俗些,就是通过 “点”(节点) + “线”(连接)来描述一个流程图结构。
2、配置字典参考
- Chain 配置属性
属性 | 数据类型 | 需求 | 描述 |
---|---|---|---|
id | String | 必填 | 链Id(要求全局唯一) |
title | String | 显示标题 | |
driver | String | 驱动器(缺省为默认驱动器) | |
meta | Map | 元信息(用于应用扩展) | |
nodes | Node[] | 节点集合 |
- Node ,配置属性(驻 start,end, execute 类型节点,支持 task 配置)
属性 | 数据类型 | 需求 | 描述 |
---|---|---|---|
id | String | 节点Id(要求链内唯一) //不配置时,会自动生成 | |
type | NodeType | 节点类型 //不配置时,缺省为 execute 类型 | |
title | String | 显示标题 | |
meta | Map | 元信息(用于应用扩展) | |
link | String or Link String[] or Link[] | 连接(支持单值、多值) //不配置时,会自动生成 | |
task | String | 任务描述(会触发驱动的 handleTask 处理) | |
when | String | 执行任务条件描述(会触发驱动的 handleTest 处理) |
link 全写配置风格为 Link 类型结构;简写配置风格为 Link 的 nextId 值(即 String 类型)
- Link 配置属性
属性 | 数据类型 | 需求 | 描述 |
---|---|---|---|
nextId | String | 必填 | 后面的节点Id |
title | String | 显示标题 | |
meta | Map | 元信息(用于应用扩展) | |
condition | String | 流出条件描述(会触发驱动的 handleTest 处理) |
- 节点类型(NodeType 枚举成员)
描述 | 任务 | 连接条件 | 可流入 连接数 | 可流出 连接数 | 图例参考 | |
---|---|---|---|---|---|---|
start | 开始 | / | / | 0 | 1 | ![]() |
execute | 执行节点(缺省类型) | 可有 | / | 1...n | 1 | ![]() |
inclusive | 包容网关 | / | 支持 | 1...n | 1...n | ![]() |
exclusive | 排它网关 | / | 支持 | 1...n | 1...n | ![]() |
parallel | 并行网关 | / | / | 1...n | 1...n | ![]() |
end | 结束 | / | / | 1...n | 0 | ![]() |
配置示例(支持 yml 或 json):
# demo1.chain.yml(完整模式)
id: "c1"
nodes:
- { id: "n1", type: "start", link: "n2"}
- { id: "n2", type: "execute", link: "n3", task: "System.out.println(\"hello world!\");"}
- { id: "n3", type: "end"}
# demo1.chain.yml(简化模式)
id: "c1"
nodes:
- { type: "start"}
- { task: "System.out.println(\"hello world!\");"}
- { type: "end"}
3、链配置的简化模式说明
属性简化:
- 当没有
id
属性时,会按顺序自动生成(格式示例:"n-1") - 当没有
link
属性时,会按顺序自动链接后一个节点 - 当没有
type
属性时,缺省为execute
节点类型
节点简化:
- 当没有
type=start
节点时,按顺序第一个节点为开始节点 - 当没有
type=end
节点时,不影响执行
4、 主要接口参考
链的流动是由“链引擎”驱动的,也称为:执行。“链引擎”在执行链时,会涉及到“链上下文”(提供执行时的上下文参数与对象引用),以及可以定制的“链驱动器”。
- 链上下文接口(ChainContext)
返回数据类型 | 描述 | |
---|---|---|
isInterrupted() | bool | 是否已中断 |
interrupt() | 中断流转 | |
engine() | FlowEngine | 当前引擎实例(驱动定制时,用于跨链调用) |
model() | Map | 参数集合 |
put(key, value) | self | 参数设置 |
putAll(model) | self | 参数设置 |
get(key) | T | 参数获取 |
getOrDefault(key, def) | T | 参数默认 |
result | Object | 执行结果(执行中可赋值) |
- 链驱动器接口(ChainDriver),可自由定制
返回数据类型 | 描述 | |
---|---|---|
onNodeStart(context, node) | 节点开始时 | |
onNodeEnd(context, node) | 节点结束时 | |
handleTest(context, condition) | bool | 处理条件检测 |
handleTask(context, task) | 处理执行任务 |
5、节点任务与连接条件
节点任务与连接条件的描述,采用开放格式(即没有格式约定)。格式由 ChainDriver 处理(或约定),使用哪个 ChainDriver 就采用哪个格式约定。就像 jdbc 的 Driver, mysql 和 pgsql 的语法即不同。
5.1、默认格式(SimpleChainDriver 方案,框架内置):
示例 | |
---|---|
任务描述 | @t (任务组件风格) 或者 context.result=1; (java 脚本风格) 或者 #c12 (链调用风格) |
条件描述 | user_id > 12 (java 脚本表达式风格。要求结果为布尔值) |
- 组件风格
@Component("t") //节点任务组件
public class TaskComponentT implements TaskComponent {
@Override
public void run(ChainContext context, Node node) throws Throwable {
}
}
- 脚本风格
SimpleChainDriver 的脚本能力,由 Liquor 提供。context
和 context.model()
里的变量在脚本里可直接使用。
//任务脚本(示例1)//完整的 java 代码
context.result=1;
//任务脚本(示例2)//完整的 java 代码
if(order_id > 0) { //order_id 即为模型里的变量: context.get("order_id")
System.out.println("订单号: " + order_id);
}
//===================
//条件脚本(示例1)//产生一个布尔结果
user_id > 12 //user_id 即为模型里的变量: context.get("user_id")
5.2、定制格式参考(RubberChainDriver 方案,第三方的):
示例 | |
---|---|
任务描述 | F,tag/fun1;R,tag/rule1 (dsl 风格) |
条件描述 | m.user_id,>,12,A;m,F,$ssss(m),E (dsl 风格) |