如何实现一个自定义规则引擎
关注公众号「后端搬运工」《如何实现一个自定义规则引擎》
规则引擎的功能可以简化为当满足一些条件时触发一些操作,通常使用 DSL 自定义语法来表述。规则引擎需要先解析 DSL 语法形成语法树,然后遍历语法树得到完整的语法表达式,最后执行这些语法表达式完成规则的执行。
本文以 gengine 来探讨如何设计和实现一个自定义规则引擎。
支持的语句
为了满足基本的业务规则需求,规则引擎应该要支持的语句有:
逻辑与算术运算
- 数学运算(+、-、*、/)
- 逻辑运算(&&、||、!)
- 比较运算(==、!=、>、<、>=、<=)
流程控制
- 条件(IF ELSE)
- 循环 (FOR)
高级语句
- 对象属性访问(对象.属性)
- 方法调用(func())
规则语法的解析
规则的 DSL 语法定义应该简单明了,gengine 使用了开源的语法解析器 Antlr4 来定义和解析规则语法。
定义规则语法
规则的 DSL 基本语法格式如下:
rule "rulename" "rule-describtion" salience 10
begin
//规则体
end
其中规则体为具体规则语句,由上述的 逻辑与算术运算、流程控制、高级语句 组合而成。
例如,判断为一个大额异常订单的规则体:
if Order.Price>= 1000000 {
return
}
编写解析器语法
Antlr4 解析器语法定义文件后缀名为.g4
,以下内容为解析器的语法定义,解析器根据语法定义去逐行解析生成语法树。
这里省略了一些非核心的语法定义并做了简化,完整内容查看 gengine.g4。
grammar gengine;
primary: ruleEntity+;
// 规则定义
ruleEntity: RULE ruleName ruleDescription? salience? BEGIN ruleContent END;
ruleName : stringLiteral;
ruleDescription : stringLiteral;
salience : SALIENCE integer;
// 规则体
ruleContent : statements;
statements: statement* returnStmt?;
// 基本语句
statement : ifStmt | breakStmt;
expression : mathExpression
| expression comparisonOperator expression
| expression logicalOperator expression
;
mathExpression : mathExpression mathMdOperator mathExpression
| mathExpression mathPmOperator mathExpression
| expressionAtom
| LR_BRACKET mathExpression RR_BRACKET
;
expressionAtom
: functionCall
| constant
| variable
;
returnStmt : RETURN expression?;
ifStmt : IF expression LR_BRACE statements RR_BRACE elseIfStmt* elseStmt?;
elseStmt : ELSE LR_BRACE statements RR_BRACE;
constant
: booleanLiteral
| integer
| stringLiteral
;
functionArgs
: (constant | variable | functionCall | expression) (','(constant | variable | functionCall | expression))*
;
integer : MINUS? INT;
stringLiteral: DQUOTA_STRING;
booleanLiteral : TRUE | FALSE;
functionCall : SIMPLENAME LR_BRACKET functionArgs? RR_BRACKET;
variable : SIMPLENAME | DOTTEDNAME;
mathPmOperator : PLUS | MINUS;
mathMdOperator : MUL | DIV;
comparisonOperator : GT | LT | GTE | LTE | EQUALS | NOTEQUALS;
// 关键字省略
解析器生成语法树
如,判断为一个大额异常订单的规则:
rule "order-large-price" "订单大额金额" salience 10
begin
if Order.Price >= 1000000 {
return
}
end
语法解析器解析之后,生成语法树:
完整内容请前往原文,公众号「后端搬运工」 如何实现一个自定义规则引擎。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: