规则引擎Drools-基础知识和简单示例

Drools

Drools(JBoss Rules )具有一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。业务分析师或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业务规则。
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。

Drools安装

一、从官网下载以下两个zip包 . http://www.drools.org/download/download.html
drools-distribution-6.5.0.Final.zip
droolsjbpm-tools-distribution-6.5.0.Final.zip
二、安装eclipse插件

  1. 解压droolsjbpm-tools-distribution-6.5.0.Final.zip
  2. 在eclipse的安装目录的dropins包下面创建文件夹drools, 将droolsjbpm-tools-distribution-6.5.0.Final.zip 解压出来的features和plugins复制 到刚刚新建立的drools包中,

重启eclipse ,在Window->Preferences,就能看到有Drools这个目录了
三、配置运行环境
解压drools-distribution-6.5.0.Final.zip
WA1kFGC.png

四、重启eclipse

Drools的常用API

主要有KnowledgeBuilder、Knowledgebase、StatefulKnowledgeSession、StatelessKnowledgeSession等。

KnowledgeBuilder

KnowledgeBuilder 的作用就是用来在业务代码当中收集已经编写好的规则,然后对这些规则文件进行编译,最终产生一批编译好的规则包(KnowledgePackage)给其它的应用程序使用。KnowledgeBuilder 在编译规则的时候可以通过其提供的 hasErrors()方法得到编译规则过程中发现规则是否有错误,如果有的话通过其提供的 getErrors()方法将错误打印出来,以帮助我们找到规则当中的错误信息。
通过 KnowledgeBuilder 编译的规则文件的类型可以有很多种,如.drl 文件、.dslr 文件或一个 xls 文件等。

    KnowledgeBuilder kbuilder=KnowledgeBuilderFactory.newKnowledgeBuilder(); 
     kbuilder.add(ResourceFactory.newClassPathResource("test.drl", Test.class),ResourceType.DRL); 
     if(kbuilder.hasErrors()){ 
         System.out.println("规则中存在错误,错误消息如下:"); 
         KnowledgeBuilderErrors kbuidlerErrors=kbuilder.getErrors();
         for(Iterator iter=kbuidlerErrors.iterator();iter.hasNext();){ 
            System.out.println(iter.next()); 
         } 
     } 
     Collection kpackage=kbuilder.getKnowledgePackages();//产生规则包的集合

Knowledgebase

Knowledgebase 是 Drools 提供的用来收集应用当中知识(knowledge)定义的知识库对象,在一个 Knowledgebase 当中可以包含普通的规则(rule)、规则流(rule flow)、函数定义(function)、用户自定义对象(type model)等。

Knowledgeba<x>se kba<x>se=Knowledgeba<x>seFactory.newKnowledgeba<x>se();

或者

 Knowledgeba<x>seConfiguration kbConf = Knowledgeba<x>seFactory.newKnowledgeba<x>seConfiguration(); 
 kbConf.setProperty( "org.drools.sequential", "true"); 
 Knowledgeba<x>se kba<x>se = Knowledgeba<x>seFactory.newKnowledgeba<x>se(kbConf); 

StatefulKnowledgeSession

规则编译完成之后,接下来就需要使用一个 API 使编译好的规则包文件在规则引擎当中运行起来。在 Drools5 当中提供了两个对象与规则引擎进行交互:StatefulKnowledgeSession和 StatelessKnowledgeSession。

 StatefulKnowledgeSession statefulKSession=kba<x>se.newStatefulKnowledgeSession(); 
 statefulKSession.setGlobal("globalTest", new ob<x>ject());//设置一个global对象
 statefulKSession.insert(new ob<x>ject());//插入一个fact对象
 statefulKSession.fireAllRules(); 
 statefulKSession.dispose();

StatefulKnowledgeSession 将规则当中需要使用的 fact 对象插入进去、将规则当中需要用到的 global 设置进去,然后调用 fireAllRules()方法触发所有的规则执行,最后调用 dispose()方法将内存资源释放。

StatelessKnowledgeSession

StatelessKnowledgeSession 的作用与 StatefulKnowledgeSession 相仿,它们都是用来接收业务数据、执行规则的。事实上,StatelessKnowledgeSession 对 StatefulKnowledgeSession 做了包装,使得在使用 StatelessKnowledgeSession 对象时不需要再调用 dispose()方法释放内存资源了。

 StatelessKnowledgeSession statelessKSession=kba<x>se.newStatelessKnowledgeSession(); 
 ArrayList list=new ArrayList(); 
 list.add(new ob<x>ject()); 
 list.add(new ob<x>ject()); 
 statelessKSession.execute(list);

