规则语言基础(DRL、MVEL等)

规则引擎的核心,说白了就是一套描述逻辑的语言。

你写的不再是 if/else,而是用规则语言告诉引擎:
“当 条件 满足时,执行 动作”。

我刚开始用 Drools 的时候,觉得 DRL 语法很像 Java,
结果一跑起来全是编译错误。后来才明白:
规则语言有自己的脾性,不能当普通代码写。

1. 规则语言概览

主流的规则语言大概分两类:

类型 代表 特点
专用规则语言 DRL(Drools Rule Language) 声明式、支持 Rete 算法、自带语法糖
通用表达式语言 MVEL、SpEL、OGNL 轻量、可嵌入、常用于条件计算

DRL 是 Drools 的亲儿子,从语法到运行都深度绑定。
MVEL 则更像一个“通用胶水”,很多框架(比如流式计算)都在用。

我个人习惯:当规则逻辑复杂(嵌套、聚合、多条件)时选 DRL;
简单条件或动态计算时用 MVEL,省得写一长串规则头。

2. DRL 深度解析

先看一个最简的 DRL 规则:

rule "检测异常密钥"
when
    $key : KeyObject( expireTime < System.currentTimeMillis() )
then
    System.out.println("密钥已过期: " + $key.getId());
end

DRL 的骨架就是 rule ... when ... then ... end。
when 里写条件,then 里写动作。

特别注意变量绑定 $key : KeyObject(...)。
这个 $key 不是随便起的——它把匹配到的对象存下来,
后面 then 里可以直接用。

DRL 的硬规则

  • 包声明:package com.example.rules 必须写在文件第一行。
  • 引入对象:import com.example.model.KeyObject,否则引擎不认。
  • 条件支持:&&、||、!、方法调用、嵌套字段。
  • 内置函数:exists、not、collect、accumulate。
我踩过一个大坑:when 里调用了 System.currentTimeMillis(),
结果每秒钟产生几十万条失效记录,直接把生产打崩了。
后来换成用 Timestamp 对象做属性比较,才好。

规则流与 salience

多个规则如果同时满足,谁先执行?用 salience 控制优先级:

rule "高优检测"
salience 10
when
    ...
then
    ...
end

rule "普通检测"
salience 0
when
    ...
then
    ...
end

数值越大越优先,默认 0。
我经常用它做“急停”规则——一旦命中,直接终止后续处理。

3. MVEL 表达式引擎

MVEL 比 DRL 轻得多,适合做动态条件、变量计算。

举个例子,在 Spring 集成 Drools 时,
我经常把 MVEL 表达式写在配置中心:

// 定义一个 MVEL 表达式
String expr = "user.age >= 18 && user.role == 'admin'";

// 用 MVEL 执行
Map<String, Object> vars = new HashMap<>();
vars.put("user", user);
Boolean result = (Boolean) MVEL.eval(expr, vars);

MVEL 支持几乎所有 Java 类型的方法调用、集合操作。
但它没有 DRL 那种“匹配-召回”机制——只能一次算个值。

关键区别:DRL 是“条件触发动作”,MVEL 是“表达式求值”。
前者适合复杂推理,后者适合快速判断。

MVEL 的常见用法

  • 属性判断:item.price > 100
  • 函数调用:str.substring(0, 5)
  • 集合操作:list.contains(item)
  • 三元表达式:age > 18 ? "adult" : "child"
我曾经在风控规则里用 MVEL 做实时特征计算:
“最近 5 分钟失败次数 > 10”直接用 MVEL 写,
比写 DRL 的 accumulate 快得多。

4. 语言选择建议

实际项目里,往往混合使用两种语言。
我整理了一张对比表:

场景 推荐语言 原因
复杂多规则推理 DRL Rete 网络优化,支持规则链
简单条件判断 MVEL 写一行就行,不用建规则文件
动态配置(如黑名单阈值) MVEL 可从数据库加载,热更新
需要 session 与状态管理 DRL 天然支持 session 和 agenda
注意:不要把 MVEL 直接用在对外接口上——
它支持任意 Java 代码执行,容易产生注入风险。
我同事就曾因为把用户输入当 MVEL 表达式执行,差点出安全事故。
规则语言体系图 规则语言体系 专用规则语言 通用表达式语言 DRL (Drools) ILR (ILog) MVEL SpEL OGNL 规则语言选择核心原则:逻辑复杂度高 → 专用语言(DRL);动态计算为主 → 通用表达式(MVEL) 实际项目常混合使用,以发挥各自优势

嗯,到这里规则语言这块就差不多了。
记住一点:语言只是工具,真正决定规则质量的,是你对业务逻辑的拆解。
别在语法上纠结太久,先把业务模型吃透。