欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

drools 规则文件 —— 语法

程序员文章站 2022-05-28 11:16:59
...
原文:[url]http://liureying.blog.163.com/blog/static/615135201111394058945/[/url]
[color=red][b]更详细的看这里[/b][/color]:drools规则语法(一) [url]http://kingsun1980.iteye.com/blog/459272[/url]
使用 Drools 和 JPA 实现持续的实时数据分析 [url]http://www.ibm.com/developerworks/cn/java/j-drools5/[/url]


在 Drools 当中,规则的编译与运行要通过Drools 提供的各种API 来实现,这些API 总体来讲可以分为三类:规则编译、规则收集和规则的执行。完成这些工作的API 主要有[b][color=darkblue]KnowledgeBuilder、KnowledgeBase、StatefulKnowledgeSession、StatelessKnowledgeSession[/color][/b]、、等,它们起到了对规则文件进行收集、编译、查错、插入fact、设置global、执行规则或规则流等作用,在正式接触各种类型的规则文件编写方式及语法讲解之前,我们有必要先熟悉一下这些API 的基本含义及使用方法。


[color=red][b]KnowledgeBuilder [/b][/color]的作用就是用来在业务代码当中收集已经编写好的规则, 然后对这些规则文件进行编译, 最终产生一批编译好的规则包(KnowledgePackage)给其它的应用程序使用。
通过KnowledgeBuilder 编译的规则文件的类型可以有很多种,如.drl 文件、.dslr 文件或一个xls 文件等。产生的规则包可以是具体的规则文件形成的,也可以是规则流(rule flow)文件形成的,在添加规则文件时,需要通过使用ResourceType 的枚举值来指定规则文件的类型;同时在指定规则文件的时候drools 还提供了一个名为ResourceFactory 的对象,通过该对象可以实现从Classpath、URL、File、ByteArray、Reader 或诸如XLS 的二进制文件里添加载规则。

[color=red][b]KnowledgeBase [/b][/color]是Drools 提供的用来收集应用当中知识(knowledge)定义的知识库对象,在一个KnowledgeBase 当中可以包含普通的规则(rule)、规则流(rule flow)、函数定义(function)、用户自定义对象(type model)等。KnowledgeBase 本身不包含任何业务数据对象(fact 对象,后面有相应章节着重介绍fact 对象),业务对象都是插入到由KnowledgeBase产生的两种类型的session 对象当中(StatefulKnowledgeSession 和StatelessKnowledgeSession,后面会有对应的章节对这两种类型的对象进行介绍),通过session 对象可以触发规则执行或开始一个规则流执行。

[color=red][b]StatefulKnowledgeSession [/b][/color]对象是一种最常用的与规则引擎进行交互的方式,它可以与规则引擎建立一个持续的交互通道,在推理计算的过程当中可能会多次触发同一数据集。在用
户的代码当中,最后使用完StatefulKnowledgeSession 对象之后,一定要调用其dispose()方法以释放相关内存资源。StatefulKnowledgeSession 可以接受外部插入(insert)的业务数据——也叫fact。

[color=red][b]StatelessKnowledgeSession [/b][/color]的作用与StatefulKnowledgeSession 相仿,它们都是用来接收业务数据、执行规则的。事实上,StatelessKnowledgeSession 对StatefulKnowledgeSession 做了包装,使得在使用StatelessKnowledgeSession 对象时不需要再调用dispose()方法释放内存资源了。
因为StatelessKnowledgeSession 本身所具有的一些特性,决定了它的使用有一定的局限性。在使用StatelessKnowledgeSession 时不能进行重复插入fact 的操作、也不能重复的调用fireAllRules()方法来执行所有的规则,对应这些要完成的工作在StatelessKnowledgeSession当中只有execute(…)方法,通过这个方法可以实现插入所有的fact并且可以同时执行所有的规则或规则流,事实上也就是在执行execute(…)方法的时候就在StatelessKnowledgeSession内部执行了insert()方法、fireAllRules()方法和dispose()方法。

[color=red][b]fact [/b][/color]对象通常是一个普通的Java 的POJO,一般它们会有若干个属性,每一个属性都会对应getter 和setter 方法,用来对外提供数据的设置与访问。一般来说,在Drools 规则引擎当中,fact 所承担的作用就是将规则当中要用到的业务数据从应用当中传入进来,对于规则当中产生的数据及状态的变化通常不用fact 传出。如果在规则当中需要有数据传出,那么可以通过在StatefulKnowledgeSession 当中设置global 对象来实现,一个global 对象也是一个普通的Java 对象,在向StatefulKnowledgeSession 当中设置global 对象时不用insert 方法而用setGlobal 方法实现。
    public static void main(String[] args) {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("test.drl",Test.class), ResourceType.DRL);
Collection<KnowledgePackage> kpackage =kbuilder.getKnowledgePackages();
KnowledgeBaseConfiguration kbConf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
kbConf.setProperty("org.drools.sequential", "true");
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbConf);
kbase.addKnowledgePackages(kpackage);//将KnowledgePackage集合添加到KnowledgeBase当中
StatefulKnowledgeSession statefulKSession = kbase.newStatefulKnowledgeSession();
statefulKSession.setGlobal("globalTest", new Object());//设置一个global对象
statefulKSession.insert(new Object());//插入一个fact对象
statefulKSession.fireAllRules();
statefulKSession.dispose();
}



[b][color=red]Drools 分为两个主要部分:构建( Authoring )和运行时( Runtime )[/color][/b]。 这遍文章介绍 构建时 .drl 或 .xml 规则文件编写
[color=red][b]1.规则文件语法和支持的语言[/b][/color]
规则文件有自己的语法用于绑定参数,条件判断跟 function ,queries等构成规则文件部分。
其它部分可以使用规则文本支持语言的脚步:目前支持:mvel和Java。默认使用java.
不管使用那种语言,要遵守那种语言的语法
示例:
[b]package [/b]com.demo
[b]rule [/b]"It of valid age"
[b]when[/b]
[color=darkblue]$a : Applicant( age < 18 )[/color]
[b]then [/b]
[color=violet]$a.setValid(false); [/color]
[b]end[/b]

note:
[b]黑体[/b]字是规则文件关键字
[color=darkblue]该颜色字体是规则文件语法[/color]
[color=violet]该颜色字体是java语法[/color]
$a是规则内的变量,在规则内对该规则变量操作

[color=red][b]2.规则文件构成[/b][/color]
[color=darkblue]package(规则文件所在包*)
import(导入java 包)
globals
function(函数)
queries(查找)
rules(规则*)[/color]

[color=red][b]3.规则引擎处理规则文件流程 [/b][/color]
输入参数 ---> 引擎读规则文件并绑定输入参数 ---> 处理规则满足条件则按结果部分逻辑处理

[color=red][b]4.编写规则文件思路[/b][/color]
import 必须的包和类,和Java静态方法,语句要以;号结束等
java属性处理语句只能出现rule的结果部分,而在条件部分则只能是创建语句
在条件部分要使用规则引擎的语法


[color=red][b]5.语法介绍[/b][/color]
[b]绑定参数语法:[/b]
$[绑定变量名] : Object([field 约束])

示例:
$add : Address() add 绑定外面传入的Address对象
$add : new Address() add 绑定新建的Address对象
$name:String(); 传入一个字符串与name绑定

[b]条件判断[/b]
$绑定变量名 :绑定类型(属性1 比较符合 比较值)
note:
括号内可以包含多个属性比较有 “&&”、 “||” , “,”
“&&”表示and、 “||”表示or , “,”表示连接

示例:
$app:Applicant(name == "依晨",age<30)
#必须是满足name=依晨,age<30的Applicant

结果部分处理
1.通过insert,update和 retract对当前 Working Memory 中的 Fact 对象进行新增、删除或者是修改。
note:
[color=red]一旦调用insert,update和 retract宏函数,那么 Drools会重新与所有的规则再重新匹配一次,对于没有设置 no-loop 属性为 true的规则,如果条件满足,不管其之前是否执行过都会再执行一次[/color]

[color=darkblue][b]insert[/b][/color]
作用:
在Java类当中调用StatefulKnowledgeSession对象的insert方法的作用相同
语法:
insert(new Object());
示例:
rule "rule1" 
salience 1
when
eval(true);
then
System.out.println("rule1");
Applicant app = new Applicant("kaka",24);
#insert(app);
drools.insert(app);
end


[color=darkblue][b]update [/b][/color]
作用:
update函数意义与其名称一样,用来实现对当前Working Memory当中的Fact进行更
语法:
update(new Object());
示例:
rule "rule2"
salience 1
#no-loop true 不会循环
when
$app:Applicant(name == "依晨",age<30)
then
#update方法2
Applicant app = new Applicant("依晨",$app.getAge() + 1);
update(drools.getWorkingMemory().getFactHandleByIdentity($app),app);

#update方法1
#$app.setAge($app.getAge() + 1);
#update($app);
System.out.println("------" + $app.getName()+"("+ $app.getAge() + ")");
end


[color=darkblue][b]retract[/b][/color]
作用:
和 StatefulSession 的 retract方法一样,宏函数 retract也是用来将 Working Memory当中
某个 Fact对象从Working Memory当中删除
语法:
update(new Object());
示例:
rule "rule2"
salience 1
when
$app:Applicant(name == "依晨");
then
#retract($app);
drools.retract($app);
end


note:
除了insert,update和 retract函数外还有drools 宏对象来处理规则.
还可以通过$绑定变量名.绑定Java对象的方法
$app.setAge($app.getAge() + 1);



[size=x-large][color=red]例子:[/color][/size]
1. 遍历List:
定义:
package com.pandy.rulemodel;

import com.pandy.model.RhSysGrid;
import com.pandy.model.RhSysGridColumn;
import com.pandy.model.RhSysUser;

import java.util.List;
public class TestProcessModel {
List<RhSysGrid> gridList;
List<RhSysGridColumn> columnList;
List<RhSysUser> userList;
//......
}


启动之前初始化数据:
        Map<String, Object> params = new HashMap<String, Object>();
List<RhSysGrid> gridList = rhService.getAllGrid();
List<RhSysGridColumn> columnList = rhService.getAllGridColumn();
List<RhSysUser> userList = rhService.getAllUser();

TestProcessModel testProcessModel = new TestProcessModel();
testProcessModel.setGridList(gridList);
testProcessModel.setColumnList(columnList);
testProcessModel.setUserList(userList);
params.put("testProcessModel", testProcessModel);
ksession1.startProcess(proId, params);
ksession1.fireAllRules();


工作流RuleTask前面的ScriptTask加入信息到引擎: 省略变量配置等
kcontext.getKnowledgeRuntime().insert(testProcessModel);

规则文件:
package com.pandy.jbpm;


import java.util.List;
import com.pandy.model.RhSysGrid;
import com.pandy.rulemodel.TestProcessModel;

rule "Hello World Rule" ruleflow-group "Print"
when
$testModel : TestProcessModel()
$gridList : List() from collect ( RhSysGrid(gridId<=100) from $testModel.gridList )
then
System.out.println("一个Drools测试例子: Hello World Rule="+ $gridList.size());
end