Drools用户指南
软件程序员当需要实现业务需求的时候经常使用程序式方法。结果导致业务规则的实现只能依赖那些有能力明白业务规则的软件工程师去开发。这种限制是可预见并且被调查证实过。
面向对象可能被看作是解决业务实现的一个解决方法,并且敏捷和许多开发者都是依赖这种方式。最终,面向对象应用以“面条式代码”结束。为了避开这种结果,一个新的应用被提出来叫用“声明式编程”。这个是一个巨大的变化并且 我们在学习Drools之前可以尝试关注一下它
下面章节
1. 第一部分叫做“drools tutorials”从基本内容(这里有很少并且集中在一个核心引擎)更多的语言内容
2. 第二部分叫“BRMS tutorial”将会介绍管理工具(叫做workbench)围绕着规则组件的生命周期。但是这个workbench 也会介绍跟多的组件类型像decision table, rule templates,等等。当你对业务需要建模的时候会会帮助
3. 第三部分叫“BRMS runtime tutorials介绍在一个真实的项目的软件架构。在例子部分,我们将在那一部分讨论使用的办法。
当使用drools工作的时候,这里有一些东西需要你定义的。
1) 在哪一个规则应用数据模型。像我们使用java语言工作一样,一个数据模型就是一组java类
2) 规则其中一个边(叫左边界或者lhs)在数据模型上表达条件,这里类名和他们的属性和其他边(叫右边界或者rhs)将会作用于在工作内存里面的事实(facts)
当你想应用一些规则在一些数据上,你将实例化一个java类并且把它添加到规则引擎。这个实例就是叫做事实对象(fact object)
为了使规则引擎工作,我们需要实例化一个KieContainer (容器)我们迟点将会看到怎样对它进行编程。这个KieContainer 包含了一组规则。KieContainer允许包含其他类型的工件是常用的其他组件如jbpm和optoplanner
当你想通过drools工作,你还需要从KieContainer获取一个KieSession。这个KieSession将允许你给事实到规则引擎,并且调用执行规则
Drools需要java环境版本是7or8 ,orachle java和openjdk都可以
Eclipse有drools的插件使用
下载Drools and jbpm Tools.,解压文件,
--里面有运行环境,droolsjbpm-integration-distribution-6.5.0.Final\binaries
然后在eclipse插件市场搜索drools安装插件
然后按next
选择中间按钮并按一下步
填入FirstProject 作为项目名称,并且选择一个"Add a sample Helloworld rule file to this project"
项目目录如下:
如果直接运行,运行结果如下
这样我们就成功安装了。
我们首先编写的java代码将会在整个drools教程使用。这里的我们将要使用的模型是我们在一个银行控制帐务和每个帐务动作。目标是在每个帐务期间所有帐务的动作计算帐务平衡
我们在junit 测试所有例子。数据模型就是你可以在drools文档中引用的模型一样
我们像之前描述一样创建一个AccountProject 的drools项目。然后我们应该创建一个java的包我们可以命名droolscours 包在 src/main/java
然后我们将创建3个java类,Account, AccountingPeriod 和CashFlow通过右键在新建的包创建新类
然后在Account类添加两个属性:accountno 和balance。调用source/generate/getter/setter
然后AccountingPeriod类也是一样
CashFlow:
这样三个类都创建好
为了可以使用junit,我们添加junit库
添加Add library按钮选择Junit,然后选择junit4
好了项目可以用junit库了
现在我们创建一些目录。test/java
然后添加一个test/rules 目录
现在选择src/test/java 点击右键作为一个源文件夹test/rules也是一样
为了测试写的简单,我们应该写一些帮助类。我们首先创建一个包名叫util 并且在这里我们创建一个叫KnowledgeSessionHelper 的类
里面的内容如下
在src/test/java创建一个junit Testcase
然后输入droolscours 作为 package名字。FirstTry 作为Name
然后点击完成。然后输入代码
右键执行 JUnit Test
现在我们可以开始课程了
在上一节我们创建了项目,我们想继续添加一个新的drl文件(drools rule language)。选择
src/test/rules 并且首先创建一个名叫lesson1的包,并且创建一个规则文件叫“lesson1”
然我们分析规则元素
1. 对于我们准备使用所有java对象,我们需要加载这些类
2. 也有可能定义全局变量
3. 唯一的规则名称
4. 规则条件又是叫做LHS=左手边就是在RETE算法左边
5. 规则动作就是当规则条件满足的时候做什么。可能使用纯粹的java代码,这就是作为右手边(RHS)
作为eclipse的插件,drools插件允许自动完成(ctrl+space) alt+/ 有提示
我们创建一个规则,有一个条件就是一个个Account类型的事实。如果规则执行,我们会在控制台显示消息“The account exists”。注意他们都是纯的java代码
然后我们创建一个"testLesson1" junit 测试
然后添加代码如下
并且在src/main/resources/META-INF 修改 kmodule.xml
这里我们定义了一个session 名字叫“ksession-rules”并且我们在哪里找到规则文件在“lesson1”包,现在你可执行TestLesson1 你可以看到如下
这个消息就是我们在fist rule 的打印出来的
让我们添加一些日志到facilate 输出
在我们刚刚做的代码里,我们写一段System.out.println("blabla"). 代码。这是可行的但是想象你想记录其他,就不可能了。一个好的练习为了这个目的我们使用全局变量。
首先我们定义一个java类叫OutputDisplay 我们会在src/main/java/util里面创建
现在我们可以更新一下lesson1.drl 文件
Global关键字是使用了并且一个常规的java定义。这里的global 的类型是OutputDisplay并且变量名称叫showResults
现在这个变量可以被规则里面任何地方使用了。为了初始化这个全局变量,我们需要在session使用setGlobal方法,如下
当运行test的时候,打印如下
我们只是定义仅仅一个规则。它运行或者不并且如果yes我们添加了一个方法向我们展示一些信息如果规则被执行了。在一些大项目,添加日志代码在每一个规则里面不是一个好的实践并且 会增加写规则的复杂性和更多的是我们推动使用drools成为一个为了业务分析的业务工具和他们需要写技术代码。Drools 提供了一个匹配规则去实现调用session回调的功能
Drools 可以被看作一个下面的图片
在production memory 包含了所有的规则定义(在我们的例子中drl)。
working memory创建session和我们可以通过方法添加事实进去。
Agenda 包含了所有可以被执行的规则。
pattern Matcher就是在给定事实匹配规则的算法。
在drools最新版本,这里有很多不同算法可以使用(最主要的是rete algorithm)
在每一部分,都有可以添加一个回调当我们创建session的时候
每一次一个事实在插入,更新获取删除的时候我们将会把这个事件记录并且在控制台展示。这里我们使用了java实例给定的toString 方法。你需要添加一些部分进去。
我们将在所有的简单类:Account, AccountingPeriod and CashFlow添加一个toString方法。
然后修改一下lession1
运行一下
你可以添加其他信息在junit测试例子
可以看到每个测试都是先执行setup,结束执行teardowen
首先你必须记住这个事实的处理
FactHandle handlea = sessionStatefull.insert(a);
然后你使用facthandle 去告诉drools就是object已经改变了
a.setBalance(12.0);
sessionStatefull.update(handlea, a);
并且相同的应用当你想回收
sessionStatefull.delete(handlea);
在我们在working memory回去唯一的事实,然后我们调用fireAllRules() ,这个规则是不会执行的,因为事实没有了
让我们看一下下面例子
我们插入Account之后,在一个session重复执行两遍规则。会发生什么事情呢?有多少次这个规则被执行呢?
可以看到规则只是被执行了一次。可能是我们没有修改Account的对象?让我们事实另外一个例子,修改account对象然后传入给Session
规则也是没有执行两遍。只是修改对象并不会执行工作。然我们修改一下例子,告诉drools对象修改:
在调用第二次执行规则之前,我们告诉一下drools,有个对象修改过了。但是对象并没有修改
这个规则被执行了两次。
这里发生了什么当在statefull session 调用 FireAllRules方法
1. drools将会查询所有规则可以应用并且把规则加入到 agenda
2. drools会执行在agenda的第一个条规则
3. 一旦执行,规则就无效了
4. 我们需要告诉drools一个事实改变的状态,使他重新考虑规则
5. 一个状态的改变可以是一个插入,更新或者删除(回收)
在最后一个例子,我们告诉drools就是fact已经被修改了
sessionStatefull.update(handle, a);
因此,考虑插入一个事实被更新之前,drools回反观规则。正如在“"Your First Rule revisited”规则这里在属性没有条件,然后规则被执行
但是我们也可以在规则RHS,插入,更新回收.
在第一个规则,我们创建了一个AccountingPeriod 对象,并且使用关键字insert 告诉drools去创建一个新的事实。因此,第二个规则就会被执行仅当在working memory.里面有一个AccountingPeriod对象
我们看到日志
1. 首两行:就是CashFlow 对象被插入。我们通过junit测试的代码添加
FactHandle handlea = sessionStatefull.insert(a);
2. 第三行:就是执行第一个规则了
3. 第四,五行:一个AccountingPeriod对象被插入。这是由规则代码插入的
AccountingPeriod newPeriod = new AccountingPeriod();
insert (newPeriod);
4. 最后一行就是执行了第二个规则
第一节结束了我们学到了需要用drools工作的核心术语