Fact 对象

Fact是指在Drools规则应用当中,将一个普通的JavaBean插入到规则的WorkingMemory当中后的对象。规则可以对 Fact 对象进行任意的读写操作,当一个 JavaBean 插入到WorkingMemory 当中变成 Fact 之后,Fact 对象不是对原来的 JavaBean 对象进行 Clon,而是原来 JavaBean 对象的引用。

规则

规则文件

在 Drools 当中,一个标准的规则文件就是一个以“.drl”结尾的文本文件,由于它是一个标准的文本文件,所以可以通过一些记事本工具对其进行打开、查看和编辑。规则是放在规则文件当中的,一个规则文件可以存放多个规则,除此之外,在规则文件当中还可以存放用户自定义的函数、数据对象及自定义查询等相关在规则当中可能会用到的一些对象。

一个标准的规则文件的结构代码清单如下:

package package-name package 
imports 
globals 
functions 
queries 
rules

package 是对于规则文件中规则的管理只限于逻辑上的管理,而不管其在物理上的位置如何。

规则语言

规则是在规则文件当中编写,所以要编写一个规则首先需要先创建一个存放规则的规则文件。一个规则文件可以存放若干个规则,每一个规则通过规则名称来进行标识。

一个标准规则的结构:

rule "name" rule
 attributes 
 when 
 LHS 
 then t
 RHS 
end

一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)。对于一个完整的规则来说,这三个部分都是可选的。

条件部分

条件部分又被称之为 Left Hand Side,简称为 LHS。
如果 LHS 部分没空的话,那么引擎会自动添加一个 eval(true)的条件。
LHS 部分是由一个或多个条件组成,条件又称之为 pattern(匹配模式),多个 pattern之间用可以使用 and 或 or 来进行连接,同时还可以使用小括号来确定 pattern 的优先级。
对于绑定变量的命名,通常的作法是为其添加一个“”符号作为前缀,这样可以很好的与Fact的属性区别开来;绑定变量不仅可以用在对象上,也可以用在对象的属性上面,命名方法与对象的命名方法相同。如:rule“rule1”when
customer:Customer()
then

end

约束连接
对于对象内部的多个约束的连接,可以采用“&&”(and)、“||”(or)和“,”(and)来实现。
“,”与“&&”和“||”不能混合使用,也就是说在有“&&”或“||”出现的 LHS 当中,是不可以有“,”连接符出现的,反之亦然。
比较操作符
十二种类型的比较操作符,分别是:>、>=、<、<=、= =、!=、contains、not contains、memberof、not memberof、matches、not matches;

contains 是用来检查一个 Fact 对象的某个字段(该字段要是一个 Collection或是一个 Array 类型的对象)是否包含一个指定的对象。
memberOf 是用来判断某个 Fact 对象的某个字段是否在一个集合(Collection/Array)当中,用法与 contains 有些类似,但也有不同。
matches 是用来对某个 Fact 的字段与标准的 Java 正则表达式进行相似匹配,被比较的字符串可以是一个标准的 Java 正则表达式,但有一点需要注意,那就是正则表达式字符串当中不用考虑“”的转义问题。

结果部分

结果部分又被称之为 Right Hand Side,简称为 RHS,在一个规则当中 then 后面部分就是 RHS,只有在 LHS 的所有条件都满足时 RHS 部分才会执行。

在 Drools 当中,在 RHS 里面,提供了一些对当前 Working Memory 实现快速操作的宏宏函数或对象,比如 insert/insertLogical、update 和 retract 就可以实现对当前 Working Memory中的 Fact 对象进行新增、删除或者是修改;如果您觉得还要使用 Drools 当中提供的其它方法,那么您还可以使用另一外宏对象 drools,通过该对象可以使用更多的操作当前 Working Memory 的方法;同时 Drools 还提供了一个名为 kcontext 的宏对象,使我们可以通过该对象直接访问当前 Working Memory 的 KnowledgeRuntime。

  • insert *

用来将一个 Fact 对象插入到当前的 Working Memory 当中。
语法:insert(new Object());

