深入浅出 Drools 规则引擎

目录

一、规则引擎简介

        1.1 应用场景

        1.2 Drools 规则引擎的特点

二、规则引擎集成

三、核心概念

        3.1 规则文件的组成

        3.2 模式匹配

        3.2 规则属性


一、规则引擎简介

        规则引擎是一种软件系统组件,设计目的是将业务决策逻辑从应用程序的主流程中解耦出来,使得业务规则可以独立于应用程序代码进行管理和变更。这种机制极大地提高了业务灵活性和可维护性,尤其是在那些业务规则频繁变动或者十分复杂的环境中。

        本文将介绍 Drools 的基本概念和简单引用,让你能快速上手使用 Drools 规则引擎。

        1.1 应用场景

        规则引擎的应用领域十分广泛,比如如下应用场景

  1. 决策支持系统:在金融、保险、医疗等行业中,Drools 可用于构建复杂的决策流程,比如金融行业的风控反欺诈系统、信贷审批、催收分案、支付路由等有广泛的使用
  2. 动态配置与策略管理:电信、电子商务等领域中,可以根据用户行为、市场条件等动态调整服务策略或营销活动规则。
  3. 合规性检查:在银行业、证券业和其他监管严格的行业,Drools 可用来实时验证交易是否符合法规要求。
  4. 物联网(IoT)智能决策:在处理大量传感器数据时,可以利用 Drools 实现基于规则的数据分析和实时决策响应。

        1.2 Drools 规则引擎的特点

  1. 业务与代码分离:Drools 支持业务专家使用自然语言式的规则描述,将业务逻辑从程序代码中抽离出来,便于业务人员维护和更新规则。
  2. 声明式编程:通过规则文件定义业务逻辑,而非传统的命令式编程,更加直观且易于理解。
  3. 复杂事件处理(CEP):能够对连续发生的事件流进行实时分析,触发相应的规则动作。
  4. 推理能力:支持Rete算法优化规则匹配,对于大规模规则集也能保证高效的推理执行。
  5. 可扩展性:Drools 不仅是一个规则引擎,还提供了完整的规则生命周期管理,包括规则的创建、存储、测试、部署和监控等功能。
  6. 集成性:Drools 可以无缝集成到Java应用程序中,并与其他企业级框架和技术良好兼容。

二、规则引擎集成

        下面以电商满减为例,演示下如何集成 Drools。

        首先是添加依赖

