第3章 Drools入门:从零跑通第一个规则

好,咱们正式开始接触Drools。这一章的目标很简单——让你亲手写一个能跑的规则文件,并且在Java代码里调用它。我见过不少新手卡在环境搭建和Session概念上,其实没那么复杂。跟着我走一遍,半小时内你就能看到控制台打印出“Hello World”。

3.1 Drools到底是什么?

Drools是一个基于Rete算法的规则引擎。说白了,它就是一个“如果…就…”的自动执行器。你把业务规则写在.drl文件里,把数据塞进去,它自动匹配、自动执行。

我个人习惯把Drools理解成一个“超级if-else处理器”。你想想看,传统代码里写几十个if-else,维护起来多痛苦。Drools把条件和动作分离,规则变了改文件就行,不用重新编译部署。

核心能力: 规则与代码解耦、动态修改、高性能匹配。

3.2 Maven依赖配置

我用的是Maven项目。别问为什么不用Gradle,团队里统一用Maven,我也习惯了。先贴依赖,版本我用的是7.73.0.Final,比较稳定。

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.73.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.73.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-mvel</artifactId>
    <version>7.73.0.Final</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.36</version>
</dependency>

避坑: 我曾经遇到过drools-compiler和drools-core版本不一致,启动直接报ClassNotFoundException。记住,三个drools依赖的版本号必须完全一致。

3.3 第一个Hello World规则文件

规则文件后缀是.drl。我习惯放在src/main/resources/rules目录下。新建一个hello.drl,内容如下:

package com.example.rules

import com.example.model.Person

rule "Hello World"
    when
        $p: Person(age > 18)
    then
        System.out.println("Hello, " + $p.getName() + "! 你已经成年了。");
end

解释一下:

  • package:规则包的命名空间,类似Java包名。
  • import:导入要使用的Java类。
  • rule:定义一个规则,后面跟规则名称。
  • when:条件部分,这里匹配年龄大于18的Person对象。
  • then:动作部分,满足条件后执行。

对应的Java模型类:

package com.example.model;

public class Person {
    private String name;
    private int age;

    // getter和setter必须写,Drools靠它们访问属性
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

注意: DRL文件里的import路径必须和Java类的全限定名一致。大小写敏感,别写错了。

3.4 KIE Session的创建与使用

KIE Session是Drools的执行入口。我刚开始学的时候,老觉得这个概念很抽象。其实你就把它当成一个“规则执行容器”——你把数据放进去,它帮你跑规则。

创建Session的标准步骤:

  1. 构建KieServices实例(入口)
  2. 获取KieContainer(管理规则文件的容器)
  3. 从KieContainer创建KieSession
  4. 插入数据(insert)
  5. 触发规则执行(fireAllRules)
  6. 释放资源(dispose)

看代码:

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class DroolsHelloWorld {
    public static void main(String[] args) {
        // 1. 获取KieServices
        KieServices ks = KieServices.Factory.get();

        // 2. 获取KieContainer(自动加载classpath下的kmodule.xml和drl文件)
        KieContainer kContainer = ks.getKieClasspathContainer();

        // 3. 创建KieSession,名称对应kmodule.xml中的ksession name
        KieSession kSession = kContainer.newKieSession("helloSession");

        // 4. 准备数据
        Person p = new Person();
        p.setName("张三");
        p.setAge(20);

        // 5. 插入数据到Session
        kSession.insert(p);

        // 6. 触发规则执行
        kSession.fireAllRules();

        // 7. 释放资源
        kSession.dispose();
    }
}

还需要一个kmodule.xml文件,放在src/main/resources/META-INF目录下:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="helloKBase" packages="rules">
        <ksession name="helloSession"/>
    </kbase>
</kmodule>

个人经验: 我早期犯过一个低级错误——忘了在resources目录下建META-INF文件夹,结果KieContainer一直报空指针。检查了半小时才发现。嗯,目录结构一定要对。

3.5 核心流程可视化

下面这张图展示了从规则文件到执行结果的完整链路。我画得比较直观,你一看就明白。

Drools规则执行流程 .drl 规则文件 kmodule.xml Java POJO模型 KieContainer KieSession insert + fireAllRules 控制台输出结果 关键动作 1. insert() 插入事实 2. fireAllRules() 触发匹配

3.6 运行与验证

直接运行main方法。如果一切正常,控制台会输出:

Hello, 张三! 你已经成年了。

没输出?别急。检查这几项:

  • Person类的getter/setter是否完整?Drools通过反射调用它们。
  • kmodule.xml里的ksession name是否和代码里一致?
  • drl文件是否放在resources/rules目录下?
  • 依赖版本是否冲突?

我曾经踩过的坑: 有一次规则怎么都不触发,查了半天发现是Person类里age字段写了Integer,但规则里判断的是int。Drools对类型匹配很严格,包装类型和基本类型不能混用。

3.7 本章小结

这一章我们走通了Drools的完整链路:从Maven依赖、规则文件编写、KIE Session创建到执行。你想想看,核心就三步:写规则、建Session、触发执行。后面的章节会在这个基础上不断扩展,但底子就是这些。

嗯,记住一个原则:规则引擎不是银弹,但它能把频繁变化的业务逻辑从代码里抽出来。这一章你亲手跑通了,后面学起来会轻松很多。