Drools规则引擎用户手册.doc_第1页
Drools规则引擎用户手册.doc_第2页
Drools规则引擎用户手册.doc_第3页
Drools规则引擎用户手册.doc_第4页
Drools规则引擎用户手册.doc_第5页
已阅读5页,还剩205页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Drools规则引擎 目 录 第一章 规则引擎初步了解51 为什么会有规则引擎?52 什么是规则引擎?53 为何要使用规则引擎?63.1 声明式编程63.2逻辑与数据分离63.3 速度及可测量性63.4 知识集中化63.5 工具集成63.6 解释机制63.7易懂的规则74 何时应当使用规则引擎?75 如何使用规则引擎?76 何时不要使用规则引擎 ?87 规则引擎的架构和推理88规则引擎的算法109 Java规则引擎商业产品1010 Dools介绍11第二章.Drools 规则引擎112.1.概述112.2.编制132.3.RuleBase182.4.WorkingMemory 和有状态/无状态Sessions222.5.StatefulSession282.6.StatelessSession292.7.Agenda312.8.Truth Maintenance with Logical Objects342.9.事件模型(Event Model)372.10.顺序模式41第三章.安装和设置(Core 与IDE)423.1.安装和使用423.1.1. 依赖库423.1.2.运行时(Runtime)433.1.3.安装IDE (规则工作台)433.2.从源码进行安装543.3.源码Checkout543.4.构建593.4.1.构建源码593.4.2.构建使用手册613.5.Eclipse653.5.1.产生Eclipse项目653.5.2.导入Eclipse项目663.5.3.导出IDE插件713.5.4.构建更新站点76第四章.决策表784.1. 在电子表格中的决策表784.1.1.何时使用决策表784.1.2.概述794.1.3.决策表如何工作814.1.4.关键字和语法834.1.5.基于决策表建立并集成电子表格874.1.6. 在决策表中管理业务规则88第五章.规则工作台 (IDE)895.1.Introduction895.1.1.特性概要905.1.2.建立规则项目905.1.3.新建规则向导925.1.4.规则编辑器945.1.5.视图955.1.6.领域规范语言DSL985.1.7.The Rete视图1005.1.8.大容量DRL文件1015.1.9.调试规则102第六章.规则语言1036.1.概述1036.1.1. 规则文件1036.1.2.规则的构成1046.1.3.保留字1046.2.Comments注释1066.2.1.单行注释1066.2.2.多行注释1066.3.Package1076.3.1.import1086.3.2.expander1086.3.3.global全局变量1086.4.Function1106.5.Rule1116.5.1.Rule 属性1126.5.2.LHS (when) 条件元素1156.5.3.The Right Hand Side (then)1406.5.4.对自动封箱/拆箱以及元数据类型的注解1416.6.Query1416.7.Domain Specific Languages 领域特定语言1426.7.1.何时使用DSL1426.7.2.编辑与管理DSL1436.7.3.在规则中使用DSL1446.7.4.增加对fact的约束1456.7.5.DSL如何工作1466.7.6.从头开始建立DSL1466.8.规则流1476.8.1.设置规则所属的规则流组1486.8.2.简单的规则流1486.8.3.如何建立规则流1486.8.4.在你的应用程序中使用规则流1536.9.XML规则语言1536.9.1.何时使用XML1536.9.2. XML 格式1546.9.3.遗留的Drools 2.x XML 规则格式1596.9.4.Automatic transforming between formats (XML and DRL)159第七章:部署和测试1607.1.部署选项1607.1.1.使用RuleAgent部署1607.1.2.使用drl源码部署1617.1.3.在你的classpath中部署规则1617.1.4.可部署的对象RuleBase, Package等等.1617.1.5.部署模式1637.1.6.Web Services1667.1.7.未来的构想1667.2.测试1667.2.1.测试框架1667.2.2.FIT for Rules 一种规则测试框架166第八章. BRMS (业务规则管理系统)1688.1.简介1688.1.1.什么是BRMS?1698.1.2.特性概要1708.2.管理指南1708.2.1.安装1718.2.2.数据库配置1728.2.3.安全性1738.2.4.数据管理1768.3.体系结构1788.3.1.从源码构建1798.3.2.可重用组件1808.3.3.版本和存储库1808.3.4.贡献1818.4.快速使用指南1818.4.1.快速使用指南1818.4.2.BRMS 概念1838.4.3.The business user perspective1978.4.4.部署: 将规则与你的应用集成1978.5.例子与教程2008.5.1.保险经济折扣200第九章. Java规则引擎API2029.1 简介2029.2 java规则引擎API体系结构2029.3 规则管理API2029.4 运行时API2039.5 java规则引擎API的安全问题2049.6 异常与日志2059.7 JSR小结2059.8 Dools API 参考2059.8.1 简介2059.8.2.如何使用2059.8.3.参考书目209第一章 规则引擎初步了解1 为什么会有规则引擎?背景:复杂企业级项目的开发以及其中随外部条件不断变化的业务规则(business logic),迫切需要分离商业决策者的商业决策逻辑和应用开发者的技术决策,并把这些商业决策放在中心数据库或其他统一的地方,让它们能在运行时(即商务时间)可以动态地管理和修改从而提供软件系统的柔性和适应性。规则引擎正是应用于上述动态环境中的一种解决方法。企业管理者对企业级IT系统的开发有着如下的要求:为提高效率,管理流程必须自动化,即使现代商业规则异常复杂;市场要求业务规则经常变化,IT系统必须依据业务规则的变化快速、低成本的更新;为了快速、低成本的更新,业务人员应能直接管理IT系统中的规则,不需要程序开发人员参与。2 什么是规则引擎?也许这又是一种“先有蛋还是先有鸡”哲学争论,在JSR-94种也几乎没有定义,规则引擎这个术语是非常不明确的,因为任何以任意形式使用能够应用于数据生成结果的规则的系统都可以称为规则引擎。包括像表单验证和动态表达式引擎这样的简单系统都可以称之为规则引擎。可以这样理解规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据规则做出业务决策。3 为何要使用规则引擎?3.1 声明式编程规则引擎允许你描述做什么而不是如何去做。这里的主要优点是使用规则更加容易对复杂的问题进行表述,并得到验证。 (规则比编码更容易阅读). 规则系统能够解决非常非常困难的问题,并提供了方案怎样达到和在解决问题的方向上所作的每一个决定的原因(这对于类似神经网络这样的AI系统来说不容易达到)3.2逻辑与数据分离数据保存在系统对象中,逻辑保存在规则中。这根本性的打破了面向对象系统中将数据和逻辑耦合起来的局面,这点是有利的也是不利的,在于你的观察角度。这样做的结果是,将来逻辑发生改变时更容易被维护,因为逻辑保存在规则中。这点在逻辑是跨领域或多领域中使用时尤其有用。通过将逻辑集中在一个或数个清晰的规则文件中,取代了之前分散在代码中的局面。3.3 速度及可测量性Rete算法、Leaps算法,以及由此衍生出来的Drools的Rete、Leaps算法,提供了对系统数据对象非常有效率的匹配。这些都是高效率尤其当你的数据是不完全的改变(规则引擎能够记得之前的匹配)。这些算法经过了大量实际考验的证明。3.4 知识集中化通过使用规则,将建立一个可执行的规则库。这意味着规则库代表着现实中的业务策略的唯一对应,理想情况下可读性高的规则还可以被当作文档使用。3.5 工具集成例如Eclipse(将来可能在基于Web的界面上)这样的工具为规则的修改与管理、即时获得反馈、内容验证与修补提供了办法。审查与调试工具同样也可用了。3.6 解释机制通过将规则引擎的决断与决断的原因一起记录下来,规则系统提供了很好的“解释机制”。3.7易懂的规则通过建立对象模型以及DSL(域定义语言),你可以用接近自然语言的方式来编写规则。这让非技术人员与领域专家可以用他们自己的逻辑来理解规则(因为程序的迷宫已经被隐藏起来了) 。4 何时应当使用规则引擎?最简短的回答就是“当没有令人满意的传统的程序设计方法能够解决这个问题时”。下面对这个所谓的传统解决方法的一个描述: 对于传统代码来说,问题需要的精确度太高。这种问题可能并不复杂,但是你找不到一种稳定的方法去建立它。 问题超越了任何有明显运算法则的方案。 它是一个难以解决的复杂问题,没有明显的传统解决方案或者问题没有一个准确的定论。 业务逻辑经常发生改变逻辑本身是简单的(但不是指过于简单),但是规则经常发生变化。在许多软件组织中正式版本的间隔是较长并且较少的,规则可以在适当的安全前提下帮助提供一定的敏捷性。 领域专家(或者业务分析师)是非技术人员领域专家通常对业务规则和流程具有很好的认知。他们通常是不了解软件技术的人员,但是具有很好的逻辑性。规则能够让他们用自己的术语来描述业务逻辑。当然他们仍然需要严密的思考和良好的逻辑思维能力(许多在非软件技术型岗位上的人没有进行过形式逻辑的训练,因此在和他们工作时要特别小心,在将业务知识编撰成规则时,要特别注意业务规则和流程应当是当前能够理解的)。 5 如何使用规则引擎?由于规则引擎是软件组件,所以只有开发人员才能够通过程序接口的方式来使用和控制它,规则引擎的程序接口至少包含以下几种API:l 加载和卸载规则集的API;l 数据操作的API;l 引擎执行的API。开发人员在程序中使用规则引擎基本遵循以下5个典型的步骤:l 创建规则引擎对象;l 向引擎中加载规则集或更换规则集;l 向引擎提交需要被规则集处理的数据对象集合;l 命令引擎执行;l 导出引擎执行结果,从引擎中撤出处理过的数据。使用了规则引擎之后,许多涉及业务逻辑的程序代码基本被这五个典型步骤所取代。一个开放的业务规则引擎应该可以“嵌入”在应用程序的任何位置,不同位置的规则引擎可以使用不同的规则集,用于处理不同的数据对象。此外,对使用引擎的数量没有限制。6 何时不要使用规则引擎 ?因为规则引擎是动态的 (动态的在这里意味着规则可以象数据一样保存、管理和更新),它们通常被看作发布软件系统的一种解决方案(大多数IT部门似乎存在的目的是防止软件系统被遗弃)。如果这是你希望使用规则引擎的原因,应当意识到在可以写出公开发布的规则时,规则引擎能够以最佳方式工作。做为另一个方面,你也可以考虑使用数据驱动的设计(查找表)或者脚本/流程引擎带有能够在数据库中管理并能够动态更新的脚本。对特定的工作要使用恰当的工具。当然,必要时老虎钳可以当作锤子用,但那并不是发明老虎钳的本意。”7 规则引擎的架构和推理规则引擎的架构如下图所示:规则引擎的推理步骤如下:a.将初始数据(fact)输入至工作内存(Working Memory)。b.使用Pattern Matcher将规则库(Rules repository)中的规则(rule)和数据(fact)比较。c.如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。d.解决冲突,将激活的规则按顺序放入Agenda。e.执行Agenda中的规则。重复步骤b至e,直到执行完毕Agenda中的所有规则。任何一个规则引擎都需要很好地解决规则的推理机制和规则条件匹配的效率问题。当引擎执行时,会根据规则执行队列中的优先顺序逐条执行规则执行实例,由于规则的执行部分可能会改变工作区的数据对象,从而会使队列中的某些规则执行实例因为条件改变而失效,必须从队列中撤销,也可能会激活原来不满足条件的规则,生成新的规则执行实例进入队列。于是就产生了一种“动态”的规则执行链,形成规则的推理机制。这种规则的“链式”反应完全是由工作区中的数据驱动的。 规则条件匹配的效率决定了引擎的性能,引擎需要迅速测试工作区中的数据对象,从加载的规则集中发现符合条件的规则,生成规则执行实例。1982年美国卡耐基梅隆大学的Charles L. Forgy发明了一种叫Rete的算法,很好地解决了这方面的问题。目前世界顶尖的商用业务规则引擎产品基本上都使用Rete算法。8规则引擎的算法大部分规则引擎产品的算法,基本上都来自于Dr. Charles Forgy在1979年提出的RETE算法及其变体,Rete算法是目前效率最高的一个Forward-Chaining推理算法,Drools项目是Rete算法的一个面向对象的Java实现,Rete算法其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。详情请见CIS587:The RETE Algorithm,The Rete Algorithm,RETE演算法,专家系统原理与编程中第11章等。9 Java规则引擎商业产品组织/厂商名称主页说明JSR 兼容性ILOGJRules/software/cn/websphere/ilog/products/jrules/index.html已被IBM收购JRules 4.6DroolsDrools/drools.html已被Redhat JBoss收购,转向商业化,仍有社区版本基于JSR94和Rete算法Sandia LabsJESS/jess/JESS 6.1 p6JLisaJLisb/商业化/社区支持TmaxSoftProRule/jsp/main.jspFair Isaac, Blaze AdvisorBlaze Advisor/fic/cn/fic/cn/index.htmPegaSystems Inc.PegaRULES Process Commander/CRM行业的解决方案供应商,转向BPM领域第二章.Drools 规则引擎2.1.概述Drools被分为两个主要的部分:编制和运行时编制的过程包括为规则建立DRL或XML文件,传入一个由Antlr 3文法器定义的解析器中。下面的翻译要参考图1.10理解解析器对文件中规则文法的正确性进行检查并为descr建立一个中间结构,在AST中的descr代表规则的描述。AST然后将descr传入Package Builder中,由其进行打包。Package Builder同时负责包括打包中用到的所有代码产生器和编译器。Package对象是自包含并可配置的,它是一个包含规则的序列化的对象。Figure2.10.编制组件RuleBase是运行时组件,包含一个或多个Package。Package在任何时候都可以向RuleBase中添加或删除。一个RuleBase可以同时初始化多个Working Memory,在其间维护着一个弱引用,除非重新进行配置。Working Memory包含许多子组件,如Working Memory Event Support(事件支持), Truth Maintenance System(真值维护系统), Agenda 和 Agenda Event Support(事件支持)。向Working Memory中设置对象的工作可能要在建立了一个或多个激活的规则后才结束。Agenda负有规划激活规则运行的责任。Figure2.11. 运行时组件2.2.编制Figure2.12.PackageBuilderDrlParser, XmlParser 和 PackageBuilder这三个类被用来进行编制。两个分析类用来从提供的可读流实例中建立descr AST模型。PackageBuilder提供相应API使得你可以不用记住这些类。addPackageFromDrl 和 addPackageFromXml是两个常用方法都要求一个可读流实例作参数。下面的例子说明一个如何建立一个包括XML和DRL规则文件的包,文件的位置在相对于classpath变量中定义的路径下。注意,对于增加到当前PackageBuilder实例中的所有规则包,必须具有同样的包名称空间。Example2.1.从多个源中建立包PackageBuilder builder = new PackageBuilder();builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( package1.drl ) ) );builder.addPackageFromXml( new InputStreamReader( getClass().getResourceAsStream( package2.xml ) ) );builder.addRuleFlow( new InputStreamReader( getClass().getResourceAsStream( ruleflow.rfm ) ) );Package pkg = builder.getPackage(); 有一个要点,在正式使用PackageBuilder之前,要先检查其中是否有错误。当一个被打断的Package加入ruleBase时,将会抛出一个InvalidRulePackage,错误被包含在这个Package并且只有一个等价于toString()的方法有效。如果你询问PackageBuilder,可以返回更多的有效信息。Example2.2.使用 PackageBuilder 检查错误PackageBuilder builder = new PackageBuilder();builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( package1.drl ) ) );PackageBuilderErrors errors = builder.getErrors();PackagBuilder使用PackageBuilderConfiguration类配置。Figure2.13.PackageBuilderConfigurationPackageBuilderConfiguration的默认值可以通过程序设置或通过外部特性配置在一开始就改变。在配置之前先通过ChainedProperties类在许多位置搜索drools.packagebuilder.conf文件;当发现它们之后,加入其中定义的配置到主要特性列表中;这提供了一个搜索的级别优先性。位置优先性的顺序是:系统特性,用户在系统特性中定义的文件,用户Home目录,工作目录,各种META-INF位置。除此之外,droosl-compiler jar在它的META-INF目录中有它自己的默认设置。当前PackageBulderConfiguration处理Accumulate函数的注册,语言的注册以及主要的类调用器(ClassLoader)。Drools有一个可插入的语言系统,它允许其它语言编译和执行表达式与代码块,当前两种支持的语言是Java和MVEL。每一个都有它自己的DialectConfiguration接口实现;Javadocs文档中提供了每一个setter/getter的细节以及用于配置它们的特性名称。Figure2.14.JavaDialectConfigurationJavaDialectConfiguration允许设置用于支持它的编译器和语言水平。你可以通过在可以被ChainedProperties 实例发现的packagebuilder.conf文件中设置piler特性来覆盖它,或者你可以通过下面的程序在运行时改变。Example2.3.配置JavaDialectConfiguration 使用JANINO PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( );JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( java );javaConf.setCompiler( JavaDialectConfiguration.JANINO ); 如果在你的classpath中没有Eclipse JDT Core,你必须在实例化PackageBuilder之前覆盖这个默认的编译器设置,你可以通过一个ChainedProperties类可以发现的packagebuilder特性文件或通过下面的程序方式改变它;注意我使用特性为启动注入值的时间。Example2.4.配置 JavaDialectConfiguration 使用 JANINOProperties properties = new Properties();properties.setProperty( piler, JANINO );PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( properties );JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( java );assertEquals( JavaDialectConfiguration.JANINO, javaConf.getCompiler() ); / 确认编译器被正确配置 当前允许在Janino和Eclipse JDT两个编译器之间选择一个,以及设置不同的JDK源码级别(1.4 和1.5)和一个父类装载器。默认的编译器是在JDK1.4水平上的Eclipse JDT Core编译器,以及将设置到Thread.currentThread().getContextClassLoader()中的父类装载器。接下来的代码显示如何指定JANINO编译器:Example2.5.通过特性配置PackageBuilder使用JANINOPackageBuilderConfiguration conf = new PackageBuilderConfiguration();conf.setCompiler( PackageBuilderConfiguration.JANINO );PackageBuilder builder = new PackageBuilder( conf );MVELDialectConfiguration更加简单,并且只允许精确的(strict)的模式被打开或关闭,默认strict是true;这意味着所有方法调用必须是类型安全的,不管是经过推断声明或显示声明的类型。Figure2.15.MvelDialectConfiguration2.3.RuleBaseFigure2.16.RuleBaseFactoryRuleBase使用RuleBaseFactory实例化,默认情况下返回一个ReteOO的RuleBase。Package通过使用addPackage方法按顺序加入。你可以指定任何名称空间的Packages或者同一名称的多个包加入RuleBase。Example2.6.增加Package到新的RuleBaseRuleBase ruleBase = RuleBaseFactory.newRuleBase();ruleBase.addPackage( pkg ); Figure2.17.RuleBaseRuleBase包含一个或多个规则包,它们已经被校验和编译完成,以备使用。RuleBase是可序列化的,因此它可以被配置到JNDI或其它类似的服务上。典型的,RuleBase在第一次使用时产生并缓存,这是一个昂贵的操作(花费大量时间)。RuleBase通过RuleBaseFactory来初始化,默认情况下返回一个ReteOO RuleBase(面向对象化的Rete算法的RuleBase)。可以指定参数决定返回ReteOO还是Leaps。接着使用addPackage方法将包加入。你可以指定在任意名称空间中的包,并且处于相同名称空间的多个包可以被加入。RuleBase的实例是线程安全的,这意味着你可以在你的应用间共享一个实例,现实中可能是一个Web应用程序。在RuleBase上最常见的操作是建立一个新的规则Session,可以是有状态或无状态的。RuleBase也保存着任何由它产生的有状态Session的引用,因此如果规则改变(被新增/删除等等。对于长时间运行的Session),它们可以用最新的规则更新而不需要重启Session。你可以指定不去维护一个引用,但只在你明确知道Rule Base不会被更新的情况下使用。RuleBase不会对无状态Session保持引用。ruleBase.newStatefulSession(); / maintains a reference.ruleBase.newStatefulSession( false ); / do not maintain a reference Package可以在任何时候新增或删除所有的变更都会传播到现存的有状态Session中;不要忘记调用fireAllRules()激发已经激活的规则。ruleBase.addPackage( pkg ); / 新增package实例ruleBase.removePackage( .sample ); /通过名称空间删除package和所有部件ruleBase.removeRule( .sample, my rule ); / 从名称空间删除指定规则 有方法可以用来删除单独的规则,但是没有方法新增一个单独的规则要实现这个目标,增加一个只含有一个规则的Package。RuleBaseConfigurator可以被用来指定RuleBase的附加行为。RuleBaseConfigurator在加入Rule Base中之后被设置为不可改变。几乎引擎的所有优化方式都可以在这里打开或关闭,也可以设置要执行的行为。用户通常关心插入行为(同一性和等同性)以及叉集行为(删除或保持同一性相等的叉集)。RuleBaseConfiguration conf = new RuleBaseConfiguration();conf.setAssertBehaviour( AssertBehaviour.IDENTITY );conf.setRemoveIdentities( true );RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );Figure2.18.RuleBaseConfiguration2.4.WorkingMemory 和有状态/无状态SessionsFigure2.19.WorkingMemoryWorkingMemory保存所有插入的数据的引用直到该数据被删除,并且它是与你的应用程序发生交互的地方。WorkingMemory是有状态的对象,它们可以短期或长期存在。2.4.1.FactsFacts是由你的应用程序设置到Working Memory 中的对象。Facts可以是任何规则可以存取的Java对象。规则引擎完全不会克隆对象,它仅仅是保存对对象的一个引用/指针。Facts是你的应用程序的数据。字符串以及其它没有getter和setter方法的类不是有效的Facts,不能被用于字段约束,因为字段约束依赖于根据JavaBean标准的getter和setter方法来与对象交互。2.4.2.Insertion Insert 是通知working memory关于facts的操作。例如,WorkingMemory. insert (yourObject)。当你插入一个fact时,它检查与规则的匹配情况。这意味着所有工作在插入Fact期间就已经完成,但在你调用fireAllRules()方法之前没有任何规则被执行。在你完成所有fact的设置之前你不应该调用fireAllRules()。人们通常会误会所有的相关工作在fireAllRules()调用后才进行。专家系统通常使用术语assert或assertion来指代将fact设置到系统中的操作,但是随着assert在大多数语言中成为了一个关键字,我们使用Insert关键字来代替它,以避免关键字冲突。当对象被Insert到WorkingMemory中时,它返回一个FactHandle。这个FactHandle是象征着你插入WorkingMemory中的对象,它也是当你希望从Working Memory中删除或修改一个对象时所必须的。Cheese stilton = new Cheese(stilton);FactHandle stiltonHandle = session.insert( stilton ); 在RuleBase中Working Memory在插入时可能有两种操作方式等同性equality和同一性identity,identity是默认操作。Identity意味着Working Memory使用一个IdentityHashMap去保存所有被插入进来的对象。被插入进来的新的实例都会返回一个新的FactHandle。如果一个实例被插入进来两次,将返回前一个的FactHandle,对相同实例直接忽略第二次插入。Equality意味着Working Memory使用一个HashMap保存所有插入的对象。这个模式下,当插入的 Object 相等时,它返回同一个 FactHandle。.Retraction当你 retract 一个 fact , WorkingMemory 将不再跟踪那个 fact 。任何被 activated 并依赖那个 fact 的规则将被取消。注意:完全有可能存在某条规则是依赖于一个 fact 的“不存在”( non existence )。在这种情况下, retract 一个 fact 将导致一条规则被激活。对一个 Fact 进行 Retraction ,必须用 Insert时返回的那个 FactHandle 做为参数。Cheese stilton = new Cheese(stilton);FactHandle stiltonHandle = session.insert( stilton );.session.retract( stiltonHandle ); 2.4.4.Update当一个 Fact 被修改了,会通知规则引擎进行重新处理。在规则引擎内部实际上是对旧的 Fact 进行 retract ,然后对新的 Object 再进行 insert。要使用 modifyObject() 方法来通知 Working Memory ,被改变的 Object 并不会自己通知规则引擎。注意: modifyObject() 方法总是要把被修改的 Object 做为第二参数,这就允许你把一个不可变对象替换为另一个新对象。update()方法只能在影子代理打开的情况下对对象使用。如果你没有使用影子代理,那你必须在调用update之前先session. modifyRestract (),然后在update之后调用session.modifyInsert()。Cheese stilton = new Cheese(stilton);FactHandle stiltonHandle = workingMemory.insert( stilton );.stilton.setPrice( 100 );workingMemory.update( stiltonHandle, stilton ); 2.4.5.全局变量Global 是一个能够被传进 WorkingMemory 但不需要进行insert操作的命名对象。大多数这些对象被用来作为静态信息或被用在一条规则的RHS 部分的服务,或者可能是从规则引擎返回对象的一种方法。 如果你在规则的LHS部分使用全局变量,那必须确保它不会改变。全局变量在Session中设置之前必须首先在Drl文件中定义。global java.util.List list 随着Rule Base现在知道全局变量的定义和它的类型,任何Session现在可以调用session.setGlobal;如果之前对全局变量的类型和定义有错误,将会抛出异常。使用session.setGlobal(identifier, value)将全局变量设置到Session中;List list = new ArrayList();session.setGlobal(list, list); 如果一条规则在你 setGlobal 之前调用了定义的 Global ,会抛出一个 NullPointerException。2.4.6.影子(shadow)Facts影子Fact是一个对象的浅拷贝,用来缓存被设置到working memory 中的对象的拷贝。术语shadow facts来自JESS(Java Expert System Shell)的一个特性。影子Fact的用意是回溯真值维护的概念。基本思路是,专家系统应当确保推导出的结论是准确的。一个运行中的应用系统可能在规则引擎的推导过程中改变了fact的数据。当发生这种情况时,规则引擎必须知道这种改变发生了,并进行适当的处理。通常有两种方法来保证真实性。第一种是在推论期间锁定所有的Facts。第二种是建立一个对象的缓存,并且强迫所有的改变必须通过规则引擎进行。在这种方法下,改变能够有序的进行。Shadow facts在多线程的环境中是非常重要的,当一个规则引擎被多个Session共享时。缺少了真值维护,系统无法证明结论是正确的。Shadow facts带来的主要优点是它使得开发更加容易。当需要开发者强制保持对fact修改的跟踪时,是非常容易出错,并且很难调试的。在没有增加对fact的更改进行跟踪的功能时,使用规则引擎建立一个有一定复杂度的系统是非常困难的。Drools4.0对影子Fact有完全的支持,使用完全透明的lazy代理实现这一机制。影子fact机制默认是启用的,不会从外部的代码中看出来,甚至是在规则代码块中的代码。虽然影子fact是确保引擎完整性的一个很好的方法,但是它们也给推论过程增加了一些负载。因此Drools4.0支持对它们更细致的控制,能够对单独的每一个类启用/禁用它们。要在所有的类上禁用影子fact,在系统特性的配置中设置以下特性:drools.shadowProxy = false另外,它也可以通过一个API调用来禁用它:RuleBaseConfiguration conf = new RuleBaseConfiguration();conf.setShadowProxy( false );.RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );只对列表中的类禁用影子代理,使用下面的特性:drools.shadowproxy.exclude = org.domainy.* org.domainx.ClassZ如上所示,使用空格来分隔多于一个类的列表,并且使用*来作为广义字符。注意: 对一个类禁用影子fact,意味着解除了引擎对类属性发生变化时的跟踪机制。它意味着一旦fact杯插入引擎后,不能有任何改变,否则会带来不可预期的行为。即使使用update()都没有帮助。在影子机制被禁止时,唯一安全的修改fact属性的方法是在属性改变前调用modifyRetract(),改变后调用modifyAssert()。2.4.7.属性更改监听器(Property Change Listener)如果你的 fact 对象是 JavaBean ,你可以为它们实现一个 property change listener ,然后把它告诉规则引擎。这意味着,当一个 fact 改变时,规则引擎将会自动知道,并进行响应的动作(你不需要调用 modifyObject() 方法来通知 WorkingMemory )。代理库将会帮助实现这一切。要让 Property Change Listener 生效,还要将 fact 设置为动态( dynamic )模式,通过将 true 做为 assertObject() 方法的第二个参数来实现: Cheese stilton = new Cheese(stilton);/specifies that this is a dynamic fact FactHandle stiltonHandle = workingMemory.insert( stilton, true ); 然后要在 JavaBean 中加入一个 PropertyChangeSupport 实例,和两个方法: addPropertyChangeListener() 和 removePropertyChangeListener() 。最后要在 JavaBean 的 setter 方法中通知 PropertyChangeSupport 所发生的变化。示例代码如下: private final PropertyChangeSupport changes = new PropertyChangeSupport( this );.public void addPropertyChangeListener(final PropertyChangeListener l) this.changes.addPropertyChangeListener( l );public void removePropertyChangeListener(final PropertyChangeListener l) this.changes.removePropertyChangeListener( l );.public void setState(final String newState) String oldState = this.state; this.state = newState; this.changes.firePropertyChange( state, oldStat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论