drools中then部分的写法(推荐)

目录
  • 1、背景
  • 2、支持的方法
    • 2.1 insert 插入对象到工作内存中
      • 2.1.1 需求
      • 2.1.2 drl文件编写
      • 2.1.3 部分java代码编写
      • 2.1.4 运行结果
      • 2.1.5 结论
    • 2.2 insertLogical 插入对象到工作内存中
      • 2.2.1 需求
      • 2.2.2 drl文件编写
      • 2.2.3 部分java代码编写
      • 2.2.4 运行结果
      • 2.2.5 结论
    • 2.3、update 更新工作内存中的对象
      • 2.3.1 需求
      • 2.3.2 drl 文件编写
      • 2.3.3 部分java文件编写
      • 2.3.4 运行结果
      • 2.3.4 结论
    • 2.4、modify 更新工作内存中的对象
      • 2.4.1 需求
      • 2.4.2 drl 文件编写
      • 2.4.3 部分java文件编写
      • 2.4.4 运行结果
      • 2.4.5 结论
    • 2.5 delete 删除工作内存中的对象
  • 3、drools变量的简单使用
  • 4、规则的继承
    • 4.1 需求
    • 4.2 drl文件编写
    • 4.3 部分java代码
    • 4.4 运行结果
    • 4.5 结论
  • 5、使用do[...]语法重写上方继承的例子
    • 5.1 需求
    • 5.2 drl文件编写
    • 5.3 部分java代码编写
    • 5.4 运行结果
    • 5.5 结论
  • 6、实现 if else if 的效果
    • 6.1 需求
    • 6.2 规则文件
    • 6.3 执行结果图
    • 6.4 各种执行结果-也就是上图的解释
    • 6.5 do和 break 有什么区别
  • 7.完整代码
  • 8.参考文档

1、背景

此处介绍一下droolsthen部分的写法,以及一些内置的方法,比如insert/delete/modify等等。同时也介绍一下rule的继承,和在when中实现if else if 等操作。

2、支持的方法

drools提供了一些内置的方法,这些方法会修改drools的工作内存Fact对象的值。从而会导致重新进行模式匹配。

2.1 insert 插入对象到工作内存中

insert是向工作内存中插入对象,同时会导致重新进行规则的模式匹配。同时当规则不满足时,不会自动删除。

2.1.1 需求

当发生火灾Fire时,向工作内存中插入一个Alarm对象,告警发生后,删除工作内存中的Fire对象,然后检测Alarm对象是否还存在。

2.1.2 drl文件编写

package rules
import com.huan.drools.insertmethod.Fire
import com.huan.drools.insertmethod.Alarm
rule "insert_发生火灾时,往工作内存中插入告警对象"
    when
        $fire: Fire()
    then
        System.out.println("1、发生火灾时,往工作内存中插入告警对象");
        insert(new Alarm($fire));
end
rule "insert_当规则内存中存在告警对象,进行告警,然后删除火灾对象"
    when
        $fire: Fire()
        $alarm: Alarm( fire == $fire )
    then
        System.out.println("2、进行告警,然后删除对应的火灾对象");
end
rule "insert_检测告警对象是否还是存在-01"
    when
        Alarm()
    then
        System.out.println("3、insert 插入的告警对象还存在");
        // 删除工作内存中的Fire对象
        delete($fire);
end
rule "insert_检测告警对象不存在"
    when
        not Alarm()
    then
        System.out.println("3、insert 插入的告警对象不存在");
end

此处使用的是 insert进行插入

2.1.3 部分java代码编写

// 将火灾对象插入到工作内存中
kieSession.insert(new Fire());
// 只触发规则名称以 insert_ 开头的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("insert_"));

2.1.4 运行结果

1、发生火灾时,往工作内存中插入告警对象
2、进行告警,然后删除对应的火灾对象
3、insert 插入的告警对象还存在

2.1.5 结论

  • insert可以向工作内存中插入Fact对象。
  • insert方法调用后,会导致模式的重新匹配,导致之前不会执行的规则,重新执行。
  • insert方法插入到工作内存的对象,在规则不成立时,不会自动删除,需要手动删除,注意和insertLogical的区别

2.2 insertLogical 插入对象到工作内存中

insert是向工作内存中插入对象,同时会导致重新进行规则的模式匹配。同时当规则不满足时,会自动删除。

2.2.1 需求

当发生火灾Fire时,向工作内存中插入一个Alarm对象,告警发生后,删除工作内存中的Fire对象,然后检测Alarm对象是否还存在。

2.2.2 drl文件编写

package rules
import com.huan.drools.Fire
import com.huan.drools.Alarm
rule "insertLogical_发生火灾时,往工作内存中插入告警对象"
    when
        $fire: Fire()
    then
        System.out.println("1、发生火灾时,往工作内存中插入告警对象");
        insertLogical(new Alarm($fire));
end
rule "insertLogical_当规则内存中存在告警对象,进行告警,然后删除火灾对象"
    when
        $fire: Fire()
        $alarm: Alarm( fire == $fire )
    then
        System.out.println("2、进行告警,然后删除对应的火灾对象");
        delete($fire);
end
rule "insertLogical_检测告警对象是否还是存在-01"
    when
        Alarm()
    then
        System.out.println("3、insertLogical 插入的告警对象还存在");
end
rule "insertLogical_检测告警对象不存在"
    when
        not Alarm()
    then
        System.out.println("3、insertLogical 插入的告警对象不存在");
end

此处使用的是insertLogical插入

2.2.3 部分java代码编写

kieSession.insert(new Fire());
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("insertLogical_"));

2.2.4 运行结果

1、发生火灾时,往工作内存中插入告警对象
2、进行告警,然后删除对应的火灾对象
3、insertLogical 插入的告警对象不存在

2.2.5 结论

  1. insertLogical可以向工作内存中插入Fact对象。
  2. insertLogical方法调用后,会导致模式的重新匹配,导致之前不会执行的规则,重新执行。
  3. insertLogical方法插入到工作内存的对象,在规则不成立时,会自动删除注意和insert的区别

2.3、update 更新工作内存中的对象

update: 使用它来指定要更新的字段和整个相关Fact,并将更改通知 Drools 引擎。 Fact发生更改后,您必须在更改可能受更新值影响的另一个事实之前调用 update。 为避免此添加步骤,请改用 modify 方法。

2.3.1 需求

规则一: 当工作内存中存在火灾对象Fire,并且名字name为空时触发规则,同时在设置火灾的名字为大火灾
规则二: 当火灾存在名字时,输出火灾名字

2.3.2 drl 文件编写

package rules
import com.huan.drools.Fire
import com.huan.drools.Alarm
rule "update_当存在火灾对象时,设置一个火灾的名字"
    when
        $fire: Fire(name == null)
    then
        System.out.println("1、设置火灾名字");
        $fire.setName("大火灾");
        update($fire)
end
rule "update_当火灾对象存在名字时触发"
    when
        $fire: Fire(name != null)
    then
        System.out.println("2、火灾对象的名字为: " + $fire.getName());
end

2.3.3 部分java文件编写

kieSession.insert(new Fire());
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("update_"));

2.3.4 运行结果

1、设置火灾名字
2、火灾对象的名字为: 大火灾

2.3.4 结论

  • update会导致模式的重新匹配。
  • update会修改工作对象内存中的值。

2.4、modify 更新工作内存中的对象

modify: 使用它来指定要为Fact对象修改的字段并将更改通知 Drools 引擎。 此方法提供了一种结构化的事实更新方法。 它将更新操作与 setter 调用相结合以更改对象字段。

2.4.1 需求

规则一: 当工作内存中存在火灾对象Fire,并且名字name为空时触发规则,同时在设置火灾的名字为大火灾
规则二: 当火灾存在名字时,输出火灾名字

2.4.2 drl 文件编写

package rules
import com.huan.drools.Fire
import com.huan.drools.Alarm
rule "modify_当存在火灾对象时,设置一个火灾的名字"
    when
        $fire: Fire(name == null)
    then
        System.out.println("1、设置火灾名字");
        modify($fire){
            setName("大火灾")
        }
end
rule "modify_当火灾对象存在名字时触发"
    when
        $fire: Fire(name != null)
    then
        System.out.println("2、火灾对象的名字为: " + $fire.getName());
end

2.4.3 部分java文件编写

kieSession.insert(new Fire());
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("modify_"));

2.4.4 运行结果

  • 1、设置火灾名字
  • 2、火灾对象的名字为: 大火灾

2.4.5 结论

  • modify会导致模式的重新匹配。
  • modify会修改工作对象内存中的值。一般情况下使用modify,不要使用update

2.5 delete 删除工作内存中的对象

用法:delete(<object>)

retract也是和delete一样的效果,但是推荐使用delete

3、drools变量的简单使用

package rules
rule "drools_变量的使用"
    wh
        eval(true)
    then
        System.out.println("Match激活的当前触发规则: " + drools.getMatch());
        System.out.println("当前触发规则的名字: " + drools.getRule().getName());
        // System.out.println("终止规则执行fireUntilHalt(): " + drools.getKieRuntime().halt());
        // System.out.println("激活AgendaGroup组: " + drools.getKieRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus());
        System.out.println("获取所有全局变量: " + drools.getKieRuntime().getGlobals());
        // System.out.println("设置全局变量:" +  drools.getKieRuntime().setGlobal("username","huan"); );
        // System.out.println("获取查询结果:" + drools.getKieRuntime().getQueryResults());
end

4、规则的继承

4.1 需求

规则一: 如果用户(customer)的年龄(age)大于60岁,则打0.9折。
规则二: 在规则一的基础上,如果用户有车(car),则可以免费停车(freeParking)。

4.2 drl文件编写

package rules
import com.huan.drools.Customer
import com.huan.drools.Car
rule "rule_extends_规则一"
    when
        $c: Customer(age > 60)
    then
        modify($c){
            setDiscount(0.9)
        }
        System.out.println("触发规则一:用户年龄>60岁,打0.9折");
end
// 规则二继承规则一的条件
rule "rule_extends_规则二" extends "rule_extends_规则一"
    when
        $car: Car()
    then
        modify($car){
            setFreeParking(true)
        }
        System.out.println("触发规则二:用户有车,免费停车");
end

此处rule_extends_规则二继承了rule_extends_规则一,所以规则一的条件也继承了。

4.3 部分java代码

Car car = new Car();
Customer customer = new Customer();
customer.setAge(65);
kieSession.insert(customer);
kieSession.insert(car);
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_extends_"));

客户有车,并且年龄是65岁,满足上方的规则一和规则二

4.4 运行结果

触发规则一:用户年龄>60岁,打0.9折
触发规则二:用户有车,免费停车

4.5 结论

可以看到在rule上使用extends关键字,可以实现规则的继承。

5、使用do[...]语法重写上方继承的例子

5.1 需求

只要用户大于60岁,直接打0.9折,如果还有车,则可以免费停车。

5.2 drl文件编写

package rules
import com.huan.drools.Customer
import com.huan.drools.Car
rule "命名结果_rule"
    when
        $c: Customer(age > 60)
        do[giveDiscount] // 当上方的条件成立时执行 then [giveDiscount]
        $car: Car() // 此条件成立时,执行默认的 then
    then
        modify($car){
            setFreeParking(true)
        };
        System.out.println("用户有车,免费停车");
    then [giveDiscount]
        modify($c){
            setDiscount(0.9)
        };
        System.out.println("用户年龄>60岁,打0.9折");
end

解释: 见上方的规则文件里的注视

5.3 部分java代码编写

Car car = new Car();
Customer customer = new Customer();
customer.setAge(65);
kieSession.insert(customer);
kieSession.insert(car);
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("命名结果_"));

5.4 运行结果

用户年龄>60岁,打0.9折
用户有车,免费停车

也实现了需求

