Drools规则引擎

一、规则引擎

规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。

需要注意的的规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。

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

二、Drools介绍

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

drools官网:https://www.drools.org/

drools中文网:Drools中文网 | 基于java的功能强大的开源规则引擎

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

在项目中使用drools时,既可以单独使用也可以整合spring使用。如果单独使用只需导入如下maven坐标即可:

<dependency>
    <groupId>org.drools</groupId>
	<artifactId>drools-compiler</artifactId>
	<version>7.6.0.Final</version>
</dependency>

三、快速入门

1、环境集成

在项目中集成使用drools时,既可以独立使用也可以整合spring使用,如果是单独使用直接引入maven依赖包:如下

    <dependency>
      <groupId>org.kie</groupId>
      <artifactId>kie-spring</artifactId>
      <version>7.68.0.Final</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-compiler</artifactId>
      <version>7.68.0.Final</version>
    </dependency>
2、drools规则引擎开发实现的具体步骤如下:

在这里插入图片描述

3、业务场景描述

用户消费的金额对应赠送的积分规则情况如下:

//消费100元以下 不加分

//消费100元-500元 加100分

//消费500元-1000元 加500分

//消费1000元以上 加1000分
4、实现
  1. 创建maven项目droolsSpring,在创建好的项目pom.xml文件中添加drools依赖包

  2. 根据drools要求在maven项目目录下创建 resources/META-INF/kmodule.xml
    需要有一个配置文件告诉代码规则文件drl在哪里,在drools中这个文件就是kmodule.xml

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

    注意:配置文件中的名称和位置都是固定写法,不能更改

    Kmodule中可以包含一个到多个kbase,分别对应drl的规则文件。

    kbase需要一个唯一的name,可以取任意字符串。

    packages为drl文件所在resource目录下的路径。注意分区drl文件中的package与此处的package不一定相同。多个包用逗号分隔,默认情况下会扫描resources目录下的所有(包含子目录)规则文件。

    kbase的default属性,标示当前KieBase是不是默认的,如果是默认的则不用名称就可以直接查找到该KieBase,但每个module最多只能有一个默认的KieBase。

    kbase下面可以有一个或多个ksession,ksession的name属性必须设置,且必须唯一。

  3. 创建订单实体类Order

    public class Order {
        /**
         * 订单金额
         */
        private int amount;
     
        /**
         * 积分
         */
        private int score;
    }
    
  4. 创建规则文件resources/rules/score-rules.drl,规则文件的内容如下:

    package rules;
    //对应实体类
    import com.pojo.Order;
     
    //100元以下不加分
    rule "score_1" //名称需唯一
    when
    $order:Order(amount < 100);
    then
    $order.setScore(0);
    System.out.println("触发规则,100元以下不加分");
    end
     
    //100元-500元 加100分
    rule "score_2"
    when
    $order:Order(100 < amount && amount< 500)
    then
    $order.setScore(100);
    System.out.println("触发规则,100元-500元 加100分");
    end
    //500元-1000元 加500分
    rule "score_3"
    when
    $order:Order(500 < amount && amount < 1000)
    then
    $order.setScore(500);
    System.out.println("触发规则,500元-1000元 加500分");
    end
    //1000元以上 加1000分
    rule "score_4"
    when
    $order:Order(1000 < amount)
    then
    $order.setScore(1000);
    System.out.println("触发规则,500元-1000元 加500分");
    end
    
  5. 编写测试类TestDrools。

    • 情况一:module文件中kbase指定特定名称,并且default设置为true,测试类的代码如下:

      public class TestDrools {
       
          @Test
          public void test() {
              //第一步 获取KieServices
              KieServices kieServices = KieServices.Factory.get();
              //第二步获取kieContainer
              KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
              //第三步获取kieSession
              KieSession simpleRuleKSession = kieClasspathContainer.newKieSession();
              //新建事实对象
              Order order = new Order();
              order.setAmount(235);
              //第四步 插入事实对象到session中
              simpleRuleKSession.insert(order);
              //第五步 执行规则引擎
              simpleRuleKSession.fireAllRules();
              //第六步 关闭规则引擎
              simpleRuleKSession.dispose();
              System.out.println("规则执行完成,关闭规则");
          }
      }
      
    • 情况二:module文件中kbase指定特定名称,default未设置或者设置为false,测试类的代码如下:

      public class TestDrools {
       
          @Test
          public void test() {
              //第一步 获取KieServices
              KieServices kieServices = KieServices.Factory.get();
              //第二步获取kieContainer
              KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer("SimpleRuleKBase");
              //第三步获取kieSession
              KieSession simpleRuleKSession = kieClasspathContainer.newKieSession("simpleRuleKSession");
              //新建事实对象
              Order order = new Order();
              order.setAmount(235);
              //第四步 插入事实对象到session中
              simpleRuleKSession.insert(order);
              //第五步 执行规则引擎
              simpleRuleKSession.fireAllRules();
              //第六步 关闭规则引擎
              simpleRuleKSession.dispose();
              System.out.println("规则执行完成,关闭规则");
          }
      }
      
  6. 测试结果

