我的编程空间,编程开发者的网络收藏夹
学习永远不晚

drools的简单入门案例场景分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

drools的简单入门案例场景分析

一、背景

最近在学习规则引擎drools,此处简单记录一下drools的入门案例。

1.Drools介绍

drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。

drools官网地址:https://drools.org/

drools源码下载地址:https://github.com/kiegroup/drools
-----------------------------------
Drools:概述和入门案例:https://www.jb51.net/article/248263.htm

二、为什么要学习drools

假设我们存在如下场景:
在我们到商店购买衣服的时候,经常会发生这样的事情,购买1件不打折,购买2件打0.98折,购买3件级以上打0.85折。
那么我们在代码中如果要实现上述功能,是不是就需要编写if ... else语句,假设后期规则变了,是不是就需要修改这些if ... else语句,然后程序重新部署。这样是可以实现,但是不够优雅。那么我们是否可以将这些业务规则写入到规则文件中,以后规则变更直接修改规则文件即可?而drools就可以实现这个功能。

三、实现上方这个简单的打折案例

1、引入jar包

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-bom</artifactId>
            <type>pom</type>
            <version>7.69.0.Final</version>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
       <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-mvel</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>
    </dependency>
</dependencies>

2、编写kmodule.xml配置文件

此配置文件需要放置在resources/META-INF目录下。

<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <!--
        kbase 可以存在多个
        name: 指定kbase的名字,需要是唯一的
        packages: 包名,可以理解为到class="lazy" data-src/main/resources目录下查找这个包名下的规则文件,多个包使用逗号分割
        default: 当前kbase是否是默认的kbase
    -->
    <kbase name="shop-kabse" packages="com.huan.shop" default="false">
        <!--
            ksession 可以存在多个
            name: 指定ksession 的名字,需要唯一
            defalut: 当前ksession在这个kbase下是否是默认的
            type: 指定当前ksession是否是有状态的 stateless表示是无状态的
        -->
        <ksession name="shop-ksession" default="false" type="stateless"/>
        <ksession name="shop-ksession-stateful" default="false" type="stateful"/>
    </kbase>
</kmodule>

此处我们需要关注一下 kbasepackage的值,这个值需要和规则文件中的package值一致,否则会找不到规则,具体看下方。

3、编写规则文件

1、规则文件的语法

包名,必须放置在第一行
package
// 引入Java中的类,需要些全限定名
import
// 定义function ,可选
function  // Optional
// 定义 query ,可选
query  // Optional
declare   // Optional
global   // Optional
// rule 关键字 "rule name" 规则的名字
rule "rule name"
    // Attributes 属性可选
    when  // 关键字
        // Conditions  条件,可为空
    then
        // Actions // 匹配后执行的结果
end // 关键字

2、编写规则文件

规则文件的名字无所谓,比如: book-discount.drl

// 包名,必须防止到第一行,这个名字需要和 kbase中package属性的值一致
package com.huan.shop

import com.huan.drools.CustomerOrder
// 定义规则
rule "shop-rule-01"
    when
        // 模式匹配:到工作内存中查找CustomerOrder,并且这个对象的purchaseQuantity值需要是1,
        // 如果条件成立,$order是绑定变量名,一般以$开头,和fact对象区分开
        $order:CustomerOrder(purchaseQuantity == 1)
    then
        System.out.println("匹配规则 shop-rule-01");
        // 赋值,此处赋值后,在Java代码中获取获取到赋值后的值
        $order.setDiscount(1D);
end
rule "shop-rule-02"
    when
        $order:CustomerOrder(purchaseQuantity == 2)
    then
        System.out.println("匹配规则 shop-rule-02");
        $order.setDiscount(0.98);
end
rule "shop-rule-03"
    when
        $order:CustomerOrder(purchaseQuantity >= 3)
    then
        System.out.println("匹配规则 shop-rule-03");
        $order.setDiscount(0.85);
end

3、解释一下包名

如果 shop-discount.drl的包名修改为com.huan.shop1则会提示如下警告:

12:43:01.589 [main] WARN org.drools.compiler.kie.builder.impl.KieBuilderImpl - File 'com/huan/shop/shop-discount.drl' is in folder 'com/huan/shop' but declares package 'com.huan.shop1'. It is advised to have a correspondance between package and folder names.

四、编写Java代码

1、编写一个订单对象

此对象保存的是用户购买了几件衣服和对应的折扣。


public class CustomerOrder {
    
    private Integer purchaseQuantity;
    
