drools的简单入门案例场景分析(drools规则引擎实战案例)

网友投稿 484 2022-07-29


目录一、背景1.Drools介绍二、为什么要学习drools三、实现上方这个简单的打折案例1、引入jar包2、编写kmodule.xml配置文件3、编写规则文件1、规则文件的语法2、编写规则文件3、解释一下包名四、编写java代码1、编写一个订单对象2、编写测试代码五、测试结果六、drools引擎的基本组件七、完整代码八、参考文档

一、背景

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

1.Drools介绍

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

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

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

二、为什么要学习drools

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

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

1、引入jar包

org.drools

drools-bom

pom

7.69.0.Final

import

org.drools

drools-compiler

org.drools

drools-mvel

ch.qos.logback

logback-classic

1.2.11

2、编写kmodule.xml配置文件

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

此处我们需要关注一下 kbase下package的值,这个值需要和规则文件中的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、编写一个订单对象

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

/**

* 客户购买衣服的订单,省略 getter 和 setter 方法

*

* @author huan.fu

* @date 2022/5/12 - 11:27

*/

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;

/**

* drools 测试类

*/

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,因为

// 中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();

http:// 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对象进行模式匹配,匹配成功的规则将被激活并放入到Agendahttp://中。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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java深入探究关键字abstract的使用(java中abstract关键字的用法)
下一篇:java泛型中占位符T和?有什么区别(java泛型?和T的区别)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~