在这里插入图片描述

四、Drools基础语法

规则文件的构成

**drl是Drools Rule Language的缩写。**在规则文件中编写具体的规则内容。一套完整的规则文件内容构成如下:

  • package:包名,package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访

  • import:用于导入类或者静态方法

  • global:全局变量

  • function:自定义函数

  • query:查询

  • rule end:规则体

规则体语法结构

一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)

rule "ruleName"     //rule关键字,表示规则开始,参数为规则的唯一名称
    attributes      //规则属性,是rule与when之间的参数,为可选项
    when            //关键字,后面是规则的条件部分
        LHS         // Left Hand Side,是规则的条件部分
    then            //后面跟规则的结果部分
        RHS         //是规则的结果或行为
    end             //表示一个规则的结束
条件部分

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

LHS部分由一个或者多个条件组成,条件又称为pattern。

pattern的语法结构为:绑定变量名:0bject(Field约束)

其中绑定变量名可以省略,通常绑定变量名的命名一般建议以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false的0个或多个表达式。

//规则1:100元以下,不加分
rule "score_1"
    when
        //工作内存中必须存在order这种类型的Fact对象-----类型约束
        //Fact对象的amout属性值必须小于等于100------属性约束
        $s:Order(amount <= 100)
    then
        $s.setScore(0);
        System.out.println("成功匹配到规则1: 100元以下,不加分");
end

