1、第一章.Drools 4.0发布版标注1.1.Drools 4.0 的新内容Drools4.0是从之前的Drools3.0.x系列以来的一次主要更新。在语言表达式,引擎性能和 工具实用性方面都有一整套的新特性开发完成。下面列出一些最引人注意的更新列表。1.1.1.语言表达式增强 新的条件元素:from,collect,accumulate for all 新的字段约束操作:not matches,not contains,in,not in,memberOf,not memberOf 新的自索引字段:this 对条件元素嵌套的完全支持,对一阶逻辑的完全支持 支持使用&和II连接多个约束条件 语
2、法分析器的增强以去除之前的一些语言约束,如字符转码和关键字冲突 支持插件式语言,以及对MVEL脚本语言的完全支持 完全重写的DSL引擎,允许完全的本地化 Fact属性对于返回值约束和内嵌求值的自动变换 支持嵌套访问,属性导航和简化的集合、数组以及映射的语法 对XML规则的增强支持1.1.2.核心引擎增强 对于元数据类型的本地支持,避免经常性的自动封包操作 支持透明的可选的影子Fact 对于复杂规则的Rete网络性能增强 支持规则流 支持有状态与无状态的Working Memory(规则引擎Session)支持异步Working Memory操作 规则代理(Agent)提供热部署机制和BRMS集
3、成 对于规则冲突解决方案的动态salience值 支持参数化查询 支持暂停命令 支持顺序执行模式支持插件式的全局变量转换器1.1.3.IDE 增强 支持调试中的规则断点 对于规则流的所见即所得功能 对于规则编制的新的向导编辑器 支持所有新的引擎特性1.1.4.业务规则管理系统-BRMS 新的BRMS工具 具有Web2.0 Ajax特性的用户友好的Web界面 Package 配置 通过向导编辑器与文本编辑器,规则的作者更容易修改规则 Package编译和部署 通过使用Rule Agent简化部署 通过分类组织规则,简化规则的查找 可版本化,你可以很容易的使用之前保存的版本替换现在的一套规则 与J
4、CR兼容的规则仓库1.1.5.其它增强减少了依赖类库和更少的内存占用1.2.从 Drool3.0.x 向 Drools4.0.x 更新的提示之前说到,Drools4.0是自Drools3.0.x系列以来的重要关键更新。但不幸的是为了达到这 次发布的目标,带来了一些向后兼容性的问题,如邮件列表和博客中所提到的。本节简单介绍一下如何从Drools3.0.x向Drool4.0.x升级1.2.1.API 变更只有很少的API变更是对于常规用户可见并需要调整的。1.2.1.1.Working Memory 创建Drools3.0.x中只有一种Working Memory类型,它的是以有状态Working
5、 Memory的方式工 作的。Drool4.0.x提供两个独立的有状态与无状态working memory,现在被称为Rule Sessiono 在 Drools3.0.x 中建立 Working Memory 的代码是:Example 1.1.Drools 3.0.x:Working Memory 仓1J建WorkingMemory wm=rulebase.newWorkingMemory();在Drools 4.0.x中必须变成:Example 1.2.Drools 4.0.x:有状态 Rule Session 仓建StatefulSession wm=rulebase.newStatef
6、ulSession();StatefulSession对象与Drools3.0.x中的WorkingMemory对象的行为相同(它甚至继承了WorkingMemory接口),因此除了创建代码以外这个调整不会带来其它问题。1.2.1.2.Working Memory 操作Drools 4.0.x支持可插入的语言,并且已经内建了对Java和MVEL脚本语言的支持。为了 避免关键字冲突,working memcny的一些操作被重新命名如下:Table 1.1.Working Memory Actions equivalent API methodsDrools 3.0.xDrools 4.0.xWo
7、rkingMemory.assertObject()WorkingMemory.assertLogicalObject()WorkingMemory.modifyObject()WorkingMemory.insert()WorkingMemory.insertLogical()WorkingMemory.update()1.2.2.规则语言的变更DRL规则语言也有如下一些变更是不支持向后兼容性的。1.2.2.1.Working Memory ActionsWorking Memory操作在规则推论中的变化和在方法API上的变化相似,下表描述了这些改 变:Table 1.2.Working M
8、emory Actions equivalent DRL commandsDrools 3.0.xDrools 4.0.xassert()insert()assertLogical()insertLogical()modify()update()1.2.2.2,元数据类型支持与解包(unboxing)Drools 3.0.x没有对元数据类型的本地支持,因此它会自动封包所有的元数据类型到各自 的封装类中。这样的化,任何封包的变量绑定需要一个手工的解包操作。Drools 4.0.x已经对元数据类型有完全的支持,不再需要封装任何值。因此所有之前的解 包操作必须从DRL中删除。Example 1.3.
9、Drools 3.0.x 手工解包rule Primitive int manual unbox”when$c:Cheese($price:price)then$c.setPrice($price.intValue()*2)end上面的规则在4.0.x中将是:Example 1.4.Drools 4.0.x 元数据支持rule Primitive support”when$c:Cheese($price:price)then$c.setPrice($price*2)end1.2.3.Drools更新工具Drools更新工具是一个帮助你将DRL从3.0.x升级到4.0.x的一个简单的程序。在这一
10、点上它主要是更新working memory从3.0.x到4.0.x的操作调用,但是期待它在未 来的几个星期里可以覆盖更多的情况。要注意的是,这个工具并不是简单的进行字符替换,实际上它分析规则文件并确保不会做出预料之外的任何事情。因此它对于大量规则的升级来 说是一个安全的工具。Drools更新工具可以在下面的源码库链接中作为一个maven项目获取http:/anonsvn.labs, Out它,然后与项目的pom.xml文件一起执行maven clean install操作。在解决了所有依赖类库的class路径后,你可以使用下面的命令运行这个工具:java-cp$CLASSPATH org.d
11、rools,tools,update.UpdateTool-f -d -s 这个程序的参数非常容易理解:-h,-help,显示一个非常简单的帮助-d你的源码根路径-f将要被更新的文件的查找模式。这个格式与ANT中使用的相同,*二单个文件,目录*=任何子目录级别;例如src/main/resources/*/*.drl=匹配所有在/src/main/resources下的子目录中的DRL文件-s,suffix被增加到所有更新文件上的后缀第2章.规则引擎2.1.什么是规则引擎?2.1.1.背景介绍A.I.(Artificial Intelligence)是一个关注于“使计算机像人类一样思考”的广泛
12、的研 究领域,包括 Neural Networks(神经网络),Genetic Algorithms(遗传算法),Decision Trees(决策树),Frame Systems(框架系统)and Expert Systems(专家系统)。Knowledge representation(知识呈现)是A.I.的一部分,关注于如何呈现和操纵知识。专家系统使 用知识表示把知识编码简化成一个可用于推理的知识库比如,我们可以用知识库处理数 据以推出结论。专家系统又叫基于知识的系统、基于知识的专家系统,并被认为是A.I.的 一个应用。开发一个专家库系统的过程被称为知识工程。EMYCIN是最早的专家系统
13、Shell(外壳)之一,它从医学诊断专家系统MYCIN发展而来。早期的专家系统有自己的logic hard codedshells(逻辑硬件编码外壳),把逻辑与系统相分离,为用户输入提供一个简单的 使用环境。Drools是一个使用基于规则的方法实现的专家系统的规则引擎,更准确的说属 于产生式规则系统。术语“产生式规则”从形式语法中产生,形式语法使用一种抽象结构来准确描述形式语 言(wikipedia)。The term Production Rule originates from formal grammar-where it is described as an abstract stru
14、cture that describes a formal language precisely,i.e.,a set of rules that mathematically delineates a(usually infinite)set of finite-length strings over a(usually finite)alphabet/z(wikipedia).业务规则管理系统在普通的规则引擎基础上通过提供一集中的业务用户,规则建立系统,管 理,发布,协作,分析和终端用户工具等来达到更高的附加价值;使得企业能够以更顺利的 方式引入规则引擎规则引擎这个术语是非常不明确的,因为
15、任何以任意形式使用能够应用于数据生成结果的规 则的系统都可以称为规则引擎。包括像表单验证和动态表达式引擎这样的简单系统都可以称 之为规则引擎。作者 Malcolm Chisholm 的著作How to Build a Business Rules Engine(2004)就例证了这种不明确性。该书实际是讲述如何为管理校验规则而建立和维护一个数 据库计划。该书中接着展示了如何根据这些校验规则产生VB代码来校验输入一在某些情况 下这是很有用的,作者十分惊讶于这种不明确性,在没有觉察到各种规则引擎间细微不同之 处时,他希望能发现其中的奥秘以帮助增强Drools引擎。JBoss jBPM(业务流程管理
16、工具)在它的判断节点上使用表达式和代理引用来控制工作流中的事务。通过在每个节点上求值以 决定分支的流向一这同样是一个规则引擎。产生式规则系统既是一种规则引擎,又是一个专 家系统,而之前提到的校验器和表达式求值规则引擎不是专家系统产生式规则系统完全关注于精确表达propositional(命题)和first order logic(一阶 逻辑)的知识表示,不存在含糊不清的定义。产生式规则系统的核心是一个能够处理大量规 则和事实的推理引擎。推理引擎将事实、数据与产生式规则(也可以叫做产生式,或干脆叫 规则)进行匹配,以推出结论。产生式规则是一个用一阶逻辑进行知识呈现的二元结构。whenthen将新
17、的或已存在的事实与产生式规则进行匹配的过程被称为模式匹配,这个过程由推理机完 成。推理机使用的用于模式匹配的算法有很多,包括:Linear线性的 Rete 网状 Treat Leaps 叶状Drool实现了 Rete和Leaps算法;Leaps是试验性质的,因为它是个十分新的算法。Drools 中的Rete算法被称为ReteOO,表示Drools为面向对象系统(Object Oriented systems)增强并优化了 Rete算法。其它基于Rete算法的引擎也有他们对Rete算法进行独有增强后 的市场术语,比如RetePlus,Retelllo要知道象RetelH这样的名字纯粹是市场性的,
18、不 像原始版本的Rete算法,它们没有公布实现细节,这一点很重要;因此,问类似于“Drools 是用Retelll实现的吗?”的问题是没有任何意义的。最寻常的对Rete算法的增强在下面 这篇文章中有论述“Prociucticm Matching for Large Learning Systems(Rete/UL)/z(1995)by Robert B.Doorenboso规则保存在Production Memory(规则库)中,推理机要匹配的facts(事实)保存在Working Memory(工作内存)中。事实被插入到工作内存中后,可能被修改或删除。一个有大量规则 和事实的系统可能会很多规
19、则被满足,这些规则被称为具有冲突性。Agenda通过(冲突决 策策略)管理这些冲突规则的执行顺序。Figure 2.1.基础 Rete 网络产生式规则系统的推理机是有状态的并且能够维持其中状态值的准确性,称为Truth Maintence(真值维护)。规则引擎中的动作仅当其依赖的约束为真值情况下执行,如果约 束不再有效,则推论动作不会执行。Honest Politician”(Drools提供的一个示例)就是 这种真值维护的示范,在示例中规定,只要在存在诚实的政治家时,一个政体才有希望。whenan honest Politician existsthenlogically assert Ho
20、pewhenHope existsthenprint Hurrah!Democracy Lives”whenHope does not existthenprint Democracy is Doomed”产生式规则系统有两种执行方法正向推理和逆向推理,两种方法都使用的系统称为混合 型产生式规则系统。理解这两种操作方法是理解产生式规则系统之所以不同和怎样从中选择 最合适的系统的关键。正向推理是数据驱动的,facts事实被传递到工作空间中,在那里有 一个或多个规则与这些事实匹配,并由Agenda安排执行一我们从一个事实开始,传递事实,最后得到一个结论。Drools是基于正向推理的规则引擎。No
21、Rule FoundIExit If specified by rulaFigure 2.2.正向推理逆向推理是由目标驱动的,这意味着我们从一个引擎需要满足的结论开始进行推理。在这个 结论不能满足时,将搜索一些能够满足的结论来推理,称为子目标,这些子目标将帮助完成 当前目标的某些未知部分一一引擎持续这个过程,直到最初的结论被证明或没有可证明的子 目标。Prolog是逆向驱动型的引擎。Drools将在下一个主要版本中加入对逆向推理的支持。-、Examine working memory and goals to see if goals are known”true in knowledge b
22、aseWorking Memory-e 0 6 e s-6-np e j f o u o三2。看山 ufflq士。e qf AFor each rule condition,recursively backchain with condition as goal.Fire RiNo Rule FoundAll recursionreturns true?One or more goals failed,Check next matching rule-Goals found to be true,exist returning true-Figure 2.3.逆向推理2.2.为何使用规则引擎?
23、人们常常会问到:1.何时应当使用规则引擎?2.规则引擎与if.then这样的硬编码比起来有什么优点?3.为何应当使用规则引擎取代脚本框架?我们尝试通过以下说明来解答这些问题2.2.1.规则引擎的优点 声明式编程规则引擎允许你描述做什么而不是如何去做。这里的主要优点是使用规则更加容易对复杂的问题进行表述,并得到验证。(规则 比编码更容易阅读).规则系统能够解决非常非常困难的问题,并提供了方案怎样达到和在解决问题的方 向上所作的每一个决定的原因(这对于类似神经网络这样的AI系统来说不容易达 到)逻辑与数据分离数据保存在系统对象中,逻辑保存在规则中。这根本性的打破了面向对象系统中将 数据和逻辑耦合起
24、来的局面,这点是有利的也是不利的,在于你的观察角度。这样 做的结果是,将来逻辑发生改变时更容易被维护,因为逻辑保存在规则中。这点在 逻辑是跨领域或多领域中使用时尤其有用。通过将逻辑集中在一个或数个清晰的规 则文件中,取代了之前分散在代码中的局面。速度及可测量性Rete算法、Leaps算法,以及由此衍生出来的Drools的Rete、Leaps算法,提供了 对系统数据对象非常有效率的匹配。这些都是高效率尤其当你的数据是不完全的改 变(规则引擎能够记得之前的匹配)。这些算法经过了大量实际考验的证明。知识集中化通过使用规则,将建立一个可执行的规则库。这意味着规则库代表着现实中的业务 策略的唯一对应,理
25、想情况下可读性高的规则还可以被当作文档使用。工具集成例如Eclipse(将来可能在基于Web的界面上)这样的工具为规则的修改与管理、即时获得反馈、内容验证与修补提供了办法。审查与调试工具同样也可用了。解释机制通过将规则引擎的决断与决断的原因一起记录下来,规则系统提供了很好的“解释 机制”。易懂的规则通过建立对象模型以及DSL(域定义语言),你可以用接近自然语言的方式来编写 规则。这让非技术人员与领域专家可以用他们自己的逻辑来理解规则(因为程序的 迷宫已经被隐藏起来了)。2.2.2.何时应当使用规则引擎?对这个问题最简短的回答就是“当没有令人满意的传统的程序设计方法能够解决这个问题 时”。下面上
26、对所谓没有传统解决方法的一个描述:对于传统代码来说,问题需要的精确度太高。这种问题可能并不复杂,但是你找不到一种稳定的方法去建立它。问题超越了任何有明显运算法则的方案。它是一个难以解决的复杂问题,没有明显的传统解决方案或者问题没有一个准确的 定论。业务逻辑经常发生改变逻辑本身是简单的(但不是指过于简单),但是规则经常发生变化。在许多软件组 织中正式版本的间隔是较长并且较少的,规则可以在适当的安全前提下帮助提供一 定的敏捷性。领域专家(或者业务分析师)是非技术人员领域专家通常对业务规则和流程具有很好的认知。他们通常是不了解软件技术的人 员,但是具有很好的逻辑性。规则能够让他们用自己的术语来描述业
27、务逻辑。当然 他们仍然需要严密的思考和良好的逻辑思维能力(许多在非软件技术型岗位上的人 没有进行过形式逻辑的训练,因此在和他们工作时要特别小心,在将业务知识编撰 成规则时,要特别注意业务规则和流程应当是当前能够理解的)。如果规则对于你的项目组来说是一种新的技术,那在使用前必须将学习与管理的费用成本考 虑进去。规则不是一种无意义的技术,这篇文档尽量让其易于理解。在一个面向对象的应用中,规则引擎通常被用在包含业务逻辑的关键部分(具体与应用相 关),特别是在十分繁杂凌乱的部分。这是对面向对象中将所有逻辑封装在对象中的一个倒 置。但这并不是说应该抛弃对象模型,相反的来说在任何一个现实应用中业务逻辑仅仅
28、是应 用的一部分。如果你曾注意到在你的代码中有很多 if else”switch”和其它凌乱的 逻辑,你总是要回过头去修改它们(可能是由于提供给你的逻辑是错误的,或是你的理解变 化了),那么可以考虑使用规则。如果你所面对的问题没有算法或者模式合适解决,考虑使 用规则。规则可以被嵌入你的应用中,或者作为一个服务使用。通常规则最好被当作一个有状态的组 件使用一一因此它们通常在应用中是一个整体。无论怎样,在一些规则被成功定义为可重用 的服务的个案中,规则是无状态的。如果考虑在组织中使用规则,那考虑产品中将如何使用和更新规则是很重要的(选择很多,但是不同的组织间有不同的需要通常这超出了应用者/项目团队
29、的控制)。2.2.3.何时不要使用规则这里引用Drools邮件发送清单中的话(DaveHamu):“在我看来,在使用规则引擎的兴奋 中,人们忘记了规则引擎只是一个复杂的应用或方法中的一部分。实际上,规则引擎不是用 于规则的工作流引擎或进程管理工具。对特定的工作要使用恰当的工具。当然,必要时老虎 钳可以当作锤子用,但那并不是发明老虎钳的本意。”因为规则引擎是动态的(动态的在这里意味着规则可以象数据一样保存、管理和更新),它们 通常被看作发布软件系统的一种解决方案(大多数IT部门似乎存在的目的是防止软件系统 被遗弃)。如果这是你希望使用规则引擎的原因,应当意识到在可以写出公开发布的规则时,规则引擎
30、能够以最佳方式工作。做为另一个方面,你也可以考虑使用数据驱动的设计(查找 表)或者脚本/流程引擎带有能够在数据库中管理并能够动态更新的脚本。2.2.4.脚本或流程引擎希望之前的讨论能够让你明白何时应该使用一个规则引擎。另一方面,基于脚本的引擎也提供了动态重组的能力。另外流程引擎(通常为工作流)如jBPM允许你使用绘图(或编程)方式描述过程的步骤 这些步骤也能够带有包含简单规则的策略决策点。过程引擎与规则通常能够很好的在一起工 作,因此这不是一个二选一的要求。对于规则引擎的一个关键点是一些规则引擎实际上就是脚本引擎。在脚本引擎下是你的程序 被牢牢绑定在脚本上(如果那里有规则,则必须直接调用),这
31、导致未来维护更加困难,因 为它们趋向于越来越复杂。在脚本引擎之上的好处是能够很容易的开始实现规则并迅速获得 反馈(概念上会使得命令式编程更简单)许多人在过去已经成功实现了数据驱动的系统(通过控制表中保存的元数据来影响应用的行 为)一一保持在一定控制范围内时这能够很好的工作。但是当超过了允许范围(如只有建立 者能够改变应用的行为)太多这将很快失控或者导致应用停滞不前。2.2.5.紧密耦合与松散耦合无疑在系统设计中你听说过紧密耦合与松散耦合。通常人们认为在设计中松散耦合是更好 的,因为增加了系统灵活性。同样你可以有紧密耦合与松散耦合两种规则。紧密耦合在这里 意味着一个规则的执行后将导致另一个规则有
32、一个明显的结果,换句话说就是在规则之间有 清晰的逻辑推理关系。如果你的规则都是紧密耦合的,那这些规则在将来会缺乏灵活性,并 且更明显,这样规则引擎可能是使用过度了(因为逻辑是一组清晰的规则推理能够被直 接编码一个决策树可能更适宜)。这并不是说紧密耦合或松散耦合本质就不好,但是在你 考虑使用规则引擎并且捕捉规则时应当牢记这点。松散耦合使得系统中的规则在变更,删除 和新增时不会影响其它无关的规则。2.3.知识表征2.3.1.一阶逻辑规则是由一阶逻辑或断言逻辑编写而成,是由命题逻辑扩展而来。Emil Leon Post(数学家 与逻辑学家1897-1954)是第一个制定了利用符号来表示逻辑的推理系统
33、作为一个推 论,他证明了任何逻辑系统(包括数学)能够被这样的一个符号系统来表达。一个命题就是一项能够被归纳为True或Flase的一个声明。如果事实能够被一个独立的声 明证明就称之为“封闭声明”。在程序中这表现为一个不含任何变量的表达式:10=2*5包含了一个或多个变量或Fact的表达式称为“开放声明”,在这种表达式中,只有当一个 变量的实例被放入表达式后,才能知道该表达式是否为真值:Person,sex=male在SQL语句中,一条语句的执行结果通常是将匹配的结果返回:select*from People where People,sex=male所有由以上SQL返回回来的数据都会推论为是男
34、性的数据,下图显示SQL如何作为一个推理 引擎从People表中返回我们需要的结果。ResultsFigure 2.4.SQL作为一个单纯的推理引擎因此在Java中,我们可以认为一个简单命题的形式是“变量”“运算符”“值”在这里 值通常代表一个字符串命题可以看作是一个字段约束。命题之间可以使用“&”或,|”进行逻辑合并。如下例:person.getEyeColor().equals(blue)|person.getEyeColor().equals(green)这在规则引擎中也可以用“II”逻辑运算符来表示。Person(eyeColour=blue)|Person(eyeColor=gree
35、n)II”逻辑运算也可以直接作用于字段约束上(Drools4.0M2实现该功能)Person(eyeColour=blue|green)命题逻辑并不能表达数据结构的标准(不具有图灵完备性),这约束了其可以定义的问题。一 阶逻辑或断言逻辑通过两种新的量词概念以允许表达式定义结构具体来说是全称量词 和存在量词,从而扩展了命题逻辑。全称量词允许对每一个对象检查某些情况是否为真,通 常使用“forall”这个条件元来支持(在Drools4.0M2中实现)。存在量词检查对象的存在 性,这意味着该对象至少要出现一次一一由“not”和“exist”这两个条件元支持。设想我们定义了两个类Student和Mod
36、uleo Module代表了一个学生在每个学期里要上 的所有课程,通过List集合引用。在学期末,每个课程有一个得分。如果某个学生的所有 课程中有一门低于40分代表该学生本学期不合格通过存在量词可以使用“less then 40”这样的开放命题来检查各Module中是否有符合该条件的情况。public class Student private String name;private List modules;public class Module private String name;private String studentName;private int score;Java具有图灵
37、完备性,因此你可以通过编写代码遍历数据结构来检查存在性。下面的代码 用来返回所有学期不合格的学生列表。List failedStudents=new ArrayList();for(Iterator studentlter=students,iterator();studentlter.hasNext()Student student=(Student)studentlter.next();for(Iterator it=student.getModules.iterator();it.hasNext();)Module module=(Module)it.next();if(module.g
38、etScoreO 40)failedStudents.add(student);break;早期的SQL实现不是图灵完备的,因此不能提供对所存取的数据结构的量化性。目前的SQL 引擎通过对嵌套SQL语句进行“exist”和“in”的关键字构造来支持存在性。以下代码显 示如何通过SQL和规则来获取学期不合格的学生。select*fromStudents swhere exists(select*fromModules mwherem.student name=s.name andm.score 40)rule/zFailed_Students/zwhenexists($student:Stude
39、nt()&Module(student=$student,score Left Input AdapteNode 和 BetaNode 节点传播数据。AlphaNode节点用来对字符串进行求值。虽然在1982年的论文中只提到了等式操作,但许 多Rete算法的实现支持其它操作。例如,Account.name=Mr Trout”是一个字符串等式。当规则对一个对象类型有很多字符串等式时,它们会链接在一起。这意味着如果应用设置了 一个Account对象,它必须满足了一个字符串等式后才能传递到下一个AlphaNode节点。在 Forgy博士的论文中,他称之为内在条件。下面显示了针对Cheese对象的结合
40、AlphaNode 节点情况:Cheese(name=cheddar,strength=strong):Cheesename=Cheddarstrength=strongFigure 2.7.AlphaNodesDrools通过在Ob jectTypdeNode节点向AlphaNode节点传递时使用Hash操作优化了 Rete 算法。每次一个AlphaNode节点被加入到Ob jectTypdeNode节点时,将在HashMap中增加 一个以字符串为键,AlphaNode节点为值的键值对。当一个新的对象实例进入 ObjectTypdeNode节点时,它可以直接从HashMap中返回正确的Alp
41、haNode节点,避免了多 余的字符串检查。有两种 two-input 节点-Jo inNode 和 NotNode,都是 BetaNode 的类型。BetaNode 节点用于比较两个对象和它们的字段。两个对象可能是相同或不同的类型。我们将这两个输入称为 左和右。BetaNode的左输入通常是一组对象的列表,在Drools中称为语义(Tuple)0右 边的输入是单个的对象。这两者能够使用“exist”进行对比检查。BetaNode具有记忆功能。左边的输入被称为Beta Memory,会记住所有到达过的语义。右边的输入成为Alpha Memory,会记住所有到达过的对象。Drools通过在Bet
42、aNode节点上建立索引扩展了 Rete算法。例 如,如果我们知道一个BetaNode用来对一个字符型字段进行检查,对每一个进入的对象,我们能够使用那个字符串的值进行一个Hash查找。这意味着当Fact从相反的一边进入 BetaNode时,不需要再对所有Fact进行检索以发现有效链接,只要一个查找就可以返回潜 在的有效候选。在任何时候,一个有效的链接是发现语义与对象的链接,它指的是一个局部 匹配,并传播到下一个节点。PersonCheeseFigure 2.8.JoinNode为了让最初的对象,在上图中是Cheese,进入Rete网络,我们使用了一个 LeftlnputNodeAdapter-
43、将一个对象作为输入并传播一个对象的语义。终端节点被用来表示一个单独的规则已经匹配了它的所有条件在这一点上,我们说这个 规则实现完全的匹配。一个使用链接符的规则在每一个可能的逻辑路径上产生子规则,在这种情况下可以有多个终端节点。Drools使用了节点共享技术。许多规则重复着同样的模式,节点共享允许我们删除这些模 式的多余复制,从而避免对每一个单独得实例进行重复的评估。下面两个规则在一开始共享 了相同的模式,但后面部分不同:rulewhenCheese($chedddar:name=cheddar)$person:Person(favouriteCheese=$cheddar)thenSystem
44、out.printin($person.getName()+likes cheddar/z);endrulewhenCheese($chedddar:name=cheddar)$person:Person(favouriteCheese!=$cheddar)thenSystem,out.printin($person.getName()+does not like cheddar/z);end你可以在下图看到,在编译的Rete网络中Alpha节点被共享了,但是Beta节点没有共享。每一个Beta节点有自己的终端节点。如果第二个模式是相同的也会被共享。Personname=CheddarSys
45、tem.out.println(person.getName()+M likes Cheddar*)Person.favounteCheeseCheese.namePerson.favouriteCheese!=Cheese.nameSystem.out.println(person.getName()+”does not like Cheddar*)Figure 2.9.Node Sharing2.5.Drools规则引擎2.5.1.概述Drools被分为两个主要的部分:编制和运行时编制的过程包括为规则建立DRL或XML文件,传入一个由Antlr 3文法器定义的解析器中。下面的翻译要参考图L
46、 10理解解析器对文件中规则文法的正确性进行检查并为descr建 立一个中间结构,在AST中的descr代表规则的描述。AST然后将descr传入Package Builder 中,由其进行打包。Package Builder同时负责包括打包中用到的所有代码产生器和编译器。Package对象是自包含并可配置的,它是一个包含规则的序列化的对象。ParserV(descr)Intermediate ASTFigure 2.10.编制组件RuleBase是运行时组件,包含一个或多个Package。Package在任何时候都可以向RuleBase 中添加或删除。一个RuleBase可以同时初始化多个W
47、orking Memory,在其间维护着一个弱引用,除非重新 进行配置。Working Memory包含许多子组件,如Working Memory Event Support(事件支持),Truth Maintenance System(真值维护系统),Agenda 和 Agenda Event Support(事件支持)。向Working Memory中设置对象的工作可能要在建立了一个或多个激活的规则后才结束。Agenda负有规划激活规则运行的责任。2.5.2.编制org.drools.rule.builderRuleBuilder pilerDialect vPackageBuilderC
48、onfiguration vProcessBuilder vorg.drools.baseClassFieldExtractorCache vTypeResolver pilerPackageBuilder+PackageBuilderO+PackageBuilder(PackageBuilderConfiguration)+PackageBuilder(Package)+PackageBuilder(Package,PackageBuilderConfiguration)+addPackage(PackageDescr):void+addPackageFromDrl(Reader):void
49、addPackageFromDrl(Reader,Reader):void+addPackageFromXml(Reader):void-+addRuleFlow(Reader):void+getClassFieldExtractorCacheO:ClassFieldExtractorCache+getErrorsO:PackageBuilderErrors+getPackageO:Package+getPackageBuilderConfigurationO:PackageBuilderConfiguration-+getTypeResolverO:TypeResolver+hasErr
50、orsO:boolean#resetErrorsQ:pilera PackageBuilderErrorsorg.drools.lang.descrA PackageDescrjava.ioA Reader1java.utilList vFigure 2.12.PackageBuilderDrlParser,XmlParser和PackageBuilder这三个类被用来进行编制。两个分析类用来从 提供的可读流实例中建立descr AST模型。PackageBuilder提供相应API使得你可以不用 记住这些类。addPackageFromDrl和addPackageFromXml”是两个常用方






