采用 Excel 作为可视化设计器的开源规则引擎 NopRule
决策树和决策矩阵是业务人员可以直观理解的复杂 IF-ELSE 逻辑表达形式,也是规则引擎中最常用、最有用的部分。常见的规则引擎如 Drools 虽然提供了更加丰富的功能特性集,特别是所谓的 RETE 算法可以用于高效复用多次重复出现的表达式片段,但在实际业务应用中很少出现必须使用 RETE 算法的情况,大部分情况下我们都是把规则引擎降级为决策表和决策矩阵来使用。
合理安排决策树和决策矩阵的节点顺序已经可以起到优化执行的作用。对于必须使用 RETE 算法的情况往往一般人已经难以直观理解,难以交给业务人员直接配置。甚至程序员理解其中的执行细节也存在困难,还不如手工实现更加便于优化。基本的决策表+类似流程图的执行控制往往比使用 RETE 算法更加合用。
NopRule 是一个非常轻量级的规则引擎,它可以嵌入在 Java 程序内部使用,也可以作为微服务被远程调用。它提供了在线可视化设计界面,可以将规则模型保存在数据库中实现动态更新,同时也可以使用静态的模型文件,不依赖数据库存储。
与 NopReport 报表引擎类似,NopRule 可以使用 Excel 作为可视化设计工具,直接导入 Excel 格式的规则模型,极大简化了业务规则的设计和使用。
一. 使用方式
仿照 nop-quarks-demo 工程中的做法,在 pom 文件中可以引入如下模块
nop-rule-service 提供后端规则服务。nop-rule-web 包含对应的 amis 前端管理页面。
在/_vfs/nop/demo/app.action-auth.xml
中引入 nop-rule.action-auth.xml,其中定义了用于测试的功能菜单
启动后访问http://localhost:8080/#/NopRuleDefinition-main
1.1 规则调用
可以通过RuleService接口调用远程规则服务
如果是嵌入在 Java 程序内部使用,则可以直接使用 IRuleManager 接口,减少请求对象的包装转换
具体示例参见 TestRuleExprParser
使用 RuleManager 嵌入调用的时候可以传入复杂的输入对象,而作为 RuleService 调用的时候输入变量应该是 JSON 数据。
1.2 导入模型
在【规则模型】的管理页面上,新增以及修改的时候都可以通过上传 Excel 模型文件来导入模型定义。
1.3 测试规则
导入规则模型之后,点击行数据上的【测试规则】按钮,可以弹出测试页面。
点击提交按钮之后,会弹出结果显示页,其中包含了返回的输出变量集合,以及规则执行过程中产生的详细日志信息,从中可以看出具体规则节点的匹配顺序和匹配结果。
二. 配置
2.1 Excel 模型配置
Excel 规则模型必须包含两个 Sheet,其中 Rule 表单配置决策规则,而 Config 表单配置输入输出变量等描述信息。
输入变量是规则模型中用于判断的那些变量,而输出变量是满足匹配条件的那些规则节点所产生的输出。为了支持在线可视化设计,我们需要为输入输出变量指定显示名和数据类型。
输入变量支持复杂对象结构。
在变量名前增加
*
号可以表示嵌套对象结构,增加几个*
号表示对应第几个层级通过设置【计算】列为 Y,则表示这个属性不是由外部调用者传入的,而是根据输出数据和上下文环境变量动态计算得到的值,计算使用的表达式由【缺省表达式】列指定
业务规则匹配时有可能会匹配到多个执行分支,每个分支都可能会产生输出变量,通过指定【汇总】列,我们可以指定如何根据综合多个输出结果产生最终返回的 output 值。
2.2 Rule 表达式
在输入列的单元格中配置规则判断表达式 RuleExpr,它的语法有些类似 Friendly Enough Expression Language (FEEL),是 XLang Expression 的一个更容易阅读的版本,使用RulExprParser来解析。
true 和 false 可以直接指定是否匹配
减号-表示 true,直接匹配
数值型表示严格匹配
引号包裹的字符串表示严格匹配
如果是单个变量名则不把它作为变量来解释,而是看作是字符串值。如果要表示等于变量,则应该使用 == myVar 这种形式
支持比较操作符和 and/or/not,并且支持括号。所有支持比较操作符在FilterOp类中定义
支持所有 XScript 中注册的全局函数
2.3 决策表配置
决策表的配置示例可以参见 decision-tree.rule.xlsx
决策表的左上角的内容必须是字母 T,表示 Table。然后是输入列和输出列。输入列和输出列的每一列都是对应的输入输出变量名。
2.4 决策矩阵配置
决策矩阵的配置示例可以参见 decision-matrix.rule.xlsx
决策表的左上交的内容必须是字母 M,表示 Matrix。
在左侧的每一列以及头部的每一行的第一个单元格中可以配置输入变量名。
单元格中可以通过批注 valueExpr 来指定表达式,此时单元格文本仅作为显示用的 label。如果不配置,则以单元格的文本为表达式。
可以配置输出多个结果值
2.5 在线修改
对于决策树模型可以通过在线页面进行修改,规则匹配条件的配置使用 AMIS 的 ConditionBuilder 控件
三. 设计原理
在 Nop 平台的整体设计中,NopRule 负责的是对复杂判断逻辑的抽象,这其中最核心的部分是 Filter 模型
3.1 Filter 模型
filter 模型由filter.xdef元模型来定义,它可以用于描述复杂的 and/or 条件
Nop 平台在所有需要表达判断条件的地方都统一使用 Filter 模型,在 Java 程序中对应 ITreeBean 类型
利用 XML 和 JSON 的双向转换,Filter 模型可以保存为 XML 格式或者 JSON 格式
Nop 平台中高级查询使用的就是 Filter 模型,后台通过FilterBeanToSQLTransformer类将它转换为 SQL 语句
前端 AMIS 的 ConditionBuilder 控件可以将复杂判断条件保存为 Condition 对象。ConditionExprHelper负责实现 Condition 和 Filter 模型之间的双向转换。
Filter 模型可以通过FilterBeanToPredicateTransformer编译得到 IEvalPredicate 接口,直接在内存中执行过滤逻辑,
Filter 模型也可以通过FilterBeanEvaluator在内存中执行
Filter 模型与表达式语言 Expression 之间可以利用FilterBeanExpressionCompiler和ExpressionToFilterBeanTransformer进行可逆转换,
3.2 Schema 模型
Nop 平台中所有需要定义对象类型的地方都统一使用 schema 模型,它由元模型schema.xdef来定义。
XDef 元模型和 Schema 模型之间可以相互转换。XDef 用于定义 XML 结构,而 Schema 用于定义对象以及 JSON 结构。
通过SimpleSchemaValidator可以检查 value 是否满足 schema 规范要求
通过XSchemaToJsonSchema可以将 schema 对象转换为 JSON Schema 定义
ConditionSchemaHelper负责将规则模型中的输入变量定义转换为前端 ConditionBuilder 控件所支持的 schema 定义。
3.3 Excel 数据模型
Nop 平台提供了 Excel 数据模型和 Java 领域模型对象之间的双向转换,因此无需编程,就可以实现 Excel 解析以及将对象导出为 Excel 文件的功能。具体介绍参见excel-import.md
NopRule 在解析 Excel 格式的规则模式时,对于 Config 表单页的解析就是使用的标准 Excel 转换技术。
NopRule 使用 Excel 格式的 API 模型来定义对外服务接口,自动生成对应的接口定义和服务框架类,参见nop-rule.api.xlsx
总结
NopRule 的实现采用了 Nop 平台的基本技术战略:
通过元模型来定义领域模型
尽量通过自动推导实现模型之间的双向转换,减少硬编码
通过复用底层的通用模型,如 Filter、Expression 等,我们可以快速组装出更复杂的领域模型,如规则模型
基于可逆计算理论设计的低代码平台 NopPlatform 已开源:
github: entropy-cloud/nop-entropy
版权声明: 本文为 InfoQ 作者【canonical】的原创文章。
原文链接:【http://xie.infoq.cn/article/5654a98c2506d1d56fef573c8】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论