如果LHS部分为空的话,那么引擎会自动添加一个eval(rue)的条件,由于该条件总是返回true,所以LHS为空的规则总是返回true

  1. 约束连接

    在LHS当中,可以包含0~n个条件,多个pattern之间可以采用“&&”(and) 、 “II”(or和“.”(and)来实现,也可以不写,默认连接为and。

    //100元-500元 加100分
    rule "score_2"
    when
    $order:Order(100 < amount && amount< 500)
    then
    $order.setScore(100);
    System.out.println("触发规则,100元-500元 加100分");
    end
    
  2. 比较操作符

    在Drools当中共提供了十二种类型的比较操作符,分别是: >、>=、〈、<=、= =、!=、 contains、not contains、memberof、not memberof、matches、not matches;在这十二种类型的比较操作符当中,前六个是比较常见也是用的比较多的比较操作符
    在这里插入图片描述

  3. 编写规则

    package rules;
    
    import pojo.*;
    
    rule "rules_1"
        when
        $order:Order();
        $customer:Customer($order memberOf orderList)
        then
        System.out.println("触发规则:orderList 包含 order对象");
    end
    
    rule "rules_2"
        when
        $order:Order();
        $customer:Customer($order not memberOf orderList)
        then
        System.out.println("触发规则:orderList 不包含 order对象");
    end
    
    rule "rules_3"
        when
            $customer:Customer(name matches "张.*");
        then
        System.out.println("matches触发");
    end
    rule "rules_4"
        when
            $customer:Customer(name not matches "张.*");
        then
        System.out.println("not matches触发");
    end
    
    @Test
        public void test4(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
    //        Order order = new Order();
            Customer customer = new Customer();
            List<Order> orderList = new ArrayList<>();
    //        orderList.add(order);
            customer.setOrderList(orderList);
            customer.setName("张星星");
            //第四步 插入事实对象到session中
    //        kieSession.insert(order);
            kieSession.insert(customer);
            //第五步 执行规则引擎
    //        kieSession.fireAllRules();
            kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rules_3"));
            //第六步 关闭规则引擎
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    
结果部分

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

  1. insert

    函数insert的作用与我们在Java类当中调用StatefulKnowledgeSession对象的insert方法的作用相同,都是用来将一个Fact对象插入到当前的 Working Memory当中
    需注意:一旦调用insert宏函数,那么Drools 会重新与所有的规则再重新匹配一次,对于没有设置no-loop属性为true的规则,如果条件满足,不管其之前是否执行过都会再执行一次,这个特性不仅存在于insert 宏函数上,后面介绍的update、retract 宏函数同样具有该特性,所以在某些情况下因考虑不周调用insert、update或retract容易发生死循环

    示例:

    rule "rules_5"
    when
        eval(true);
    then
        Customer cus = new Customer();
        cus.setName("张三");
        insert(cus);
        System.out.println("内置insert方法触发");
    end
    
    rule "rules_6"
    when
        $customer:Customer(name == "张三");
    then
        System.out.println("内置insert方法触发"+$customer.getName());
    end
    
    @Test
        public void test5(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
            kieSession.fireAllRules();
            //第六步 关闭规则引擎
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

    在这里插入图片描述

  2. update

    update函数意义与其名称一样,用来实现对当前Working Memory当中的Fact进行更新,用来告诉当前的Working Memory该Fact 对象已经发生了变化。l
    示例:

    rule "rules_7"
    //	no-loop true
    when
        $customer:Customer(name == "李四");
    then
        $customer.setName("张三");
        update($customer)
        System.out.println("内置update方法触发");
    end
    rule "rules_6"
    when
        $customer:Customer(name == "张三");
    then
        System.out.println("内置update方法触发"+$customer.getName());
    end
    
    	@Test
        public void test6(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
            Customer customer = new Customer();
            customer.setName("李四");
            //第四步 插入事实对象到session中
            kieSession.insert(customer);
            //第五步 执行规则引擎
            kieSession.fireAllRules();
            //第六步 关闭规则引擎
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    
  3. retract

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

    rule "rules_9"
    when
        $customer:Customer(name == "李四");
    then
        $customer.setName("张三");
    //    retract($customer)
        System.out.println("内置retract方法触发");
    end
    rule "rules_10"
    when
        $customer:Customer();
    then
        System.out.println("内置retract方法触发"+$customer.getName());
    end
    
    	@Test
        public void test6(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
            Customer customer = new Customer();
            customer.setName("李四");
            //第四步 插入事实对象到session中
            kieSession.insert(customer);
            //第五步 执行规则引擎
            kieSession.fireAllRules();
            //第六步 关闭规则引擎
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    
属性部分

在这里插入图片描述

  1. salience

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

    rule "attributes_1"
    salience 1
    when
        eval(true)
    then
        System.out.println("attributes_1");
    end
    
    rule "attributes_2"
    salience 2
    when
        eval(true)
    then
        System.out.println("attributes_2");
    end
    
        @Test
        public void test7(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
    
    
            kieSession.fireAllRules();
    
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

在这里插入图片描述

  1. no-loop

    作用是用来控制已经执行过的规则在条件再次满足时是否再次执行。no-loop 属性的值是一个布尔型,默认情况下规则的no-loop属性的值为false,如果no-loop属性值为true,那么就表示该规则只会被引擎检查一次,
    如果满足条件就执行规则的 RHS部分,如果引擎内部因为对Fact更新引起引擎再次启动检查规则,那么它会忽略掉所有的noloop属性设置为true的规则。
    示例:

    rule "attributes_3"
        salience 1
        no-loop true
    when
        $customer:Customer(name == "张三");
    then
        update($customer)
        System.out.println("customer name:"+$customer.getName());
    end
    
        @Test
        public void test7(){
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
            Customer customer = new Customer();
            customer.setName("张三");
    
            kieSession.insert(customer);
    
            kieSession.fireAllRules();
    
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

    没有no-loop结果

在这里插入图片描述

no-loop结果
在这里插入图片描述

  1. date-effective

    作用是用来控制规则只有在到达后才会触发,在规则运行时,引擎会自动拿当前操作系统的时候与date-effective 设置的时间值进行比对,**只有当系统时间>=date-effective设置的时间值时,规则才会触发执行,否则执行将不执行。**在没有设置该属性的情况下,规则随时可以触发,没有这种限制。date-effective的值为一个日期型的字符串,默认情况下,date-effective 可接受的日期格式为“dd-MMM-yyyy”

    在实际使用的过程当中,如果您不想用这种时间的格式,那么可以在调用的Java代码中通过使用System.setProperty(Stringkey,String value)方法来修改默认的时间格式

    在java文件中添加此条命令: System.setProperty(drools.dateformat",“yyyy-MM-dd”);

    示例:

    rule "attributes_4"
        date-effective "2022-9-17"
    when
        eval(true)
    then
        System.out.println("date-effective");
    end
    
        @Test
        public void test7(){
            System.setProperty("drools.dateformat","yyyy-MM-dd");
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
    
            kieSession.fireAllRules();
    
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    
  2. date-expires

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

  3. enabled

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

  4. dialect

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

  5. activation-group

    作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同activation-group属性的规则中只要有一个会被执行,其它的规则都将不再执行。
    也就是说,**在一组具有相同activation-group属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行。**当然对于具有相同activation-group属性的规则当中究竟哪一个会先执行,则可以用类似salience之类属性来实现。
    示例:

    rule "attributes_5"
        activation-group "test"
    when
        eval(true)
    then
        System.out.println("attributes_5 execute");
    end
    
    rule "attributes_6"
        salience 2
        activation-group "test"
    when
        eval(true)
    then
        System.out.println("attributes_6 execute");
    end
    
        @Test
        public void test7(){
            System.setProperty("drools.dateformat","yyyy-MM-dd");
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
    
            kieSession.fireAllRules();
    
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

    在一组具有相同activation-group属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行。

  6. agenda-group

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

    rule "attributes_7"
        agenda-group "001"
    when
        eval(true)
    then
        System.out.println("attributes_7 execute");
    end
    
    rule "attributes_8"
        agenda-group "002"
    when
        eval(true)
    then
        System.out.println("attributes_8 execute");
    end
    
        @Test
        public void test7(){
            System.setProperty("drools.dateformat","yyyy-MM-dd");
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
            kieSession.getAgenda().getAgendaGroup("002").setFocus();
            kieSession.fireAllRules();
    
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

    设置焦点:kieSession.getAgenda().getAgendaGroup(“002”).setFocus();

    或者设置

    auto-focus
    
  7. auto-focus

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

  8. timer

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

    方式一: timer (int: ?)
    此种方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
    方式二: timer(cron: )
    此种方式使用标准的unix cron表达式的使用方式来定义规则执行的时间。

    示例:

    rule "rule_timer_1"
    timer (5s 2s)
    when
    then
        System.out.println("规则rule_timer_1触发时间为:" +
        new SimpleDateFormat("yyyy-MM-dd HH:m()m:ss").format(new Date()));
    end
    
    rule "rule_timer_2"
    timer (cron:0/1 * * * * ?)
    when
    then
        System.out.println("规则rule_timer_2触发时间为:" +
        new SimpleDateFormat("yyyy-MM-dd HH:m()m:ss").format(new Date()));
    end
    
    @Test
        public void test8() throws InterruptedException {
            System.setProperty("drools.dateformat","yyyy-MM-dd");
            //第一步 获取KieServices
            KieServices kieServices = KieServices.Factory.get();
            //第二步 获取kieContainer
            KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
            //第三步 获取kieSession
            KieSession kieSession = kieClasspathContainer.newKieSession();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    kieSession.fireUntilHalt();
                }
            }).start();
    
            Thread.sleep(10000);
            kieSession.halt();
            kieSession.dispose();
            System.out.println("规则执行完成,关闭规则");
        }
    

在这里插入图片描述

在这里插入图片描述

五、Drools高级语法

在这里插入图片描述

global全局变量

全局变量,一般用作执行规则后的结果数据返回或对具体某个服务调用等,如一个电子邮件服务的实例,在调用规则引擎的集成代码中,获取emailService对象,然后将其设置在工作内存中。
语法结构为: global 对象类型 对象名称
示例:

import java.util.List;

global java.util.List myGlobalList

rule "global_rule1"
when
    eval(true)
then
    myGlobalList.add("Hello World");
    System.out.println("global_rule1 is execute...");
end

rule "global_rule2"
when
    eval(true)
then
    System.out.println("myGlobalList的元素个数:"+myGlobalList.size());
    System.out.println("global_rule2 is execute...");
end
    @Test
    public void test9() throws InterruptedException {
        //第一步 获取KieServices
        KieServices kieServices = KieServices.Factory.get();
        //第二步 获取kieContainer
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        //第三步 获取kieSession
        KieSession kieSession = kieClasspathContainer.newKieSession();

        List<String> list = new ArrayList();
        kieSession.setGlobal("myGlobalList",list);

        kieSession.fireAllRules();

        kieSession.dispose();
        System.out.println("规则执行完成,关闭规则:"+list);
    }
query查询

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

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

示例:

import pojo.*;

//不带参数的查询
query "query-1"
    $person:Person(age > 30)
end

//带参数的查询
query "query-2"(String nameParam)
    $person:Person(age > 30,name == nameParam)
end
    @Test
    public void test10()  {
        //第一步 获取KieServices
        KieServices kieServices = KieServices.Factory.get();
        //第二步 获取kieContainer
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        //第三步 获取kieSession
        KieSession kieSession = kieClasspathContainer.newKieSession();

        Person person = new Person();
        person.setAge(32);
        person.setName("tjg");
        kieSession.insert(person);

        Person person2 = new Person();
        person2.setAge(31);
        person2.setName("tjg2");
        kieSession.insert(person2);

        kieSession.fireAllRules();

        QueryResults queryResults = kieSession.getQueryResults("query-1");
        System.out.println("queryResults size is "+queryResults.size());
        for (QueryResultsRow queryResult : queryResults) {
            Person person1 = (Person) queryResult.get("$person");
            System.out.println("person1: "+person1);
        }

        QueryResults queryResults2 = kieSession.getQueryResults("query-2","tjg");
        System.out.println("queryResults2 size is "+queryResults2.size());
        for (QueryResultsRow queryResult : queryResults2) {
            Person person1 = (Person) queryResult.get("$person");
            System.out.println("person1: "+person1);
        }

        kieSession.dispose();
        System.out.println("规则执行完成,关闭规则:");
    }
function函数

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

function String format(String name){
    return "hello" + name;
}

函数的返回类型与参数类型与java的规则一样示例:

function String format(String name){
    return "hello" + name;
}

rule "function_rule"
    when
        $person:Person(name != null && age > 30)
    then
        String format = format($person.getName());
        System.out.println(format);
end 
    @Test
    public void test10()  {
        //第一步 获取KieServices
        KieServices kieServices = KieServices.Factory.get();
        //第二步 获取kieContainer
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        //第三步 获取kieSession
        KieSession kieSession = kieClasspathContainer.newKieSession();

        Person person = new Person();
        person.setAge(32);
        person.setName("tjg");
        kieSession.insert(person);

        Person person2 = new Person();
        person2.setAge(31);
        person2.setName("tjg2");
        kieSession.insert(person2);

        kieSession.fireAllRules();

        kieSession.dispose();
        System.out.println("规则执行完成,关闭规则:");
    }

name){
return “hello” + name;
}

rule “function_rule”
when
KaTeX parse error: Expected 'EOF', got '&' at position 28: …n(name != null &̲& age > 30) …person.getName());
System.out.println(format);
end


~~~java
    @Test
    public void test10()  {
        //第一步 获取KieServices
        KieServices kieServices = KieServices.Factory.get();
        //第二步 获取kieContainer
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        //第三步 获取kieSession
        KieSession kieSession = kieClasspathContainer.newKieSession();

        Person person = new Person();
        person.setAge(32);
        person.setName("tjg");
        kieSession.insert(person);

        Person person2 = new Person();
        person2.setAge(31);
        person2.setName("tjg2");
        kieSession.insert(person2);

        kieSession.fireAllRules();

        kieSession.dispose();
        System.out.println("规则执行完成,关闭规则:");
    }
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值