Drools 规则引擎:声明式业务逻辑
规则引擎 Drools:声明式业务逻辑
为什么需要规则引擎?
在传统 Java 开发中,业务逻辑往往以命令式代码形式嵌入系统——大量的 if-else、switch 与多层嵌套判断。当规则频繁变更时,修改代码、测试、部署的成本极高,且业务人员无法直观理解程序中的规则。
规则引擎将业务决策从应用代码中分离,以声明式方式描述“在什么条件下执行什么动作”。这带来了三大核心价值:
- 业务可读性:规则使用接近自然语言的 DSL 编写,业务人员也能参与维护。
- 变更灵活性:修改规则无需重新编译、部署应用,可实现热加载。
- 逻辑集中管理:所有规则统一存放,避免分散在代码各处导致的维护黑洞。
Drools 正是 Java 生态中最成熟、功能最全面的开源规则引擎。
什么是 Drools?
Drools 是 Red Hat 旗下的开源业务规则管理系统 (BRMS),提供规则引擎、决策表、复杂事件处理(CEP)等能力。其核心基于 Rete 算法 的高效模式匹配网络,能够在对大量事实(数据)与规则进行匹配时保持优异性能。
Drools 使用 DRL (Drools Rule Language) 定义规则,语法简洁,支持与 Java 无缝集成,很容易嵌入任意 Java 应用。
核心概念速览
在动手之前,先理解 Drools 的四个核心角色:
| 概念 | 说明 |
|---|---|
| Fact(事实) | 输入到规则引擎的数据对象,通常是普通的 POJO。 |
| Rule(规则) | 由条件(LHS)和动作(RHS)组成的业务逻辑单元。 |
| KieSession(会话) | 规则执行的核心运行时,持有规则库和插入的事实,并触发推理。 |
| KieBase(知识库) | 编译后的规则集合,可以从 DRL、决策表等资源创建。 |
简单执行流程:创建 KieBase → 创建 KieSession → 插入事实 → 触发所有匹配规则 → 执行动作。
环境准备
推荐使用 Maven 快速构建,引入核心依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<version>8.44.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
</dependencies>
提示:若使用 Spring Boot,可集成
kie-spring-boot-starter,后文会给出示例。
第一个 Drools 规则:Hello World
假设我们要实现一个简单的会员积分奖励规则:消费超过 100 元送 10 积分。
1. 定义事实对象
public class Order {
private double amount;
private int points;
// 构造函数、getter/setter 省略
}
2. 编写 DRL 规则文件(rules/order.drl)
package com.example.rules
import com.example.Order
rule "Give 10 points for orders over 100"
when
$order : Order( amount > 100 )
then
$order.setPoints( $order.getPoints() + 10 );
System.out.println("Order " + $order + " gets 10 points.");
end
3. 在 Java 中执行规则
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer(); // 自动加载 classpath 下的 kmodule.xml 及规则
KieSession session = kc.newKieSession("ksession-rules");
Order order = new Order(120, 0);
session.insert(order); // 插入事实
session.fireAllRules(); // 触发所有匹配的规则
session.dispose();
System.out.println("Final points: " + order.getPoints()); // 输出 10
META-INF 下需放置 kmodule.xml 配置:
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules" packages="rules">
<ksession name="ksession-rules"/>
</kbase>
</kmodule>
DRL 规则语法精要
Drools 规则采用 rule...end 块,基本结构如下:
rule "规则名称"
attributes // 可选属性,如 no-loop, salience, date-effective
when
// 条件(LHS – Left Hand Side)
then
// 动作(RHS – Right Hand Side)
end
条件部分 (LHS):模式匹配
- 字段约束:
Order(amount > 100),支持>,<,==,!=,contains,matches等。 - 绑定变量:
$order : Order(...)将匹配的事实绑定到变量,后续可使用。 - 多个模式:并列写出,表示“同时满足” (AND 关系)。例如:
when $order : Order(amount > 100) Customer(status == "VIP") from $order.customer - 组合条件:可使用
and、or、not、exists关键字。 - 复杂值操作:
eval()可调用任意 Java 表达式(慎用,影响性能)。
动作部分 (RHS):执行业务
- 直接修改绑定事实的属性,如
$order.setPoints(10)。 - 调用 Java 方法、输出日志、插入新事实 (
insert) 或修改事实 (modify)。 - 使用
drools内置函数:kcontext.getKieRuntime()获取运行时。
常用属性
| 属性 | 功能 |
|---|---|
salience |
优先级,数字越大越先执行,默认 0。 |
no-loop |
防止规则在修改自身导致的事实变化后重新触发,避免死循环。 |
date-effective / date-expires |
生效/失效时间,格式 dd-MMM-yyyy。 |
activation-group |
同一组内仅触发一个规则。 |
agenda-group |
将规则分组,可控制执行流。 |
进阶:使用业务人员友好的决策表
如果规则由非技术人员维护,DRL 文件可能仍有门槛。Drools 支持通过 Excel 决策表 定义规则,将条件-动作映射为表格。
示例:会员等级折扣决策表(.xls 文件)
| RuleSet | 会员折扣计算 |
|---|---|
| RuleTable 会员折扣 | |
| CONDITION | ACTION |
| 消费金额 >= | 等级 == |
| 1000 | "VIP" |
| 500 | "NORMAL" |
在代码中加载决策表只需让 KieBase 加载对应的 .xls 资源即可,Drools 会自动解析。
与 Spring Boot 集成
Spring Boot 项目可使用 kie-spring-boot-starter 快速集成:
- 添加依赖:
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring-boot-starter</artifactId>
<version>8.44.0.Final</version>
</dependency>
- 在
application.yml中配置规则文件路径:
kieserver:
resources: classpath:rules/**/*.drl
- 注入
KieContainer或KieService便可直接使用,无需手动编写kmodule.xml。
最佳实践与性能提示
- 避免在 LHS 中使用
eval:eval会放弃索引优化,尽量使用字段约束。 - 注意
modify与update:修改已存在的事实必须通过modify或update通知引擎,否则规则不会重新评估。 - 使用
no-loop或lock-on-active防止无限循环触发。 - 合理设计事实模型:将频繁变化的数据与静态属性分离,降低重新评估的范围。
- 策略化会话:对于高频调用,可使用
KieSessionPool复用会话,避免频繁创建销毁。
总结
Drools 让开发者从“如何实现”转向“声明规则是什么”,极大提升了业务逻辑的可维护性与敏捷性。本文从核心概念和第一个规则入手,覆盖了 DRL 语法、决策表以及 Spring Boot 集成,为你后续深入学习(复杂事件处理 CEP、规则流、BRMS 等)打下了扎实基础。
将规则外置,迈向声明式业务逻辑,正是企业级应用应对变化的不二选择。