规则语言基础(DRL、MVEL等)
规则引擎的核心,说白了就是一套描述逻辑的语言。
你写的不再是 if/else,而是用规则语言告诉引擎:
“当 条件 满足时,执行 动作”。
我刚开始用 Drools 的时候,觉得 DRL 语法很像 Java,
结果一跑起来全是编译错误。后来才明白:
规则语言有自己的脾性,不能当普通代码写。
1. 规则语言概览
主流的规则语言大概分两类:
| 类型 | 代表 | 特点 |
|---|---|---|
| 专用规则语言 | DRL(Drools Rule Language) | 声明式、支持 Rete 算法、自带语法糖 |
| 通用表达式语言 | MVEL、SpEL、OGNL | 轻量、可嵌入、常用于条件计算 |
DRL 是 Drools 的亲儿子,从语法到运行都深度绑定。
MVEL 则更像一个“通用胶水”,很多框架(比如流式计算)都在用。
我个人习惯:当规则逻辑复杂(嵌套、聚合、多条件)时选 DRL;
简单条件或动态计算时用 MVEL,省得写一长串规则头。
简单条件或动态计算时用 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 的
“最近 5 分钟失败次数 > 10”直接用 MVEL 写,
比写 DRL 的
accumulate 快得多。
4. 语言选择建议
实际项目里,往往混合使用两种语言。
我整理了一张对比表:
| 场景 | 推荐语言 | 原因 |
|---|---|---|
| 复杂多规则推理 | DRL | Rete 网络优化,支持规则链 |
| 简单条件判断 | MVEL | 写一行就行,不用建规则文件 |
| 动态配置(如黑名单阈值) | MVEL | 可从数据库加载,热更新 |
| 需要 session 与状态管理 | DRL | 天然支持 session 和 agenda |
注意:不要把 MVEL 直接用在对外接口上——
它支持任意 Java 代码执行,容易产生注入风险。
我同事就曾因为把用户输入当 MVEL 表达式执行,差点出安全事故。
它支持任意 Java 代码执行,容易产生注入风险。
我同事就曾因为把用户输入当 MVEL 表达式执行,差点出安全事故。
嗯,到这里规则语言这块就差不多了。
记住一点:语言只是工具,真正决定规则质量的,是你对业务逻辑的拆解。
别在语法上纠结太久,先把业务模型吃透。