【规则引擎】Drools急速入门
作者:mmseoamin日期:2023-12-20

文章目录

        • 1.Drools规则引擎简介
        • 2.Drools API开发步骤
        • 3.SpringBoot整合Drools案例
        • 4.Drools基础语法
        • 5.Drools条件语法部分
        • 6.Drools结果操作部分
        • 7.Drools内置属性部分
        • 8.Drools高级语法部分
          1.Drools规则引擎简介

          (1)什么是规则引擎

          ​ 全称为业务规则管理系统,英⽂名为BRMS(即 Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。 需要注意的是规则引擎并不是一个具体的技术框架,而是指的⼀类系统,即业务规则管理系统。

          ​ 目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等,使用最为广泛并且开源的是Drools。

          ​ 规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出的平台。

          (2)规则引擎主要的应用场景

          • 风险控制系统----风险贷款、风险评估
          • 反欺诈项目----银行贷款、征信验证
          • 决策平台系统----财务计算
          • 促销平台系统----满减、打折、加价购

            (3)Drools介绍

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

            【规则引擎】Drools急速入门,在这里插入图片描述,第1张

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

            ​ drools源码下载地址:https://github.com/kiegroup/drools

            (4)使用规则引擎能解决什么问题

            • 硬编码实现业务规则难以维护
            • 硬编码实现业务规则难以应对变化
            • 业务规则发⽣变化需要修改代码,重启服务后才能生效

              (5)使用规则引擎的优势

              • 业务规则与系统代码分离,实现业务规则的集中管理
              • 在不重启服务的情况下可随时对业务规则进行扩展和维护
              • 可以动态修改业务规则,从⽽快速响应需求变更
              • 规则引擎是相对独立的,只关心业务规则,使得业务分析⼈员也可以参与编辑、维护系统的业务规则
              • 减少了硬编码业务规则的成本和风险
              • 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单
                2.Drools API开发步骤

                【规则引擎】Drools急速入门,在这里插入图片描述,第2张

                我们在操作Drools时经常使用的API以及它们之间的关系如下图:

                【规则引擎】Drools急速入门,在这里插入图片描述,第3张

                Kie全称为Knowledge Is Everything,即“知识就是一切”的缩写,是Jboss一系列项目的总称。

                规则引擎构成

                drools规则引擎由以下三部分组成:

                • Working Memory(工作内存)
                • Rule Base(规则库)
                • Inference Engine(推理引擎)

                  其中Inference Engine(推理引擎)又包括:

                  ● Pattern Matcher(匹配器) 具体匹配哪⼀个规则,由这个完成

                  ● Agenda(议程)

                  ● Execution Engine(执行引擎)

                  【规则引擎】Drools急速入门,在这里插入图片描述,第4张

                  相关概念说明

                  • **Working Memory:**工作内存,drools规则引擎会从Working Memory中获取数据和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要我们的数据插入到Working Memory中即可。

                  • **Fact:**事实,是指在drools规则应用中,将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象。

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

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

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

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

                    规则引擎执行过程

                    【规则引擎】Drools急速入门,在这里插入图片描述,第5张

                    3.SpringBoot整合Drools案例

                    (1)案例背景

                    某电商平台的促销活动,活动规则是根据⽤户购买订单的⾦额给⽤户送相应的积分,购买的越多送的积分越多

                    用户购买的金额和对应送多少积分的规则如下:

                    100元以下, 不加分
                    100元-500元 加100分
                    500元-1000元 加500分
                    1000元 以上 加1000分
                    

                    按照常理,作为一个工作一两年的开发工程师来说,这不是分分钟搞定的事情,直接上午开发,下午提测。

                    /**
                     * 设置订单积分
                     */
                    public void setOrderPoint(Order order){
                        if (order.getAmout() <= 100){
                        	order.setScore(0);
                        }else if(order.getAmout() > 100 && order.getAmout() <= 500){
                        	order.setScore(100);
                        }else if(order.getAmout() > 500 && order.getAmout() <= 1000){
                        	order.setScore(500);
                        }else{
                        	order.setScore(1000);
                        }
                    }
                    

                    但是,假如说现在产品经理不想100元以下不送积分了,想要200元以下不送金额了,是不是又要重新改代码了。所以Drools帮我们解决在不改动原有代码的情况下修改规则的信息。

                    (2)创建Maven项目,加入SpringBoot依赖

                    【规则引擎】Drools急速入门,在这里插入图片描述,第6张

                            
                                org.springframework.boot
                                spring-boot-starter-parent
                                2.5.12
                                
                            
                            
                                
                                    org.springframework.boot
                                    spring-boot-starter-web
                                
                            
                            
                                
                                    
                                        org.springframework.boot
                                        spring-boot-maven-plugin
                                    
                                
                            
                    

                    (3)resources下创建yml配置文件

                    server:
                      port: 8888
                    spring:
                      application:
                        name: drools-server
                    

                    (4)创建SpringBoot启动主类

                    @SpringBootApplication
                    public class DroolsApplication {
                        public static void main(String[] objArgs)
                        {
                            SpringApplication.run(DroolsApplication.class, objArgs);
                        }
                    }
                    

                    (5)添加单元测试依赖

                            
                                org.springframework.boot
                                spring-boot-starter-test
                            
                    

                    (6)添加Drools和lombok依赖

                            
                            
                                org.drools
                                drools-core
                                7.6.0.Final
                            
                            
                                org.drools
                                drools-compiler
                                7.6.0.Final
                            
                            
                                org.drools
                                drools-templates
                                7.6.0.Final
                            
                            
                                org.kie
                                kie-api
                                7.6.0.Final
                            
                            
                                org.kie
                                kie-spring
                                7.6.0.Final
                            
                            
                            
                                org.projectlombok
                                lombok
                                1.18.20
                                compile
                            
                    

                    (7)创建订单实体类Order

                    /**
                     * @description 订单实体类
                     * @author lixiang
                     */
                    @Data
                    public class Order {
                        /**
                         * 订单金额
                         */
                        private int amount;
                        /**
                         * 积分
                         */
                        private int score;
                    }
                    

                    (8)创建规则⽂件/resources/rules/score-rules.drl

                    package rules
                    import com.lixiang.domain.Order
                    //规则1:100元以下, 不加积分
                    rule "score_1"
                    when
                        $s : Order(amount <= 100)
                    then
                        $s.setScore(0);
                        System.out.println("消费100元以下, 不加积分 ");
                    end
                    //规则2:100元-500元 加100积分
                    rule "score_2"
                    when
                        $s : Order(amount > 100 && amount <= 500)
                    then
                        $s.setScore(100);
                        System.out.println("消费100元-500元 加100积分 ");
                    end
                    //规则3:500元-1000元 加500积分
                    rule "score_3"
                    when
                        $s : Order(amount > 500 && amount <= 1000)
                    then
                        $s.setScore(500);
                        System.out.println("消费500元-1000元 加500积分 ");
                    end
                    //规则4:1000元 以上 加1000积分
                    rule "score_4"
                    when
                        $s : Order(amount > 1000)
                    then
                        $s.setScore(1000);
                        System.out.println("消费1000元 以上 加1000积分 ");
                    end
                    

                    (9)创建DroolsConfig配置类

                    /**
                     * @author lixiang
                     * @description Drools规则引擎配置类
                     */
                    @Configuration
                    public class DroolsConfig {
                        /**
                         * 定义规则路径
                         */
                        private static final String RULES_PATH = "rules/";
                        private final KieServices kieServices = KieServices.Factory.get();
                        /**
                         * 获取规则文件
                         * @return
                         * @throws IOException
                         */
                        @Bean
                        @ConditionalOnMissingBean
                        public KieFileSystem kieFileSystem() throws IOException {
                            KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
                            ResourcePatternResolver resourcePatternResolver =  new PathMatchingResourcePatternResolver();
                            Resource[] files = resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");
                            String path;
                            for (Resource file : files) {
                                path = RULES_PATH + file.getFilename();
                                kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));
                            }
                            return kieFileSystem;
                        }
                        /**
                         * 创建Kie容器
                         * @return
                         * @throws IOException
                         */
                        @Bean
                        @ConditionalOnMissingBean
                        public KieContainer kieContainer() throws IOException {
                            KieRepository kieRepository = kieServices.getRepository();
                            kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
                            KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
                            kieBuilder.buildAll();
                            return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
                        }
                        @Bean
                        @ConditionalOnMissingBean
                        public KieBase kieBase() throws IOException {
                            return kieContainer().getKieBase();
                        }
                        @Bean
                        @ConditionalOnMissingBean
                        public KModuleBeanFactoryPostProcessor kiePostProcessor() {
                            return new KModuleBeanFactoryPostProcessor();
                        }
                    }
                    

                    (10)编写测试类

                    @SpringBootTest
                    public class DroolsTest {
                        @Autowired
                        private KieBase kieBase;
                        @Test
                        public void droolsTest(){
                            Order order = new Order();
                            order.setAmount(200);
                            //创建会话对象,用于和规则交互的引擎
                            KieSession kieSession = kieBase.newKieSession();
                            //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                            kieSession.insert(order);
                            //激活规则引擎,如果匹配成功则执行
                            kieSession.fireAllRules();
                            //关闭会话
                            kieSession.dispose();
                            System.out.println("订单金额:"+order.getAmount()+",订单积分:"+order.getScore());
                        }
                    }
                    

                    【规则引擎】Drools急速入门,在这里插入图片描述,第7张

                    4.Drools基础语法

                    (1)规则文件的构成

                    drl是Drools Rule Language的缩写。在规则⽂件中编写具体的规则内容。

                    ⼀套完整的规则文件内容构成如下:

                    • package:包名,package对应的不⼀定是真正的目录,可以任意写com.abc,同⼀个包下的drl文件可以相互访问
                    • import:用于导入类或者静态方法
                    • global:全局变量
                    • function:自定义函数
                    • query:查询
                    • rule end:规则体

                      (2)规则体语法构成

                      一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)
                      rule "ruleName" //rule关键字,表示规则开始,参数为规则的唯⼀名称
                      	attributes //规则属性,是rule与when之间的参数,为可选项
                      	when //关键字,后⾯是规则的条件部分
                      		LHS //Left Hand Side,是规则的条件部分
                      	then //后⾯跟规则的结果部分
                      		RHS //是规则的结果或⾏为
                      end //表示⼀个规则的结束
                      
                      5.Drools条件语法部分

                      LHS(Left Hand Side):是规则的条件部分的通⽤名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。

                      (1)约束连接

                      • 在 LHS 当中,可以包含 0~n 个条件,多个pattern之间可以采⽤“&&” (and) 、 “||”(or)和“,”(and)来实现,也可以不写,默认连接为and。
                        rule "rule1"
                            when
                            	$s : Order(amout > 100 && amout <= 500)
                            then
                            	$s.setScore(100);
                            	System.out.println("成功匹配到规则:100元-500元 加100积分 ");
                        end
                        
                        • 测试代码
                              @Test
                              public void test1(){
                                  Order order = new Order();
                                  order.setAmount(200);
                                  //创建会话对象,用于和规则交互的引擎
                                  KieSession kieSession = kieBase.newKieSession();
                                  //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                  kieSession.insert(order);
                                  //激活规则引擎,如果匹配成功则执行
                                  kieSession.fireAllRules();
                                  //关闭会话
                                  kieSession.dispose();
                              }
                          

                          【规则引擎】Drools急速入门,在这里插入图片描述,第8张

                          (2)比较运算符

                          • 在 Drools当中共提供了⼗⼆种类型的⽐较操作符, 分别是: >、 >=、 <、 <=、 = =、 !=、contains、 not contains、memberof、not memberof、matches、not matches;在这⼗⼆种类型的比较操作符当中,前六个是⽐较常⻅也是⽤的⽐较多的⽐较操作符。
                            符号说明
                            >大于
                            <小于
                            >=大于等于
                            <=小于等于
                            ==等于
                            !=不等于
                            contains检查一个Fact对象的某个属性值是否包含一个指定的对象值
                            not contains检查⼀个Fact对象的某个属性值是否不包含⼀个指定的对象值
                            memberOf判断⼀个Fact对象的某个属性是否在⼀个或多个集合中
                            not memberOf判断⼀个Fact对象的某个属性是否不在⼀个或多个集合中
                            matches判断⼀个Fact对象的属性是否与提供的标准的Java正则表达式进⾏匹配
                            not matches判断⼀个Fact对象的属性是否不与提供的标准的Java正则表达式进⾏匹配

                            验证:

                            • 创建订单项实体类
                              /**
                               * @description 订单项
                               * @author lixiang
                               */
                              @Data
                              public class OrderItem {
                                  /**
                                   * 订单项名称
                                   */
                                  private String name;
                                  /**
                                   * 订单项金额
                                   */
                                  private int amount;
                              }
                              
                              • 订单中加入订单项集合
                                /**
                                 * @description 订单实体类
                                 * @author lixiang
                                 */
                                @Data
                                public class Order {
                                    /**
                                     * 订单金额
                                     */
                                    private int amount;
                                    /**
                                     * 积分
                                     */
                                    private int score;
                                    List orderItemList;
                                }
                                
                                • 测试contains 规则
                                  规则文件内容:
                                  //测试contains规则
                                  rule "rule1"
                                      when
                                          $orderItem:OrderItem();
                                          $order:Order(orderItemList contains $orderItem);
                                      then
                                          System.out.println("测试 contains 规则触发:"+$order.getOrderItemList());
                                  end
                                  
                                  	//java测试代码
                                  	@Test
                                      public void test2(){
                                          Order order = new Order();
                                          order.setAmount(200);
                                          OrderItem orderItem = new OrderItem();
                                          List orderItemList = new ArrayList<>();
                                          orderItemList.add(orderItem);
                                          order.setOrderItemList(orderItemList);
                                          //创建会话对象,用于和规则交互的引擎
                                          KieSession kieSession = kieBase.newKieSession();
                                          //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                          kieSession.insert(order);
                                          kieSession.insert(orderItem);
                                          //激活规则引擎,如果匹配成功则执行
                                          kieSession.fireAllRules();
                                          //关闭会话
                                          kieSession.dispose();
                                      }
                                  

                                  【规则引擎】Drools急速入门,在这里插入图片描述,第9张

                                  • 测试not contains 规则
                                    规则文件内容:
                                    //测试not contains规则
                                    rule "rule1"
                                        when
                                            $orderItem:OrderItem();
                                            $order:Order(orderItemList contains $orderItem);
                                        then
                                            System.out.println("测试not contains 规则触发:"+$order.getOrderItemList());
                                    end
                                    
                                    	//java测试代码
                                    	@Test
                                        public void test3(){
                                            Order order = new Order();
                                            order.setAmount(200);
                                            OrderItem orderItem = new OrderItem();
                                            List orderItemList = new ArrayList<>();
                                            orderItemList.add(orderItem);
                                            //创建会话对象,用于和规则交互的引擎
                                            KieSession kieSession = kieBase.newKieSession();
                                            //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                            kieSession.insert(order);
                                            kieSession.insert(orderItem);
                                            //激活规则引擎,如果匹配成功则执行
                                            kieSession.fireAllRules();
                                            //关闭会话
                                            kieSession.dispose();
                                        }
                                    

                                    【规则引擎】Drools急速入门,在这里插入图片描述,第10张

                                    • 测试matches规则
                                      规则文件内容:
                                      //测试⽐较操作符matches
                                      rule "rule3"
                                          when
                                          	OrderItem(name matches "订单*")
                                          then
                                          	System.out.println("测试⽐较操作符matches触发...");
                                      end
                                      
                                      	//java测试代码
                                      	@Test
                                          public void test3(){
                                              OrderItem orderItem = new OrderItem();
                                              orderItem.setName("订单项1");
                                              //创建会话对象,用于和规则交互的引擎
                                              KieSession kieSession = kieBase.newKieSession();
                                              //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                              kieSession.insert(orderItem);
                                              //激活规则引擎,如果匹配成功则执行
                                              kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule3"));
                                              //关闭会话
                                              kieSession.dispose();
                                          }
                                      

                                      【规则引擎】Drools急速入门,在这里插入图片描述,第11张

                                      • 测试not matches规则
                                        规则文件内容:
                                        //测试⽐较操作符not matches
                                        rule "rule4"
                                            when
                                            	OrderItem(name not matches "订单1.*")
                                            then
                                            	System.out.println("测试⽐较操作符not matches触发...");
                                        end
                                        
                                        	//java测试代码
                                        	@Test
                                            public void test3(){
                                                OrderItem orderItem = new OrderItem();
                                                orderItem.setName("订单项1");
                                                //创建会话对象,用于和规则交互的引擎
                                                KieSession kieSession = kieBase.newKieSession();
                                                //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                kieSession.insert(orderItem);
                                                //激活规则引擎,如果匹配成功则执行
                                                kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
                                                //关闭会话
                                                kieSession.dispose();
                                            }
                                        

                                        【规则引擎】Drools急速入门,在这里插入图片描述,第12张

                                        • 测试memberOf规则
                                          规则文件内容:
                                          //测试⽐较操作符memberOf
                                          rule "rule5"
                                              when
                                              	Order(orderItemList memberOf list)
                                              then
                                              	System.out.println("测试⽐较操作符memberOf触发...");
                                          end
                                          
                                          	//java测试代码
                                          	@Test
                                              public void test4(){
                                                  Order order = new Order();
                                                  OrderItem orderItem = new OrderItem();
                                                  List orderItemList = new ArrayList<>();
                                                  orderItemList.add(orderItem);
                                                  order.setOrderItemList(orderItemList);
                                                  //创建会话对象,用于和规则交互的引擎
                                                  KieSession kieSession = kieBase.newKieSession();
                                                  //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                  kieSession.insert(order);
                                                  kieSession.insert(orderItem);
                                                  //激活规则引擎,如果匹配成功则执行
                                                  kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule5"));
                                                  //关闭会话
                                                  kieSession.dispose();
                                              }
                                          

                                          【规则引擎】Drools急速入门,在这里插入图片描述,第13张

                                          • 测试not memberOf规则
                                            规则文件内容:
                                            //测试⽐较操作符memberOf
                                            rule "rule6"
                                                when
                                                    $orderItem:OrderItem();
                                                	Order($orderItem not memberOf orderItemList);
                                                then
                                                	System.out.println("测试⽐较操作符not memberOf触发...");
                                            end
                                            
                                            	@Test
                                                public void test4(){
                                                    Order order = new Order();
                                                    OrderItem orderItem = new OrderItem();
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    kieSession.insert(order);
                                                    kieSession.insert(orderItem);
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule6"));
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第14张

                                            6.Drools结果操作部分

                                            在Drools当中,在RHS里面,提供了一些对当前Working Memory实现快速操作的宏函数或对象,比如insert/insertLogical、update和retract就可以实现对当前Working Memory中的Fact对象进行新增、删除或者是修改。

                                            (1)insert/insertLogical函数

                                            函数insert的作用与我们在java类当中调用StatefulKnowIedgeSession对象的insert方法的作用相同,都是将一个Fact对象插入到当前的Working Memory当中。

                                            需注意:一旦调用 insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配⼀次, 对于没有设置no-loop 属性为 true 的规则,如果条件满足,不管其之前是否执行过都会在执行,这个特性不仅存在于 insert 宏函数上,后⾯介绍的 update、retract 宏函数同样具有该特性,所以在某些情况下因考虑不周调用 insert、update 或 retract 容易发生死循环。

                                            //Drools提供的内置⽅法insert
                                            rule "rule7"
                                                when
                                                    eval(true); //默认成⽴
                                                then
                                                    Order order=new Order();
                                                    order.setAmount(1000);
                                                    insert(order);
                                                    System.out.println("测试Drools提供的内置⽅法insert 触发...,order:"+order);
                                            end
                                            
                                                @Test
                                                public void test6() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule7"));
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第15张

                                            insertLogical:insertLogical 作⽤与 insert 类似,它的作用也是将⼀个 Fact 对象插入到当前的 Working Memroy 当中

                                            (2)update函数

                                            update函数意义与其名称⼀样, ⽤来实现对当前Working Memory当中的 Fact进⾏更新,⽤来告诉当前的 Working Memory 该 Fact 对象已经发生了变化。

                                            //Drools提供的内置⽅法update
                                            rule "rule8"
                                                when
                                                    $order:Order(amount == 100);
                                                then
                                                    $order.setAmount(1000);
                                                    update($order);
                                                    System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
                                            end
                                            
                                            	@Test
                                                public void test8() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    Order order = new Order();
                                                    order.setAmount(100);
                                                    kieSession.insert(order);
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule8"));
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第16张

                                            (3)retract

                                            retract用来将Wroking Memory当中某个Fact对象从Working Memory当中删除

                                            rule "rule9"
                                                when
                                                    $order:Order(amount == 100);
                                                then
                                                    //retract($order); //先不执行删除
                                                    System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
                                            end
                                            rule "rule10"
                                                when
                                                    $order:Order();
                                                then
                                                    System.out.println("order:"+$order);
                                            end
                                            
                                                @Test
                                                public void test9() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    Order order = new Order();
                                                    order.setAmount(100);
                                                    kieSession.insert(order);
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第17张

                                            rule "rule9"
                                                when
                                                    $order:Order(amount == 100);
                                                then
                                                    retract($order); //执行删除
                                                    System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
                                            end
                                            rule "rule10"
                                                when
                                                    $order:Order();
                                                then
                                                    System.out.println("order:"+$order);
                                            end
                                            

                                            测试方法还是上面那个

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第18张

                                            7.Drools内置属性部分

                                            Drools中提供的属性

                                            属性名说明
                                            salience指定规则执行优先级
                                            dialect指定规则使用的语言类型,取值为java或者mvel
                                            enabled指定规则是否启用
                                            date-effective指定规则生效时间
                                            date-expires指定规则失效时间
                                            activation-group激活分组,具有相同分组名称的规则只能有一个规则触发
                                            agenda-group议程分组,只有获取焦点的组中的规则才有可能触发
                                            timer定时器,指定规则触发的时间
                                            auto-focus自动获取焦点,一般饥饿和agenda-group一起使用
                                            no-loop防止死循环

                                            (1)salience

                                            salience用来设置规则执行的优先级,salience属性的值是一个数字,数字越大执行优先级越高。默认情况下,规则的salience默认值为0。如果不设置salience属性,规则体的执行顺序为由上到下。

                                            rule "rule1"
                                                salience 1
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则1");
                                            end
                                            rule "rule2"
                                                salience 2
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则2");
                                            end
                                            
                                               @Test
                                                public void test10() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第19张

                                            (2)no-loop

                                            no-loop是用来控制已经执行过的规则在条件再次满足的时候是否再次执行。no-loop属性是一个布尔型默认情况下规则的no-loop属性的值为false,如果no-loop属性值为true,那么就表示该规则只会被引擎检查一次。

                                            //这是一个死循环修改,永远都会被匹配到修改
                                            rule "rule3"
                                                when
                                                    $order:Order(amount == 100);
                                                then
                                                    $order.setAmount(100);
                                                    update($order);
                                                    System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
                                            end
                                            
                                                @Test
                                                public void test10() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    Order order = new Order();
                                                    order.setAmount(100);
                                                    kieSession.insert(order);
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第20张

                                            //这是一个死循环修改,永远都会被匹配到修改
                                            rule "rule3"
                                                no-loop true  //配置no-loop属性
                                                when
                                                    $order:Order(amount == 100);
                                                then
                                                    $order.setAmount(100);
                                                    update($order);
                                                    System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
                                            end
                                            

                                            再次测试

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第21张

                                            (3)date-effective

                                            date-effective的作用是来控制规则只有达到指定的时候后才会触发,只有当系统时间大于等于date-effective设置的时间值时,规则才会被执行。

                                            date-effective 的值为⼀个日期型的字符串,默认情况下,date-effective 可接受的日期格式为 “dd-MM-yyyy”。

                                            在实际使用中,如果不想使用这种格式,也可以通过java代码去设置System.setProperty(String key,String value)方法来修饰默认的时间格式。

                                            System.setProperty("drools.dateformat","yyyy-MM-dd");
                                            
                                            rule "rule4"
                                                date-effective "2022-11-30"
                                                when
                                                    eval(true);
                                                then
                                                    System.out.println("测试Drools date-effective ");
                                            end
                                            
                                                @Test
                                                public void test10() {
                                                    //设置时间格式
                                                    System.setProperty("drools.dateformat","yyyy-MM-dd");
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            (4)date-expires

                                            date-expires的作用正好与date-effective属性恰恰相反,date-expires的作用时用来设置规则的有效期,引擎在执行规则的时候,会检查规则有没有date-expires属性,如果有的话,那么将这个属性与当前系统时间进行比较,如果大于系统时间就执行。

                                            rule "rule5"
                                                date-expires "2022-11-30"
                                                when
                                                    eval(true);
                                                then
                                                    System.out.println("测试Drools date-effective ");
                                            end
                                            
                                                @Test
                                                public void test10() {
                                                    //设置时间格式
                                                    System.setProperty("drools.dateformat","yyyy-MM-dd");
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            (5)enabled

                                            enabled的作用就是定义一个规则是否可用。该属性的值是一个布尔值默认该属性的值为true,表示规则是可用的。设置enabled属性为false时,该规则引擎不会执行。

                                            rule "rule1"
                                                enabled true
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则1");
                                            end
                                            rule "rule2"
                                                enabled false
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则2");
                                            end
                                            
                                                @Test
                                                public void test11() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第22张

                                            (6)dialect

                                            dialect作用是用来定义规则当中要使用的语言类型,目前支持两种类型的语言,mvel和java,默认情况下,如果没有手工设置的话,默认使用java语言。

                                            (7)activation-group

                                            activation-group的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,在执行规则时,具有相同activation-group属性的规则中只要有一个会被执行,其他规则将不再执行。当然具有相同activation-group属性的规则中哪一个会先执行,可以设置salience属性来实现。

                                            rule "rule1"
                                                activation-group "test"
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则1");
                                            end
                                            rule "rule2"
                                                activation-group "test"
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则2");
                                            end
                                            
                                            	@Test
                                                public void test11() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第23张

                                            (8)agenda-group

                                            agenda-group属性是一个字符串,不过通过这个字符串可以分为若干个AgendaGroup,默认情况下,引擎在调用这些设置了agenda-group属性的规则的时候需要显示的指定某个Agenda Group得到Focus,这样位于该Agenda Group当中的规则才会触发执行,否则将不执行。

                                            rule "rule1"
                                                agenda-group "001"
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则1");
                                            end
                                            rule "rule2"
                                                agenda-group "002"
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则2");
                                            end
                                            
                                            	@Test
                                                public void test11() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //获取执行焦点
                                                    kieSession.getAgenda().getAgendaGroup("002").setFocus();
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第24张

                                            (9)auto-focus

                                            auto-focus的作用是在已经设置了agenda-group的规则上设置该规则是否可以自动独取Focus,如果该属性设置为true,那么在执行引擎时,就不需要设置Focus。

                                            rule "rule1"
                                                agenda-group "001"
                                                auto-focus true
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则1");
                                            end
                                            rule "rule2"
                                                agenda-group "002"
                                                when
                                                    eval(true)
                                                then
                                                    System.out.println("执行规则2");
                                            end
                                            
                                            	@Test
                                                public void test11() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //激活规则引擎,如果匹配成功则执行
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第25张

                                            (10)timer

                                            timer属性可以通过定时器的方式指定规则执⾏的时间,使⽤方式有两种

                                            方式一:timer(int ?)

                                            此方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。

                                            方式二:timer(cron)

                                            此方式使用标准的unix cron 表达式的使用来定义规则执行的时间。

                                            rule "rule_timer_1"
                                                timer (5s 2s) //含义:5秒后触发,然后每隔2秒触发⼀次
                                                when
                                                then
                                                    System.out.println("规则rule_timer_1触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                                            end
                                            rule "rule_timer_2"
                                                timer (cron:0/1 * * * * ?) //含义:每隔1秒触发⼀次
                                                when
                                                then
                                                    System.out.println("规则rule_timer_2触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                                            end
                                            
                                            	@Test
                                                public void test12() throws InterruptedException {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    //启动规则引擎进行规则匹配,知道调用halt方法才结束引擎
                                                    new Thread(kieSession::fireUntilHalt).start();
                                                    //当前线程睡眠10s
                                                    Thread.sleep(10000L);
                                                    //调用halt
                                                    kieSession.halt();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第26张

                                            8.Drools高级语法部分
                                            关键字描述
                                            package包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用
                                            import用于导入类或者静态方法
                                            global全局变量
                                            function自定义函数
                                            query查询
                                            rule end规则体

                                            (1)global全局变量

                                            全局变量,一般用作执行规则后的结果数据返回或对具体某个服务调用等。在调用规则引擎的集成代码中,获取emailService对象,然后将其设置在工作内存中。

                                            语法结构为:global对象类型 对象名称

                                            import java.lang.String;
                                            global java.lang.String name;
                                            rule "rule6"
                                                when
                                                    eval(true);
                                                then
                                                    System.out.println("测试Global--全局order:"+name);
                                            end
                                            
                                            	@Test
                                                public void test14() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    kieSession.setGlobal("name","李祥");
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第27张

                                            (2)query查询

                                            query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定"when"和"then"部分。Query有一个可选参数集合,每一个参数都可选的类型。如果没有指定类型,则默认为Object类型。引擎会尝试转为需要的类型。对于KieBase来说,query的名字是全局性的,因此不要向同一RuleBase的不同包添加相同名称的query。

                                            使用ksession.getQueryResult(“name”)方法可以获得查询的结果,其中name为query的名称,方法的返回结果一个列表,从中可以获取匹配查询到的对象。

                                            import com.lixiang.domain.Order;
                                            //不带参数的进行查询
                                            query "query-1"
                                                $order : Order(amount == 100)
                                            end
                                            //带参数的进行查询
                                            query "query-2"(Integer amountParam)
                                                $order : Order(amount == amountParam)
                                            end
                                            
                                            	@Test
                                                public void test14() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    Order order1 = new Order();
                                                    order1.setAmount(1000);
                                                    Order order2 = new Order();
                                                    order2.setAmount(100);
                                                    //添加到工作空间
                                                    kieSession.insert(order1);
                                                    kieSession.insert(order2);
                                                    kieSession.fireAllRules();
                                                    QueryResults queryResults = kieSession.getQueryResults("query-1");
                                                    System.out.println("无查询参数:result size is "+queryResults.size());
                                                    for (QueryResultsRow queryResult : queryResults) {
                                                         Order order = (Order)queryResult.get("$order");
                                                        System.out.println("查询出来的结果:"+order);
                                                    }
                                                    System.out.println("------------------------------------------");
                                                    QueryResults queryResults1 = kieSession.getQueryResults("query-2",1000);
                                                    System.out.println("有查询参数:result size is "+queryResults1.size());
                                                    for (QueryResultsRow queryResult : queryResults) {
                                                        Order order = (Order)queryResult.get("$order");
                                                        System.out.println("查询出来的结果:"+order);
                                                    }
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第28张

                                            (3)function函数

                                            在规则中可以通过函数来做一些通用的逻辑,就相当于java类中的方法一样。

                                            //定义函数
                                            function String format(String name){
                                                return "hello "+name;
                                            }
                                            rule "function_rule"
                                                when
                                                    eval(true);
                                                then
                                                    //调⽤上⾯定义的函数
                                                    String ret = format("李祥");
                                                    System.out.println(ret);
                                            end
                                            
                                                @Test
                                                public void test13() {
                                                    //创建会话对象,用于和规则交互的引擎
                                                    KieSession kieSession = kieBase.newKieSession();
                                                    //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
                                                    kieSession.fireAllRules();
                                                    //关闭会话
                                                    kieSession.dispose();
                                                }
                                            

                                            【规则引擎】Drools急速入门,在这里插入图片描述,第29张