5.5 结论

通过when中使用 do[名字] 然后 then then 名字 也可以实现。

6、实现 if else if 的效果

6.1 需求

完成类似 if else if else效果。见下方的各种执行结果

6.2 规则文件

rule "if else-if"
    when
       $customer: Customer(age > 60) // 规则内存中存在Customer对象,并且age>60
        if($customer.getLevel() == 1) do[level1] // 用户的级别是1,执行then[level1],然后继续执行下方的条件
        else if ($customer.getLevel() == 2) break[level2] // 用户的级别是2,执行then[level2],不在执行下方的条件
        else do[levelOther] // 其他的level级别,执行then[levelOther],然后在执行下方的条件
        Car()
    then
        System.out.println("我执行了");
    then[level1]
        System.out.println("level1");
    then[level2]
        System.out.println("level2");
    then[levelOther]
        System.out.println("levelOther");
end

6.3 执行结果图

6.4 各种执行结果-也就是上图的解释

1、Customerage小于60
输出: 没有输出。
2、Customerage大于60并且level=1,没有Car
输出: level1
3、Customerage大于60并且level=1,有Car
输出: level1 我执行了
4、Customerage大于60并且level=2,没有Car
输出: level2
5、Customerage大于60并且level=2,有Car
输出: level2
6、Customerage大于60并且level=3,没有Car
输出: levelOther
7、Customerage大于60并且level=3,有Car
输出: levelOther 我执行了

6.5 do和 break 有什么区别

