规则引擎—Drools 语法第一天[学习笔记]

1.为什么要用规则引擎?

eg:商场商品打折(逻辑与规则如下表)

规则编号购买总金额折扣
1total<1000.9
2100<= total <5000.8
3total>=5000.7

     正常思维如何实现以上逻辑?无非就是if-else分支来判断。

//伪代码

if(total < 100) {
    total *= 0.9;
}else if(total < 500) {
    total *= 0.8;
}else {
    total *= 0.7;
}

此逻辑是通过java代码方式实现的,但存在问题:

硬编码实现业务规则难以维护,难以应对变化,业务规则发生变化需要修改java代码,重启服务才能生效,此操作过于麻烦。

并且 每个节日 打折方式不同,我们不可能每次都去改java代码,并且重启服务器。所以规则引擎就可以解决我们这样的问题。

2.规则引擎 

简介:

       规则引擎,全称为业务规则管理系统,由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。在Java中,大多数流行的规则引擎都实现JSR94。

        他并不是一种具体的技术框架,而是指一类系统,及业务规则系统。比如:drools、ILog等。

优点:

  • 简化系统架构,优化应用
  • 提高系统的可维护性
  • 减少编写“硬代码”业务规则的成本和风险
  • 应付特殊状况,即客户一开始没有提到要将业务逻辑考虑在内
  • 过将规则引擎分开,它提供了更大的可重用性。

应用场景: 

  • 流程分支非常复杂,规则变量庞大
  • 有不确定性的需求,变更频率较高
  • 需要快速做出响应和决策
  • 规则变更期望脱离于开发人员,脱离coding

3.Drools介绍

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

在项目中使用Drools,可以直接在IDEA工具中下载Drools插件。

使用:

①单独使用,在pom.xml文件中

//添加依赖
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.6.0.Final</version>
</dependency>

也可以集成spring、SpringBoot框架使用,之后会说.......

    drools API 开发步骤: 

      ①获取KieServices

      ②获取KieContainer

      ③获取KieSession

      ④Insert fact(事实对象,接收数据的对象实体类)

      ⑤触发规则 fireAllrules()

      ⑥关闭KieSession

4.具体入门案例:

业务场景:消费者在商场消费,优惠折扣如下表:

规则编号购买总金额折扣
1total<300不打折
2300<= total <5000.9
3500<=total<8000.8
4total>=8000.7

开发实现 :

①创建maven项目,添加依赖

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.10.0.Final</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

② 在resource文件夹下META-INF中创建kmoudle.xml配置文件(文件名称和位置,固定写法,不可改变)

<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <!--
        name:指定kbase的名称,可以任意,但是需要唯一
        packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
        default:指定当前kbase是否为默认
    -->
    <kbase name="myKbase1" packages="rules" default="true">
        <!--
            name:指定ksession名称,可以任意,但是需要唯一
            default:指定当前session是否为默认
        -->
        <ksession name="ksession-rule" default="true"/>
    </kbase>
</kmodule>

 ③创建实体类Goods 创建的对象相当于事实对象。

package com.simia.drools.entity;
​
/**
 * 商品
 */
public class Goods {
    private String name;
    private Double originalPrice;//商品原始价格,即优惠前价格
    private Double realPrice;//商品真实价格,即优惠后价格
​
    public String toString() {
        return "Goods{" +
                "name=" + name +
                ", originalPrice=" + originalPrice +
                ", realPrice=" + realPrice +
                '}';
    }
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public Double getOriginalPrice() {
        return originalPrice;
    }
​
    public void setOriginalPrice(Double originalPrice) {
        this.originalPrice = originalPrice;
    }
​
    public Double getRealPrice() {
        return realPrice;
    }
​
    public void setRealPrice(Double realPrice) {
        this.realPrice = realPrice;
    }
}

fact对象是用来接收数据进入规则引擎与规则匹配进行相对应业务的。

 ④编写规则文件(在resource->rules->goodsDiscount.drl)

//商品优惠规则
package good.discount
import com.simia.drools.entity.Goods
​
//规则一:所购总价在300元以下的没有优惠
rule "good_discount_1"
    when
        $order:Order(originalPrice < 300)
    then
        $order.setRealPrice($order.getOriginalPrice());
        System.out.println("成功匹配到规则一:所购总价在300元以下的没有优惠");
end
​
//规则二:所购总价在300到500元的打9折
rule "good_discount_2"
    when
        $order:Order(originalPrice < 500 && originalPrice >= 300)
    then
        $order.setRealPrice($order.getOriginalPrice()*0.9);
        System.out.println("成功匹配到规则二:所购总价在300到500元的打9折");
end
​
//规则三:所购总价在500到800元的打8折
rule "good_discount_3"
    when
        $order:Order(originalPrice <= 300 && originalPrice >= 200)
    then
        $order.setRealPrice($order.getOriginalPrice()*0.8);
        System.out.println("成功匹配到规则三:所购总价在500到800元的打8折");
end
​
//规则四:所购总价在800元以上的打7折
rule "good_discount_4"
    when
        $order:Order(originalPrice >= 800)
    then
        $order.setRealPrice($order.getOriginalPrice()*0.7);
        System.out.println("成功匹配到规则四:所购总价在800元以上的打7折");
end

⑤编写单元测试 

@Test
public void test1(){
    KieServices kieServices = KieServices.Factory.get();
    KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
    //会话对象,用于和规则引擎交互
    KieSession kieSession = kieClasspathContainer.newKieSession();
​
    //构造订单对象,设置原始价格,由规则引擎根据优惠规则计算优惠后的价格
    Order order = new Order();
    order.setOriginalPrice(500D);
​
    //将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配
    kieSession.insert(order);
​
    //激活规则引擎,如果规则匹配成功则执行规则
    kieSession.fireAllRules();
    //关闭会话
    kieSession.dispose();
​
    System.out.println("优惠前原始价格:" + order.getOriginalPrice() +
                       ",优惠后价格:" + order.getRealPrice());
}

总结:由此入门案例可以发现drools工具就是来写drl规则文件的,那drl写业务规则和java代码写有什么区别呢?

          drl文件写业务规则,可以不用重新启动服务,就可以直接使用,实现业务规则的动态化管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。而java硬代码达不到。 

5.规则引擎总结 

构成:

Working Memory:工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可,例如本案例中我们调用kieSession.insert(order)就是将order对象插入到了工作内存中。

Fact:事实,是指在drools 规则应用当中,将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象,例如本案例中的Order对象就属于Fact对象。Fact对象是我们的应用和规则引擎进行数据交互的桥梁或通道。

Rule Base:规则库,我们在规则文件中定义的规则都会被加载到规则库中。

Pattern Matcher:匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。

Agenda:议程,用于存放通过匹配器进行模式匹配后被激活的规则。

Execution Engine:执行引擎,执行Agenda中被激活的规则。

 规则引擎执行过程:

kie介绍

通过上面的核心API可以发现,大部分类名都是以Kie开头。Kie全称为Knowledge Is Everything,即"知识就是一切"的缩写,是Jboss一系列项目的总称。如下图所示,Kie的主要模块有OptaPlanner、Drools、UberFire、jBPM。

 通过上图可以看到,Drools是整个KIE项目中的一个组件,Drools中还包括一个Drools-WB的模块,它是一个可视化的规则编辑器。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值