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

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)

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

喜欢听相声的朋友,也可以来我的 YouTube,来听郭老师的相声    秋酿


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350