Drools 技术指南
Drools(JBoss Rules )具有一个易于访问企业策略、易于调整以及易于
管理的开源业务规则引擎,符合业内标准,速度快、效率高。业务分析师或审核
人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业
务规则。
JBoss Rules 的前身是 Codehaus 的一个开源项目叫 Drools。最近被纳入
JBoss 门下,更名为 JBoss Rules,成为了 JBoss 应用服务器的规则引擎。
Drools 是为 Java 量身定制的基于 Charles Forgy 的 RETE 算法的规则引擎
的实现。具有了 OO 接口的 RETE,使得商业规则有了更自然的表达。
Drools 的简要概述
Drools 是一款基于 Java 的开源规则引擎,以将复杂多变的规则从硬编码中解放出来,以规则脚本的
形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效
规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码
中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做
出业务决策,从而给编程带来了极大的方便。
下图就是引用了规则引擎后的效果:
图(1-1)
开始我们 Drools 规则引擎之旅
小编是一经验尚浅的 java 工程师,有写的不得当的地方,还请大家海涵。小编
研究的版本是 Drools6.4 版本,目前看的最新的版本是 Drools6.5,上面做了一
些优化,在最后小编会简单的在文中说明一下的。
Drools 新特性
Drools 推出了一套新的基于 KIE(Knowledge Is Everything 知识就是一切)概
念的 API,其目的是将之前版本中对规则引擎繁琐的调用和加载过程加以简
化。
Drools6 给我的最大不同就是把 rules 打包成 jar,使用端通过 kie-ci 来动态从
maven repo 中获取指定 rules jar 版本,虽然和 maven 有紧耦合,简化以及清
晰了 rules 的使用和动态升级,例如:系统建立 2 个项目:一个 Drools 项目来实
现规则,验收规则,生成 jar 包,另外一个就是真正要用规则的项目,直接通过
引入不同版本的 jar 包实现规则动态升级。
引入业务规则技术的目的
对系统的使用人员
• 把业务策略(规则)的创建、修改和维护的权利交给业务经理
• 提高业务灵活性
• 加强业务处理的透明度,业务规则可以被管理
• 减少对 IT 人员的依赖程度
• 避免将来升级的风险
对 IT 开发人员
• 简化系统架构,优化应用
• 提高系统的可维护性和维护成本
• 方便系统的整合
• 减少编写“硬代码”业务规则的成本和风险
这里引用了一位 Drools 大咖的博客文章
http://blog.csdn.net/lifetragedy/article/details/51143914
如果大咖看到了,请谅解。小编在这里先谢谢您啦 MK 大神!
应用场景
• 为提高效率,管理流程必须自动化,尽管现代商业规则异常复杂。
• 市场要求业务规则经常变化,系统必须依据业务规则的变化快速、
低成本的更新。
• 为了快速、低成本的更新,业务人员应能直接管系统中的规则,不
需要程序开发人员参与。
作用与优点:
• 将业务规则与业务系统分离,解耦合;
• 实现自然语言描述规则逻辑,业务人员易于理解;
• 可视化的规则定制、审批、查询及管理;
• 能有效的提高实现复杂逻辑的代码的可维护性;
• 应付特殊状况,即客户一开始没有提到要将业务逻辑考虑在内;
• 符合组织对敏捷或迭代开发过程的使用;
如下如所示:
(图:1-2)
Drools 的基本工作过程
之前我们一般的做法都是使用一个接口进行业务的工作,首先要传进去参数,其次要获
取到接口的实现执行完毕后的结果。其实 Drools 也大相径庭,我们需要传递进去数据,用
于规则的检查,调用外部接口,同时还可能需要获取到规则执行完毕后得到的结果。
在 drools 中,这个传递数据进去的对象,术语叫 Fact 对象。Fact 对象是一个普通的 java
bean(小编是这样理解的),规则中可以对当前对象进行任何的读写操作,调用该对象提供的
方法,当一个 java bean 插入到 working Memory(内存储存)中,规则使用的是原有对象的
引用,规则通过对 fact 对象的读写,实现对应用数据的读写,对于其中的属性,需要提供
getter setter 访问器,规则中,可以动态的往当前 working Memory 中插入删除新的 fact 对象。
注:何为 fact 对象 下面只是小编对 fact 对象的一些理解和认知,有说的不对的地方还请指点
Fact 对象
Fact 是指在 Drools 规则应用当中,将一个普通的 JavaBean 插入到规则的 WorkingMemory 当中后的对象。规则可以对 Fact
对象进行任意的读写操作,当一个 JavaBean 插入到 WorkingMemory 当中变成 Fact 之后,Fact 对象不是对原来的 JavaBean
对象进行 Clon(克隆),而是原来 JavaBean 对象的引用。
规则进行计算的时候需要用到应用系统当中的数据,这些数据设置在 Fact 对象当中,然后将其插入到规则的 WorkingMemory
当中,一个 Fact 对象通常是一个具有 getter 和 setter 方法的 POJO 对象,通过 getter 和 setter 方法可以方便的对 Fact 对象 f
进行操作,所以我们可以简单的把 Fact 对象理解为规则与应用系统数据交互的桥梁或通道。
当 Fact 对象插入到 WorkingMemory 当中后,会与当前 WorkingMemory 当中所有的规则进行匹配,同时返回一个 FactHandler
对象。FactHandler 对象是插入到 WorkingMemory 当中 Fact 对象的引用句柄,通过 FactHandler 对象可以实现对对应的 Fact
对象通过 API 进行删除及修改等操作。
Drools 文件多变的扩展名
说了这么多,这规则引擎是个什么文件呢,也是*.java *.class *.js 之类的?当然不是,
规则引擎可以分为多种方式,最原始也是最基本的是*.drl 文件,当然也可以是*.xml 的方式,
还可以是*.xls or *.xlsx 的方式;看着就很灵活是吧。
Drools Hello world
在上面的文章里,我们对 Drools 有一个简单的认识,在这里章节里,小编对详
细的对 Drools 语法进行一个说明:
在小编看来 Drools 的基础语法可分为三块内容,包路径、引用、规则体;一个
最简单的规则至少要包含“包路径”,”规则体“这两部分。下面我们就写一个
hello world。
上面的例子是最简单的一个规则,只要触发该规则时,就会在控制空 输出 hello
world,那么这几个都代表的是什么意思呢,说的这三大块内容以是什么呢,小
编这里给大家分析一下上面的例子,
首先:规则文件及扩展名,hello.drl 规则名是可以随便起的,不要求像 java
首字母大写,这里小编要提示一下读者,规则名起名最好还是规范,见名知意。
hello.drl’
package rules.testwrod
rule “test001”
System.out.println(“hello world”);
end
when
then
eval(true);
Drl 文件内容:
package 这就是三大块中的包路径,这里的路径是逻辑路径,理论上是可以随便写的,但不
能不写。但为了更方便的开发,这里小编提醒大家最好与文件目录同名,像 java 一下以点
(.)的方式隔开
rule 就是三大块中的规则体,以 rule 开头,以 end 结尾,每个规则文件可以包含多个 rule。
规则体分为三个部分,LHS RHS 属性 三大部分,下面小编会对这三个部分做一个简单的说
明,在语法详情的篇章里,会有说明的。
LHS:条件部分又被称之为 Left Hand Side,简称为 LHS,在一个规则当中 when 与 then 中
间的部分就是 LHS 部分。在 LHS 当中,可以包含 0~n 个条件,如果 LHS 部分没空的话,
那么引擎会自动添加一个 eval(true)的条件,由于该条件总是返回 true,所以 LHS 为空的规
则总是返回 true。
也就是这样的效果
hello.drl’
package rules.testwrod
rule “test001”
System.out.println(“hello world”);
end
//这里如果为空 则表示 eval(true);
when
then
RHS:结果部分又被称之为 Right Hand Side,简称为 RHS,在一个规则当中 then 后面部分
就是 RHS,只有在 LHS 的所有条件都满足时 RHS 部分才会执行。
RHS 部分是规则真正要做事情的部分,可以将因条件满足而要触发的动作写在该部分当
中,在 RHS 当中可以使用 LHS 部分当中定义的绑定变量名、设置的全局变量、或者是直接
编写 Java 代码(对于要用到的 Java 类,需要在规则文件当中用 import 将类导入后方能
使用,这点和 Java 文件的编写规则相同)。
我们知道,在规则当中 LHS 就是用来放置条件的,所以在 RHS 当中虽然可以直接编写
Java 代码,但不建议在代码当中有条件判断,如果需要条件判断,那么请重新考虑将其放
在 LHS 当中,否则就违背了使用规则的初衷。
在 Drools 当中,在 RHS 里面,提供了一些对当前 Working Memory 实现快速操作的宏
函数或对象,比如 insert/insertLogical、update/modify 和 retract 就可以实现对当前 Working
Memory 中的 Fact 对象进行新增、修改或者是删除;如果您觉得还要使用 Drools 当中提
供的其它方法,那么您还可以使用另一外宏对象 drools,通过该对象可以使用更多的操作当
前 Working Memory 的方法;同时 Drools 还提供了一个名为 kcontext 的宏对象,使我们可
以通过该对象直接访问当前 Working Memory 的 KnowledgeRuntime。
这里我们有提到了 import,这是一个什么概念呢,其实很简单,就是引入所需要的 Java 类
或方法。import:导入规则文件需要使用到的外部变量,这里的使用方法跟 java 相同,但是
不同于 java 的是,这里的 import 导入的不仅仅可以是一个类,也可以是这个类中的某一个
可访问的静态方法。小编这里要提醒一下读者,在规则文件里 package 永远是第一行
比如:
import com.drools.demo.point.PointDomain; 导入类
import function com.drools.demo.point.PointDomain.getById; 导入静态方法
例如下面代码:
hello.drl
package rules.testwrod
import cn.test.Person;
when
rule “test001”
$p:Person();
end
then
ntln(“hello ”+$p.getName());
Drools 的 API 调用
在上一章节里,小编简单的讲述了规则文件的编辑语法与规范,读者还没有看过 rule
的执行过程,下面我们就通过例子对 rule 进行一下调用。在 Drools 当中,规则的编译与运
行要通过 Drools 提供的各种 API 来实现,这些 API 总体来讲可以分为三类:规则编译、规则
收集和规则的执行。
在调用时,我们先要做以下几个操作:
1、Kmodule.xml 的编辑
kmodule.xml 文件放到 src/main/resources/META-INF/文件夹下
代码的实现(具体内容)
(图 2-1)
分析上面代码:
1) 一个 kmodule 里面可包含多 kbase,这个也是我们这个例子里面的用例对应 drl 规则文
件的例子,每一个 kbase 都有一个 name,可以取任意字符串,但是不能重名。
2) 然后有一个 packages,可以看到 packages 里面的字符串其实就是 src/main/resources
下面的文件夹的名称,或者叫包名,规则引擎会根据这里定义的包来查找规则定义文件。
可以同时定义多个包,以逗号分隔开来就行。每一个 kbase 下面可以包含多个 ksession,
当然本例中都自定义了一个。注:packages 是以小数点进行分离的,与 java 中 package
是一样的,指的是物理路径,packages 只能指到该值的路径,是不能递归子文件夹的,
这一点读者要谨记。
3) 每一个 ksession 都有一个 name,名字也可以是任意字符串,但是也不能重复。kbase
和 ksession 里面的 name 属性是全局不能重复的。kbase 和 ksession 中其实还有很多
其它的属性,每一个 kbase 下面可以包含多个 ksession。
4) 在运行时,KieContainer 会根据*Model 对象来创建 KieModule、KieBase、KieSession
对象。其中 KieModule 和 KieBase 只会创建一次,而 KieSession 则有可能创建多次,
因为 KieSession 的创建成本很低,同时 KieSession 包含了运行时的数据,所以可以销
毁、创建若干次。
2、API 的说明,创建一个 java 文件
在写 java 文件之前我们先要引用 drools 相关的 jar 包,小编再次说明一下,以下的例子都
是 drools6.4 版本
Mavne pom.xml
4.0.0
com.drools.modules.test
drools-moudles
1.0-SNAPSHOT
jar
drools-moudles
http://maven.apache.org
UTF-8
6.4.0.Final
4.2.6.RELEASE
2.5
org.drools
drools-core
${drools.version}
org.drools
drools-compiler
${drools.version}
org.drools
drools-decisiontables
${drools.version}
org.drools
drools-workbench-models-guided-template
${drools.version}
org.drools
drools-simulator
${drools.version}
org.jbpm
jbpm-flow-builder
${drools.version}
org.kie
kie-spring
${drools.version}