一旦调用 insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配一次,对于没有设置 no-loop 属性为 true 的规则,如果条件满足,不管其之前是否执行过都会再执行一次,这个特性不仅存在于 insert 宏函数上,update、retract 宏函数同样具有该特性。

  • insertLogical *

insertLogical 作用与 insert 类似,它的作用也是将一个 Fact 对象插入到当前的 Working Memroy 当中。

  • update *

update 函数意义与其名称一样,用来实现对当前 Working Memory 当中的 Fact 进行更新,update 宏函数的作用与 StatefulSession 对象的 update 方法的作用基本相同,都是用来告诉当前的 Working Memory 该 Fact 对象已经发生了变化。它的用法有两种形式,一种是直接更新一个 Fact 对象,另一种为通过指定 FactHandle 来更新与指定 FactHandle 对应的 Fact 对象。

语法:
1.update(new Object());
2.update(new FactHandle(),new Object());

  • retract *

retract 是用来将 Working Memory 当中某个 Fact 对象从 Working Memory 当中删除。

  • drools *

在规则文件里更多的实现对当前的 Working Memory 控制,那么可以使用drools 宏对象实现,通过使用 drools 宏对象可以实现在规则文件里直接访问 Working Memory。
使用 drools 宏对象,可以得到很多操纵 Working Memory 的方法,如果想查看 drools 宏对象具有哪些方法可以使用,可以通过按“ALT”+“/”这两个功能键实现。

kcontext
kcontext 是 Drools 提 供 的 一 个 宏 对 象 , 它 的 作 用 主 要 是 用 来 得 到 当 前 的KnowledgeRuntime 对象,KnowledgeRuntime 对象可以实现与引擎的各种交互。

modify
modify 是一个表达式块,它可以快速实现对 Fact 对象多个属性进行修改,修改完成后会自动更新到当前的 Working Memory 当中
语法:

modify(fact-expression){ 
 <修改 Fact 属性的表达式>[,<修改 Fact 属性的表达式>*] 
} 

规则属性

Drools5 当中,规则的属性共有 13 个,它们分别是:activation-group、agenda-group、auto-focus、date-effective、date-expires、dialect、duration、enabled、lock-on-active、no-loop、ruleflow-group、salience、when。

salience
作用是用来设置规则执行的优先级,
salience 属性的值是一个数字,数字越大执行优先级越高,同时它的值可以是一个负数。默认情况下,规则的 salience 默认值为 0,所以如果我们不手动设置规则的 salience 属性,那么它的执行顺序是随机的。

no-loop
no-loop 属性的作用是用来控制已经执行过的规则在条件再次满足时是否再次执行。默认情况下规则的 no-loop属性的值为 false,如果 no-loop 属性值为 true,那么就表示该规则只会被引擎检查一次。

date-effective
引擎会自动拿当前操作
系统的时候与 date-effective 设置的时间值进行比对,只有当系统时间>=date-effective 设置的时间值时,规则才会触发执行,否则执行将不执行。
date-effective 的值为一个日期型的字符串,默认情况下,date-effective 可接受的日期格式为“dd-MMM-yyyy”。如果您的操作系统为英文的,那么应该写成“25-Sep-2009”;如果是中文操作系统“25-九月-2009”。

date-expires
date-expires 的作用是用来设置规则的有
效期,引擎在执行规则的时候,会检查规则有没有 date-expires 属性,如果有的话,那么会将这个属性的值与当前系统时间进行比对,如果大于系统时间,那么规则就执行,否则就不执行。

enabled
enabled 属性比较简单,它是用来定义一个规则是否可用的。该属性的值是一个布尔值,
默认该属性的值为 true,表示规则是可用的,如果手工为一个规则添加一个 enabled 属性,并且设置其 enabled 属性值为 false,那么引擎就不会执行该规则。

dialect
该属性用来定义规则当中要使用的语言类型,默认情况下,如果没有手工设置规则的 dialect,那么使用的 java 语言。

duration
如果设置了该属性,那么规则将在该属性指定的值之后在另外一个线程里触发。该属性对应的值为一个长整型,单位是毫秒,该规则将在xx毫秒之后在另外一个线程里触发。

lock-on-active
当在规则上使用 ruleflow-group 属性或 agenda-group 属性的时候,将 lock-on-action 属性的值设置为 true,可能避免因某些 Fact 对象被修改而使已经执行过的规则再次被激活执行。

