信息发布→ 登录 注册 退出

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

发布时间:2026-01-11

点击量:
目录
  • 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

                                        在线客服
                                        服务热线

                                        服务热线

                                        4008888355

                                        微信咨询
                                        二维码
                                        返回顶部
                                        ×二维码

                                        截屏,微信识别二维码

                                        打开微信

                                        微信号已复制,请打开微信添加咨询详情!