do:执行完之后,还会继续判断后面的执行条件。 (即还会执行后面的Car判断,根据是否有Car获取不同的结果
break:执行完之后,不会在判断后面的执行条件。(即忽略了后面的Car判断,rule执行完了

7.完整代码

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

8.参考文档

https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-rules-THEN-con_drl-rules

到此这篇关于drools中then部分的写法的文章就介绍到这了,更多相关drools中then写法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

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

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

  • 聊聊drools session的不同

    目录 一.理解 1.有状态Session 2.无状态Session 3.那么何时使用不同的Session呢? 二.需求 三.实现步骤 1.项目结构说明 2.引入jar包 3.编写Count类 4.编写kmodule.xml文件 5.编写规则文件 6.Stateful session运行结果 7.Stateless Session运行结果 四.注意事项 五.完整代码 六.参考文档 一.理解 在drools中存在2种session,一种是有状态的Session (Stateful Session),

  • Drools Fusion(CEP)定义及使用方法讲解

    从 Drools 统一行为建模平台的视野看,Drools Fusion 是负责启用事件处理行 为的一个模块. 定义 支持复杂事件处理,是比简单的理解事件是什么要更多得多,cep场景具有几个共同而明显的特点: 通常需要处理巨量的事件,但是只有少部分事件是真正关心的. 事件通常是不变的,因为它们是状态改变的一条记录. 通常有关事件的规则和查询必须是运行在被动模式(reactive modes),即,对事件模式(patterns)的检测作出反应. 通常在相关的事件之间有强烈的时间关系. 个别事件通常是

  • drools中then部分的写法(推荐)

    目录 1.背景 2.支持的方法 2.1 insert 插入对象到工作内存中 2.1.1 需求 2.1.2 drl文件编写 2.1.3 部分java代码编写 2.1.4 运行结果 2.1.5 结论 2.2 insertLogical 插入对象到工作内存中 2.2.1 需求 2.2.2 drl文件编写 2.2.3 部分java代码编写 2.2.4 运行结果 2.2.5 结论 2.3.update 更新工作内存中的对象 2.3.1 需求 2.3.2 drl 文件编写 2.3.3 部分java文件编写

  • javaScript中的原型解析【推荐】

    最近在学习javaScript,学习到js面向对象中的原型时,感悟颇多.若有不对的地方,希望可以指正. js作为一门面向对象的语言,自然也拥有了继承这一概念,但js中没有类的概念,也就没有了类似于java中的extends,所以,我觉得js中的继承主要依赖于js中的原型(链). 那么,原型是什么呢?我们知道js中函数亦是一种对象,当我们创建一个函数时,其实这个函数也就默认的拥有了一个属性叫做prototype,这个属型叫做原型属性,他是一个指针,指向了这个函数的原型对象,这个原型对象有一个默认的

  • drools中使用function的方法小结

    目录 一.背景 二.需求 三.前置知识 1.function语法结构 2.drl文件中如何调用java的静态方法 四.实现 1.项目结构 2.引入drools依赖 3.编写kmodule.xml文件 4.编写Person实体类 5.drl function编写 6.编写测试类 7.查看运行结果 五.假设我想在when阶段调用function 六.完整代码 七.参考链接 一.背景 当我们在drools中编写规则时,有些时候存在重复的代码,那么我们是否可以将这些重复代码抽取出来,封装成一个funct

  • Vue3 中的插件和配置推荐大全

    目录 1. Vite 2. 自动导入常见方法 2.1 传统写法 2.2 自动导入 3. 组件去后缀 4. name 属性问题 小伙伴们知道 TienChin 项目前端用的是 Vue3,当我们把 Vue3 官网刷了一遍之后回来看 TienChin 项目的前端,发现还是有很多不太一样的地方,今天松哥就来和大家捋一捋 Vue3 中几个好玩的插件和配置,学完之后,相信大家对 TienChin 项目前端的很多写法就明白了. 1. Vite 首先来给大家介绍一下 Vite,虽然这在 Vue3 中并不是必须的

  • 再谈Javascript中的基本类型和引用类型(推荐)

    一.基本类型和引用类型概述 js中数据类型的值包括:基本类型值和引用类型值 基本数据类型:undefined;null;boolean;number;string 引用类型值:保存在内存中,js不允许直接访问内存位置,因此时操作引用而不是实际对象 二.如何检测数据类型 1.基本数据类型的检测:使用typeof var s = "AAA"; alert(typeof s); //返回string 2.引用类型(对象类型)检测:使用instanceof alert(person insta

  • YII框架中搜索分页jQuery写法详解

    控制层 use frontend\models\StudUser; use yii\data\Pagination; use yii\db\Query; /** * 查询 * */ public function actionSearch() { //接值 $where=Yii::$app->request->get(); //实例化query $query=new Query(); $query->from('stud_user'); //判断 if(isset($where['sex

  • JavaScript中一些常用的正则表达式(推荐)

    正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取出符合某个条件的子串等. var validateRegExp = { decmal: "^([+-]?)\\d*\\.\\d+$", // 浮点数 decmal1: "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$", // 正浮点数 decmal2: "^-([1-9]\\d*.\\d*|

  • C++ 中的Lambda表达式写法

    小喵的唠叨话: 寒假之后,小喵在家里无所事事,最近用C++写代码的时候,用到了std::sort这个函数,每次用这个函数,小喵似乎都得查一下lambda表达式的写法.正好最近很闲,不如总结一下. 在Bing上搜索 C++ lambda ,第一条记录就是MSDN上的C++ lambda的介绍.本文也是基于这篇文章来写的. 那么接下来,我们分几个部分来介绍. 一.什么是Lambda表达式 MSDN上对lambda表达式的解释: 在 C++ 11 中,lambda 表达式(通常称为 "lambda&q

  • 星期几的不同脚本写法(推荐)

    在前端领域里,很多时候,一个简单的功能可以有很多种不同的实现方式,今天就拿星期几的不同脚本实现方法作为例子,希望能激发童鞋们更多的想法. 1.使用 if 语句: var str = ""; var week = new Date().getDay(); if (week == 0) { str = "今天是星期日"; } else if (week == 1) { str = "今天是星期一"; } else if (week == 2) { s

  • js获取页面引用的css样式表中的属性值方法(推荐)

    如下所示: function getStyle(node, property){ if (node.style[property]) { return node.style[property]; } else if (node.currentStyle) { return node.currentStyle[property]; } else if (document.defaultView && document.defaultView.getComputedStyle) { var s

随机推荐