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用于将数据的更改更新到引擎,并通知引擎重新匹配该事实
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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
1 2 3 4 5 6 7 8 9 10 11 @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
1 2 update1执行====People(sex=0, name=达, age=17, drlType=update) update2执行====People(sex=1, name=达, age=17, drlType=update)
modify 用法与 update类似 1 2 3 4 5 6 7 8 9 rule 'modify' when $p : People(drlType == "update" && sex == 1) then System.out.println("update3执行====" + $p); modify($p){ setSex(-1) } end
1 2 3 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对象时,值已经被改变,只是不出发规则执行   修改后的测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 @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()); }
  修改后的规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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
  执行结果:
1 2 update1执行====People(sex=0, name=达, age=17, drlType=update) test执行====People(sex=1, name=达, age=17, drlType=update)
2.1 import引入java方法 以及 function   导入规则文件需要使用到的外部规则文件或者变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法
被引入的java方法 1 2 3 4 5 6 7 package com.ytooo.utils;public class DroolsStringUtils { public static boolean isEmpty (String param) { return param = = null || "" .equals(param); } }
在规则文件中使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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
执行测试方法,函数执行 1 2 3 4 5 6 7 @Test public void impot () { People people = new People (); people.setDrlType("impot" ); session.insert(people); session.fireAllRules(); }
执行结果
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 定义全局服务以及全局对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.ytooo.globa;import com.ytooo.bean.People;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.List;@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; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.ytooo.bean;import lombok.Data;@Data public class NumCount { private int count; public void plus () { count = count + 1 ; } }
2.2.2.2 在drl脚本中使用全局变量   全局变量以 global 类型 变量名 的方式在规则中定义,在规则Then语句中使用变量名直接对其进行操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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(变量名)的方法,其中变量名要与规则中引入变量名相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @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()); }
输出结果 1 2 [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 查询
  Query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分。Query有一个可选参数集合,每一个参数都有可选的类型。如果没有指定类型,则默认为Object类型。
2.3.1 定义drl查询语句    可以定义多个查询参数,在调用查询时传入
1 2 3 4 5 6 7 8 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匹配对象列表
1 2 3 4 5 6 7 8 9 10 11 12 13 @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 查询结果 1 People(sex=5, name=达, age=null, drlType=query)
2.4 declare 自定义fact对象 2.4.1 declare在drl规则文件中定义: 1 2 3 4 5 6 7 8 9 10 11 12 13 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(实例,属性名,属性值)的方式来赋值变量
1 2 3 4 5 6 7 8 9 10 @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 执行结果 1 People(sex=5, name=达, age=null, drlType=query)
教程代码已提交到ytooo-drools ,欢迎star
Drools规则引擎 系列教程(二)Drools规则语法 & LHS 条件
Drools规则引擎 系列教程(四)Drools 主要API & 决策表
更多好玩好看的内容,欢迎到我的博客交流,共同进步         胡萝卜啵的博客