1

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引擎的工作
insertLogicalinsert增强版,需声明撤回事件,或待不在匹配条件后自动撤回
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详解

<div id="import_function"></div>

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 达!

<div id="global_detail"></div>

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<People> getPeoples() {
        List<People> 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<People> 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)

<div id="querys_detail"></div>

2.3 querys 查询

avatar
  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)

<div id="declare_detail"></div>

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


WaterMin
33 声望5 粉丝

只会抄袭的码农