Drools规则引擎 系列教程(三)Drools规则语法 & RHS动作 & header详解

Drools规则引擎 系列教程(一)SpringBoot整合 & 快速集成上手

Drools规则引擎 系列教程(二)Drools规则语法 & LHS 条件

Drools规则引擎 系列教程(四)Drools 主要 API

教程代码已提交到ytooo-drools,欢迎star

1. RHS动作

  RHS 部分定义了当LHS满足是要进行的操作,规则操作的主要目的是在Drools引擎的工作内存中插入,删除或修改数据。RHS中可以编写代码,可以使用LHS 部分当中定义的绑定变量名以及drl头部定义的全局变量。在RHS当中如果需要条件判断,那么请重新考虑将其放在 LHS 当中,否则就违背了使用规则的初衷。

1.2. 主要操作

动作 描述
set 给属性赋值
modify 将改变通知drolls引擎
update 将改变通知drolls引擎
insert 将新实事插入到drools引擎的工作
insertLogical insert增强版,需声明撤回事件,或待不在匹配条件后自动撤回
delete 删除实事

1.3. Update

  Update用于将数据的更改更新到引擎,并通知引擎重新匹配该事实

package com.ytooo.updat
dialect "java"
import com.ytooo.bean.People

rule 'update1'
    when
       $p : People(drlType == "update" && sex == 0)
    then
        System.out.println("update1执行====" + $p);
        $p.setSex(1);
        update($p)
    end
rule 'update2'
    when
       $p : People(drlType == "update" && sex == 1)
    then
        System.out.println("update2执行====" + $p);
    end
@Test
public void update() {

    People people = new People();
    people.setName("达");
    people.setSex(0);
    people.setAge(17);
    people.setDrlType("update");
    session.insert(people);//插入
    session.fireAllRules();//执行规则
}

当规则1执行后,通过update($p)改变对象值,并重新触发规则2

update1执行====People(sex=0, name=达, age=17, drlType=update)
update2执行====People(sex=1, name=达, age=17, drlType=update)
modify 用法与 update类似
rule 'modify'
    when
      $p : People(drlType == "update" && sex == 1)
    then
       System.out.println("update3执行====" + $p);
       modify($p){
          setSex(-1)
       }
    end
update1执行====People(sex=0, name=达, age=17, drlType=update)
update2执行====People(sex=1, name=达, age=17, drlType=update)
update3执行====People(sex=1, name=达, age=17, drlType=update)
特别注意,当在then中改变变量属性值,但不使用update语句时,在调用测试方法中,打印people对象时,值已经被改变,只是不出发规则执行

  修改后的测试代码:

@Test
public void update() {

    People people = new People();
    people.setName("达");
    people.setSex(0);
    people.setAge(17);
    people.setDrlType("update");
    session.insert(people);//插入
    session.fireAllRules();//执行规则
    System.out.println("test执行====" + people.toString());
}

  修改后的规则:

package com.ytooo.updat
dialect "java"
import com.ytooo.bean.People

rule 'update1'
    when
       $p : People(drlType == "update" && sex == 0)
    then
        System.out.println("update1执行====" + $p);
        $p.setSex(1);
//        update($p)
    end
rule 'update2'
    when
       $p : People(drlType == "update" && sex == 1)
    then
        System.out.println("update2执行====" + $p);
    end
rule 'modify'
    when
      $p : People(drlType == "update" && sex == 1)
    then
       System.out.println("update3执行====" + $p);
       modify($p){
         setSex(-1)
       }
    end

  执行结果:

update1执行====People(sex=0, name=达, age=17, drlType=update)
test执行====People(sex=1, name=达, age=17, drlType=update)

2. drools header详解

2.1 import引入java方法 以及 function

  导入规则文件需要使用到的外部规则文件或者变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法

被引入的java方法
package com.ytooo.utils;

public class DroolsStringUtils {
    public static boolean isEmpty(String param) {
        return param == null || "".equals(param);
    }
}
在规则文件中使用
package com.rules.impor
dialect "java"
import com.ytooo.bean.People
import function com.ytooo.utils.DroolsStringUtils.isEmpty

function String hello(String applicantName) {
    return "Hello " + applicantName + "!";
}

rule "impot"

  when
    $p : People(drlType == "impot")
  then
    System.out.println(isEmpty("我"));
    System.out.println(hello("达"));
  end
执行测试方法,函数执行
 @Test
public void impot() {
    People people = new People();
    people.setDrlType("impot");
    session.insert(people);//插入
    session.fireAllRules();//执行规则
}
执行结果
false
Hello 达!

2.2 Global 全局变量

  Drools规则文件中的全局变量(global variables)是规则文件代码与java代码之间相互交互的桥梁,我们可以利用全局变量让规则文件中的程序使用java代码中的基本变量、缓存信息或接口服务等等。

2.2.1 基本语法:

global 类型 变量名

例如:
global java.util.List list

2.2.2 使用全局变量来传递数据样例

   全局变量可以是一个services或者一个对象,来方便drolls与java之间的数据传输

2.2.2.1 定义全局服务以及全局对象
package com.ytooo.globa;

import com.ytooo.bean.People;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by Youdmeng on 2020/1/14 0014.
 */
@Service
public class GloableService {

    public static List getPeoples() {
        List peoples = new ArrayList<>();
        peoples.add(new People(1, "春", "global"));
        peoples.add(new People(2, "夏", "global"));
        peoples.add(new People(3, "秋", "global"));
        peoples.add(new People(4, "冬", "global"));
        peoples.add(new People(5, "达", "global"));
        return peoples;
    }
}
package com.ytooo.bean;
import lombok.Data;
/**
 * Created by Youdmeng on 2020/1/14 0014.
 */
@Data
public class NumCount {

    private int count;

    public void plus() {
        count = count + 1;
    }
}
2.2.2.2 在drl脚本中使用全局变量

  全局变量以 global 类型 变量名 的方式在规则中定义,在规则Then语句中使用变量名直接对其进行操作

package com.ytooo.globa
dialect "java"

import com.ytooo.bean.People
import  java.lang.Integer

global com.ytooo.globa.GloableService service
global java.util.List list
global com.ytooo.bean.NumCount numCount

rule "global"
    when
        People(drlType == "global")
        $p : People() from service.getPeoples()
    then
        list.add($p);
        numCount.plus();
    end
2.2.2.3 在java代码中声明全局变量,并取值

   在java代码中使用全局变量,首先要使用 session.setGlobal(变量名,变量)的方式声明变量,其中变量名要与规则中引入变量名相同

   若要取值,要使用 session.getGlobal(变量名)的方法,其中变量名要与规则中引入变量名相同

 @Test
public void global() {
    People people = new People();
    people.setDrlType("global");
    session.insert(people);//插入
    //配置全局变量
    List list = new ArrayList<>();
    NumCount numCount = new NumCount();
    GloableService service = new GloableService();
    session.setGlobal("list", list);
    session.setGlobal("numCount", numCount);
    session.setGlobal("service", service);
    session.fireAllRules();//执行规则
    //取出全局变量值
    System.out.println(session.getGlobal("list").toString());
    System.out.println((session.getGlobal("numCount")).toString());
}
输出结果
[People(sex=5, name=达, age=null, drlType=global), People(sex=4, name=冬, age=null, drlType=global), People(sex=3, name=秋, age=null, drlType=global), People(sex=2, name=夏, age=null, drlType=global), People(sex=1, name=春, age=null, drlType=global)]
NumCount(count=5)

2.3 querys 查询

Drools规则引擎 系列教程(三)Drools规则语法 & RHS动作 & header详解_第1张图片
  Query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分。Query有一个可选参数集合,每一个参数都有可选的类型。如果没有指定类型,则默认为Object类型。

2.3.1 定义drl查询语句

   可以定义多个查询参数,在调用查询时传入

package com.ytooo.quey
dialect "java"

import com.ytooo.bean.People

query "queryPeople" (String $name,Integer $sex)
    $p : People(name == $name, sex == $sex)
end
2.3.2 java中进行查询

   使用session.getQueryResults(查询名, 参数, 参数。。。) 来获取QueryResults匹配对象列表

 @Test
public void query() {
    session.insert(new People(1, "春", "query"));
    session.insert(new People(2, "夏", "query"));
    session.insert(new People(3, "秋", "query"));
    session.insert(new People(4, "冬", "query"));
    session.insert(new People(5, "达", "query"));
    QueryResults results = session.getQueryResults("queryPeople", "达", 5);
    for (QueryResultsRow row : results) {
        People p = (People) row.get("$p");
        System.out.println(p);
    }
}
2.3.2 查询结果
People(sex=5, name=达, age=null, drlType=query)

2.4 declare 自定义fact对象

2.4.1 declare在drl规则文件中定义:
package com.ytooo.declar
dialect "java"

declare Love
    feel : String
    continued : String
end
rule "love"
when
    $l : Love()
then
    System.out.println("自定义事件执行: " + $l);
end
2.4.2 在api中使用

  通过 kieBase.getFactType(域名,实事名)的方式获取实事对象并实例
  通过 factType.set(实例,属性名,属性值)的方式来赋值变量

@Test
public void declare() throws IllegalAccessException, InstantiationException {

    FactType factType = kieBase.getFactType("com.ytooo.declar","Love");
    Object obj = factType.newInstance();
    factType.set(obj,"feel","sad");
    factType.set(obj,"continued","永远");
    session.insert(obj);
    session.fireAllRules();
}
2.4.3 执行结果
People(sex=5, name=达, age=null, drlType=query)






教程代码已提交到ytooo-drools,欢迎star

Drools规则引擎 系列教程(二)Drools规则语法 & LHS 条件

Drools规则引擎 系列教程(四)Drools 主要 API

你可能感兴趣的:(Drools规则引擎 系列教程(三)Drools规则语法 & RHS动作 & header详解)