// 这里只添加 Drools 相关依赖,其他依赖请自行添加
<dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-api</artifactId>
            <version>${drools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>${drools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-decisiontables</artifactId>
            <version>${drools.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>poi-ooxml</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>poi</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jbpm</groupId>
            <artifactId>jbpm-test</artifactId>
            <version>${drools.version}</version>
        </dependency>

        第二步,配置 Drools 配置类

@Configuration
public class DroolsConfig {

    // 规则文件路径
    private static final String RULE_PATH = "rules/test.drl";

    @Bean
    public KieContainer kieContainer() {
        // 设置日期格式
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        // 将规则添加到 KieFileSystem 中
        kieFileSystem.write(ResourceFactory.newClassPathResource(RULE_PATH));
        // 构建 kieBuilder 编译规则
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        Results results = kieBuilder.getResults();
        if (results.hasMessages(Message.Level.ERROR)) {
            throw new IllegalStateException(">>> Error Messages:\n" + results.getMessages());
        }
        // 获取KieModule
        KieModule kieModule = kieBuilder.getKieModule();
        // 创建KieContainer,装载模块
        return kieServices.newKieContainer(kieModule.getReleaseId());
    }
}

        第三步,在 resources 下添加规则文件

package com.order.rules

import com.scf.drools.model.Order

// 规则文件中函数定义
function boolean orderIsNull(Order order) {
    // 规则中通过 eval 来调用函数
    return order == null;
}


// 规则的默认执行顺序是从上向下执行,可以通过 salience 指定执行顺序

// 规则一:消费金额 100-200 优惠10元
rule "order_1"
    date-effective "2024-04-02 00:00:00" // 生效时间
    date-expires "2024-04-03 23:59:59"  // 失效时间
    when
        $order: Order(originalPrice >= 100 && originalPrice < 200)
    then
        $order.setRealPrice($order.getOriginalPrice() - 10);
        // 执行update后,会重新插入到工作内充中匹配其他规则
        // update($order)
    end

// 规则二:消费金额 200-300 优惠20元
rule "order_2"
    when
        $order: Order(originalPrice >= 200 && originalPrice < 300)
    then
        $order.setRealPrice($order.getOriginalPrice() - 20);
        update($order)
    end

// 规则三:消费金额 300-400 优惠30元
rule "order_3"
    when
        $order: Order(originalPrice >= 300 && originalPrice < 400)
    then
        $order.setRealPrice($order.getOriginalPrice() - 30);
        update($order)
    end

                第四步,根据插入的 fact 运行相应的规则

package com.scf.drools.service;

import com.scf.drools.model.Order;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class RuleEngineService {

    @Autowired
    private KieContainer kieContainer;

    public void execute(Order fact) {
        KieSession kieSession = kieContainer.newKieSession();
        try {
            kieSession.insert(fact);
            kieSession.fireAllRules();
        } finally {
            kieSession.dispose();
        }
    }
}

        当方法被调用时,就会自动取匹配规则,并执行相应的代码,如果没有规则引擎,大概率是写一堆的 if else 来判断不同的业务逻辑,当然这个例子不叫简单,如果业务非常复杂,试想你将写出什么样的 if else 代码。

三、核心概念

        3.1 规则文件的组成

package ....

import ....


rule "ruleName"
    attributes
    when
        LHS
    then
        RHS
end

        规则文件由以下几部分组成

  • package:包名,逻辑单位,同一个包下查询或者函数可以直接调用
  • import:用于导入类或静态方法
  • global:全局变量
  • function:自定义函数
  • query:定义一个查询语句,这个查询语句不会像规则那样自动触发,而是供您在应用程序中主动调用,用于检索满足特定条件的事实对象集合
  • rule end:规则体,规则体语法中包含的内容如下:
    • rule:关键字,标识开始,参数为唯一的规则名称
    • attrbutes:规则属性,为可选项,包括 date-effective 等
    • LHS:规则条件部分,只有规则条件成立才会进入到 RHS
    • RHS:规则的后果或行动部分,条件成立后,在这部分做相应的操作
    • end:关键字,标识一个规则的结束

        3.2 模式匹配

        匹配器可以将 rule base 中所有规则与 working memory 中的 fact 对象进行模式匹配,我们需要在 LHS 不分定义规则并进行模式匹配。LHS 不分由一个或多个条件组成,条件称为 pattern。

        pattern 的语法结构为:绑定的变量名:Object(filed约束)。比如 $order : Order(originalPrice >= 100),在 LHS 中比较符有下面这些:

符号

说明

>

大于

<

小于

>=

大于等于

<=

小于等于

==

等于

!=

不等于

contains

检查一个fact对象的某个属性值是否包含一个执行的对象值

not contains

检查一个fact对象的某个属性值是否不包含一个执行的对象值

member of

判断一个fact对象的某个属性是否存在一个或多个集合中

not member of

判断一个fact对象的某个属性是否不在一个或多个集合中

matchers

判断一个fact对象的属性是否与提供的标准的java正则表达式进行匹配

not matchers

判断一个fact对象的属性是否不与提供的标准的java正则表达式进行匹配

        3.2 规则属性

        Drools 规则引擎中的规则可以包含多种属性以控制规则的行为、执行顺序以及与其他规则的关系。以下是一些常用的规则属性及其用途: 

属性名

说明

salience

指定规则执行顺序,默认顺序是规则书写顺序

dialect

指定规则语言的类型,一种是java一种是mvel

enable

规则是否启动

date-effective

指定规则生效时间

date-expires

指定规则失效时间

activation-group

激活分组,具有相同分组名称的规则只能有一个规则触发

agenda-group

议程分组,只有获取焦点的组中的规则才有可能触发,组内规则不互斥

timer

定时器,指定规则触发时间

auto-focus

自动获取焦点,一般结合agenda-group一起使用

no-loop

防止死循环

ock-on-active

控制规则在特定条件下是否能够被多次执行。当规则由于满足条件而激活并进入执行阶段后,如果由于规则执行过程中改变了工作内存(Working Memory)中的事实,导致原本已经激活并正在执行的规则的条件再次满足,那么在lock-on-active为true的情况下,该规则不会再被重新激活和执行。

        规则还可以通过继承拿到 LHS 部分,语法:rule "rule1" extends "rule2" ,rule1继承了rule2,同时只会继承LHS部分。

        通过这节介绍相信你对如何使用 Drools 已经非常清楚了,后面的文章将继续介绍其原理和高阶应用,欢迎关注。

往期经典推荐:

系统优化都没做过?看这篇就够了-CSDN博客

MySQL为什么会选错索引-CSDN博客

一文掌握Java动态代理的奥秘与应用场景-CSDN博客

一文看懂Nacos如何实现高效、动态的配置中心管理_nacos配置中心-CSDN博客

Redis 6.0进化之路:关键新特性详解_redis6.0新特性-CSDN博客

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超越不平凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值