如何实现一个自定义规则引擎

关注公众号「后端搬运工」《如何实现一个自定义规则引擎

规则引擎的功能可以简化为当满足一些条件时触发一些操作,通常使用 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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!