    private Double discount;
    public CustomerOrder(Integer purchaseQuantity) {
        this.purchaseQuantity = purchaseQuantity;
    }
}

2、编写测试代码

1、无状态测试方法statelessSessionTest规则规则2,即最终打0.98折。
2、有状态测试方法statefulSessionTest规则规则3,即最终打0.85折。

package com.huan.drools;
import org.kie.api.KieServices;
import org.kie.api.event.rule.DebugRuleRuntimeEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;

public class DroolsApplication {
    public static void main(String[] args) throws InterruptedException {
        // 无状态session测试
        statelessSessionTest();
        // 有状态session测试
        statefulSessionTest();
    }
    private static void statelessSessionTest() {
        // 获取kie services
        KieServices kieServices = KieServices.get();
        // 获取kie容器对象
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        // 获取kie session , 此处获取的是无状态的session,因为 <ksession name="shop-ksession" default="false" type="stateless"/>
        // 中type="stateless"就是无状态的session
        StatelessKieSession kieSession = kieContainer.newStatelessKieSession("shop-ksession");
        // 创建一个对象,可以理解为 Fact对象,即事实对象
        CustomerOrder customerOrder = new CustomerOrder(2);
        // 添加监听器,便于观察日志
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());
        // 无状态的session只需要执行 execute 方法即可。
        kieSession.execute(customerOrder);
        System.err.println("通过规则后,获取到的折扣为:" + customerOrder.getDiscount());
    }
    private static void statefulSessionTest() {
        // 获取kie services
        KieServices kieServices = KieServices.get();
        // 获取kie容器对象
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        // 获取kie session , 此处获取的是有状态的session
        KieSession kieSession = kieContainer.newKieSession("shop-ksession-stateful");
        // 创建一个对象,可以理解为 Fact对象,即事实对象
        CustomerOrder customerOrder = new CustomerOrder(3);
        // 添加监听器,便于观察日志
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());
        // 将customerOrder对象加入到工作内存中
        kieSession.insert(customerOrder);
        // 触发所有的规则,如果只想触发指定的规则,则使用fireAllRules(AgendaFilter agendaFilter)方法
        kieSession.fireAllRules();
        // 有状态的session一定需要调用dispose方法
        kieSession.dispose();
        System.err.println("通过规则后,获取到的折扣为:" + customerOrder.getDiscount());
    }
}

此处需要注意有状态session无状态session写法的区别。

五、测试结果

到此,我们使用drools实现的一个简单的案例就实现了。

六、drools引擎的基本组件

1、Rules:我们自己定义的业务规则,比如我们自己写的规则文件。所有规则必须至少包含触发规则的条件和规则规定的操作。
2、Production memory:规则存储在 Drools 引擎中的位置。
3、Facts:输入或更改到 Drools 引擎中的数据,Drools 引擎匹配规则条件以执行适用规则。在规则中修改了Fact对象的值,真实的JavaBean的数据也会发生改变。
比如:当我们调用ksession.insert(对象),那么插入的这个对象就可以理解成Facts对象。
4、Working memory:facts 在 Drools 引擎中存储的位置。
5、Pattern matcher:匹配器,将Rule Base中所有的规则与Working memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入到Agenda中。
6、Agenda:议程,执行Agenda中被激活的排好序的规则。

七、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-quickstart

八、参考文档

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#decision-engine-con_decision-engine

到此这篇关于drools的简单入门案例的文章就介绍到这了,更多相关drools入门案例内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

drools的简单入门案例场景分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

drools入门案例分析

今天小编给大家分享一下drools入门案例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、背景最近在学习规则引擎dro
2023-06-30

Java注解的简单入门小案例

这篇文章主要介绍了Java注解的简单入门小案例,注解是干什么的?怎么使用?注解的简单用法,需要的朋友可以参考下
2023-05-14

Go语言泛型的应用场景和案例分析

Go语言自从发布以来一直以其简洁、高效和并发性能而备受开发者青睐。然而,长期以来一直受到开发者们诟病的一点就是缺乏泛型支持。在2021年的Go语言1.18版本中,泛型正式成为了标准特性,为开发者们带来了更加灵活和高效的编程体验。本文将深入探
Go语言泛型的应用场景和案例分析
2024-03-10

Python中使用插入排序算法的简单分析与代码示例

问题描述 将一组随机排列的数字重新按照从小到大的顺序排列。 插入算法 每次从数组中取一个数字,与现有数字比较并插入适当位置。 如此重复,每次均可以保持现有数字按照顺序排列,直到数字取完,即排序成功。 这很像打牌时的抓牌情况, 第一个条件:保
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录