activation-group
的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同 activation-group 属性的规则中只要有一个会被执行,其它的规则都将不再执行。

agenda-group
引擎在调用这些设置了 agenda-group 属性的规则的时候需要显示的指定某个 Agenda Group 得到 Focus(焦点),这样位于该 Agenda Group 当中的规则才会触发执行,否则将不执行。

auto-focus
作用是用来在已设置了 agenda-group 的规则上设置该规则是否可以自动独取 Focus,如果该属性设置为 true,那么在引擎执行时,就不需要显示的为某个 Agenda Group 设置 Focus,否则需要。

ruleflow-group
作用是用来将规则划分为一个个的组,然后在规则流当中通过使用 ruleflow-group 属性的值,从而使用对应的规则。

函数

函数是定义在规则文件当中一代码块,作用是将在规则文件当中若干个规则都会用到的业务操作封装起来,实现业务代码的复用,减少规则编写的工作量。
函数的编写位置可以是规则文件当中 package 声明后的任何地方。
语法:

function void/Object functionName(Type arg...) { 
    /*函数体的业务代码*/
}

业务代码的书写采用的是标准的 Java 语法。

Drools 的函数定义当中没有可见范围的设定,而 Java 当中可以通过 public、private 之类来设置方法的可见范围。

查询

查询是 Drools 当中提供的一种根据条件在当前的 WorkingMemory 当中查找 Fact 的方法。查询是定义在规则文件当中,和函数一样,查询的定义可以是 package 语句下的任意位置,在 Drools 当中查询可分为两种:一种是不需要外部传入参数;一种是需要外部传入参数。

无参数查询
在 Drools 当中查询以 query 关键字开始,以 end 关键字结束,在 package 当中一个查询要有唯一的名称,查询的内容就是查询的条件部分,条件部分内容的写法与规则的 LHS 部分写法完全相同。

语法:

query "query name"
    #conditions
end

查 询 的 调 用 是 由 StatefulSession 完 成 的 , 通 过 调 用 StatefulSession 对 象 的getQueryResults(String queryName)方法实现对查询的调用,该方法的调用会返回一个QueryResults 对象,QueryResults 是一个类似于 Collection 接口的集合对象,在它当中存放在若干个 QueryResultsRow 对象,通过 QueryResultsRow 可以得到对应的 Fact 对象,从而实现根据条件对当前 WorkingMemory 当中 Fact 对象的查询。

//调用查询
 QueryResults queryResults=statefulSession.getQueryResults("testQuery"); 
 for(QueryResultsRow qr:queryResults){ 
     Customer cus=(Customer)qr.get("customer"); 
     //打印查询结果
     System.out.println("customer name :"+cus.getName()); 
 } 
 statefulSession.dispose(); 

参数查询
和不带参数的查询相比,唯一不同之外就是在查询名称后面多了一个用括号括起来的输入参数,查询可接收多个参数,多个参数之间用“,”分隔,每个参数都要有对应的类型声明。

语法:

query "query name" (Object obj,...) 
    #conditions
end

这里传入参数变量名前添加前缀“$”符号,是为了和条件表达式中相关变量区别开来。

对象定义

在 Drools 当中,可以定义两种类型的对象:一种是普通的类型 Java Fact 的对象;另一种是用来描述 Fact 对象或其属性的元数据对象。

Fact 对象定义
Fact 对象就是普通的具有若干个属性及其对应的 getter 与 setter方法的 JavaBean 对象。
在规则文件当中定义 Fact 对象要以 declare 关键字开头,以 end 关键字结尾,中间部分就是该 Fact 对象的属性名及其类型等信息的声明。
示例:

declare Address 
     city : String 
     addressName : String 
end

元数据定义
元数据就是用来描述数据的数据。
元数据定义采用的是“@”符号开头,后面是元数据的属性名(属性名可以是任意的),然后是括号,括号当中是该元数据属性对应的具体值(值是任意的)。

示例:

@metadata_key( metadata_value ) 

Drools5与Drools6的区别

规则收集加载部分:Drools6通过kmodule.xml配置不同的drl文件路径和命名。

规则更新部分:由于采用了KIE机制,Drools6可通过Maven实现规则jar包的热部署。



请为这篇文章评分:
( 已有 1 人评分, 平均得分: 4 分 )

标签: drools JAVA规则引擎 规则引擎

发表评论: