Drools应用手册 (2)

上传人:痛*** 文档编号:120608767 上传时间:2022-07-18 格式:DOC 页数:42 大小:950.50KB
收藏 版权申诉 举报 下载
Drools应用手册 (2)_第1页
第1页 / 共42页
Drools应用手册 (2)_第2页
第2页 / 共42页
Drools应用手册 (2)_第3页
第3页 / 共42页
资源描述:

《Drools应用手册 (2)》由会员分享,可在线阅读,更多相关《Drools应用手册 (2)(42页珍藏版)》请在装配图网上搜索。

1、Drools应用手册版本日期修改历史作者0.12010年8月27日文档创建刘俊豪33 / 42目 录1简介11.1什么是规则引擎?11.2Drools简介11.3何时使用Drools12Drools工作原理32.1产生式规则引擎工作原理32.2RETE算法43Drools实战13.1安装Eclipse开发插件13.2Hello Drools23.3规则语言73.3.1规则文件73.3.2规则构成83.3.3保留字83.3.4注释103.3.5Package103.3.6Import113.3.7Expander113.3.8Global全局变量113.3.9Function133.3.10规则

2、133.3.11规则属性153.3.12LHS (when) 条件元素17简介本文档是描述如何去使用Drools的文档,重点放在规则的语法和用法上,可让读者在编写规则是查阅,因此对于Drools的实现原理就不会详尽的介绍,如果读者有兴趣可以联系本文作者索取相关资料。什么是规则引擎?在大型商业系统中,业务规则、商业逻辑等等都会比较复杂。而且在很多大型系统当中,很多业务规则、商业逻辑并不是一成不变的。甚至当系统进入生产阶段时,客户的业务规则、商业逻辑也会改变。某些系统要求甚至更高,要求能24小时不停机,并且能够实时修改商业规则。这就对商业系统提出了较大的挑战。如果将这些可变的规则直接编写到代码里面

3、的话,业务规则一旦改变,就要修改代码。并由此带来编译、打包、发布等等问题。这对于生产系统来说是极不方便的。因此,如何考虑把一些可变的业务规则抽取到外面,使这些业务规则独立于程序代码。并最好是能够实时的修改业务规则,这样就可以做到不用打包编译发布等等。因此,规则引擎营运而生。规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。使用规则引擎可以通过降低实现复杂业务逻辑的组件的复杂性,降低应用程序的维护和可扩展性成本。大多数规则引擎都支持规则的次序和规则冲突检验

4、,支持简单脚本语言的规则实现,支持通用开发语言的嵌入开发。目前,市面上应用产生了众多的规则引擎。开源规则引擎的代表是Drools;商业规则引擎的代表是ILog。Drools简介Drools(又称 JBoss Rules)是JBoss开源社区中的一个为Java量身定制的、基于RETE算法的产生式规则引擎的实现。 目前(2010年8月),Drools最新的版本是5.1.0.M1,本文档是基于此版本来描述,所有例子都是基于Drools5.1.0.M1。读者可到Drools的官方网站下载Drools的相应版本()。何时使用Drools对这个问题最简短的回答就是“当没有令人满意的传统的程序设计方法能够解

5、决这个问题时”。下面上对所谓没有传统解决方法的一个描述: l 对于传统代码来说,问题需要的精确度太高。这种问题可能并不复杂,但是你找不到一种稳定的方法去建立它。l 问题超越了任何有明显运算法则的方案。 它是一个难以解决的复杂问题,没有明显的传统解决方案或者问题没有一个准确的定论。l 业务逻辑经常发生改变逻辑本身是简单的(但不是指过于简单),但是规则经常发生变化。在许多软件组织中正式版本的间隔是较长并且较少的,规则可以在适当的安全前提下帮助提供一定的敏捷性。l 领域专家(或者业务分析师)是非技术人员领域专家通常对业务规则和流程具有很好的认知。他们通常是不了解软件技术的人员,但是具有很好的逻辑性。

6、规则能够让他们用自己的术语来描述业务逻辑。当然他们仍然需要严密的思考和良好的逻辑思维能力(许多在非软件技术型岗位上的人没有进行过形式逻辑的训练,因此在和他们工作时要特别小心,在将业务知识编撰成规则时,要特别注意业务规则和流程应当是当前能够理解的)。如果规则对于你的项目组来说是一种新的技术,那在使用前必须将学习与管理的费用成本考虑进去。规则不是一种无意义的技术,这篇文档尽量让其易于理解。在一个面向对象的应用中,规则引擎通常被用在包含业务逻辑的关键部分(具体与应用相关),特别是在十分繁杂凌乱的部分。这是对面向对象中将所有逻辑封装在对象中的一个倒置。但这并不是说应该抛弃对象模型,相反的来说在任何一个

7、现实应用中业务逻辑仅仅是应用的一部分。如果你曾注意到在你的代码中有很多”if”else”switch”和其它凌乱的逻辑,你总是要回过头去修改它们(可能是由于提供给你的逻辑是错误的,或是你的理解变化了),那么可以考虑使用规则。如果你所面对的问题没有算法或者模式合适解决,考虑使用规则。规则可以被嵌入你的应用中,或者作为一个服务使用。通常规则最好被当作一个有状态的组件使用因此它们通常在应用中是一个整体。无论怎样,在一些规则被成功定义为可重用的服务的个案中,规则是无状态的。如果考虑在组织中使用规则,那考虑产品中将如何使用和更新规则是很重要的(选择很多,但是不同的组织间有不同的需要通常这超出了应用者/项

8、目团队的控制)。Drools工作原理上文中曾经提到过,Drools是基于RETE算法的产生式规则引擎。那么,什么事产生式规则引擎?什么事RETE算法呢?下面为您逐一讲解。产生式规则引擎工作原理产生式规则引擎完全关注于精确表达propositional(命题)和first order logic(一阶逻辑)的知识表示,不存在含糊不清的定义。产生式规则系统的核心是一个能够处理大量规则和事实的推理引擎。推理引擎将事实、数据与产生式规则(也可以叫做产生式,或干脆叫规则)进行匹配,以推出结论。产生式规则是一个用一阶逻辑进行知识呈现的二元结构。when then 将新的或已存在的事实与产生式规则进行匹配的

9、过程被称为模式匹配,这个过程由推理机完成。推理机使用的用于模式匹配的算法有很多,包括: Linear 线性的 Rete 网状 Treat Leaps 叶状Drools实现了Rete和Leaps算法;Leaps是试验性质的,因为它是个十分新的算法。Drools目前用的主要是Rete算法,下一章会详细介绍Rete算法。规则保存在Production Memory(规则库)中,推理机要匹配的facts(事实)保存在Working Memory(工作内存)中。事实被插入到工作内存中后,可能被修改或删除。一个有大量规则和事实的系统可能会很多规则被满足,这些规则被称为具有冲突性。Agenda通过(冲突决策

10、策略)管理这些冲突规则的执行顺序。RETE算法RETE算法是一个用来实现产生式规则系统的高效模式匹配算法。该算法是由卡内基美隆大学的Charles L. Forgy在1974年发表的论文中所阐述的算法。RETE算法提供了专家系统的一个高效实现。规则推理引擎做为产生式系统的一部分,当进行事实的断言时,包含三个阶段:匹配、选择和执行,称做match-select-act cycle。RETE算法可以对匹配阶段进行高效实现,下面从鉴别网络和模式匹配过程两个方面对该算法进行介绍。鉴别网络(如下图所示):由RETE算法在进行模式匹配时,是根据生成的鉴别网络来进行的。网络中非根结点的类型有1-input结

11、点(也称为alpha结点)和2-input结点(也称为beta结点)两种。1-input结点组成了Alpha网络,2-input结点组成了Beta网络。每个非根结点都有一个存储区。其中1-input结点有alpha存储区和一个输入口;2-input结点有left存储区和right存储区和左右两个输入口,其中left存储区是beta存储区,right存储区是alpha存储区。存储区储存的最小单位是工作存储区元素(Working Memory Element,简称WME),WME是为事实建立的元素,是用于和非根结点代表的模式进行匹配的元素。Token是WME的列表,包含有多个WME,(在Forgy

12、的论文中,把Token看成是WME的列表或者单个WME,为了阐述方便,本文将把Token只看成WME的列表,该列表可以包含一个WME或者多个WME),用于2-input结点的左侧输入。事实可以做为2-input结点的右侧输入,也可以做为1-input结点的输入。每个非根结点都代表着产生式左部的一个模式,从根结点到终结点的路径表示产生式的左部。Drools实战安装Eclipse开发插件Drools提供了基于eclipse的IDE,读者可以到Drools官网()上下载Drools Eclipse 3.5 Workbench插件到本地,然后解压该压缩包。把解压出来的features和plugins文

13、件夹拷贝到Eclipse安装目录下dropins文件夹,然后重启Eclipse。Eclipse启动后,打开Windows Preference。我们就看到Drools插件已经加载进来,看下图:然后进入Drools Install Drools Runtime 点击Add 按钮。分别填入Runtime的名称和Drools的安装路径(bin)。包存后,勾上CheckBox。让新增的Runtime成为默认的Runtime再保存设置。到此为止,Drools的Eclipse插件安装已经成功。Hello Drools闲话少说,下面我们利用Eclipse插件来建立第一个Drools项目。首先,打开File

14、New Other窗口打开新建项目窗口,展开Drools节点选择Drools Project再点击Next按钮。请看下图:然后,在New Drools Project页面输入你Project的名字,再点击Next按钮。来到例子的生成页面,勾上头两项:生成一个Hello World的规则文件和生成一个执行规则文件的Java文件。如下图:最后,Eclipse就会新建一个带有规则文件例子的Drools项目。接下来我们看看这个项目的结构吧。从上图可以看到,整个项目中有两个文件。第1个是调用规则文件的Java文件,里面写有如何去加载和执行规则文件;第2个文件就是规则文件,里面定义了一些规则。我们再看看这

15、文件里面的内容吧。首先,是DroolsTest.java文件。从上图我们也可以看出Drools被分为两个主要的部分:编制和运行时。编制的过程包括为规则建立DRL或XML文件,传入一个由Antlr 3文法器定义的解析器中。解析器对文件中规则文法的正确性进行检查并为descr建立一个中间结构,在AST中的descr代表规则的描述。AST然后将descr传入Package Builder中,由其进行打包。Package Builder同时负责包括打包中用到的所有代码产生器和编译器。(请参考下图理解)Package对象是自包含并可配置的,它是一个包含规则的序列化的对象。RuleBase是运行时组件,包

16、含一个或多个Package。Package在任何时候都可以向RuleBase中添加或删除。一个RuleBase可以同时初始化多个Working Memory,在其间维护着一个弱引用,除非重新进行配置。Working Memory包含许多子组件,如Working Memory Event Support(事件支持), Truth Maintenance System(真值维护系统), Agenda 和 Agenda Event Support(事件支持)。向Working Memory中设置对象的工作可能要在建立了一个或多个激活的规则后才结束。Agenda负有规划激活规则运行的责任。然后,我们再

17、看看规则文件里的内容:package com.sample import com.sample.DroolsTest.Message; rule Hello Worldwhenm : Message( status = Message.HELLO, myMessage : message )thenSystem.out.println( myMessage ); m.setMessage( Goodbye cruel world );m.setStatus( Message.GOODBYE );update( m );endrule GoodByewhenMessage( status = M

18、essage.GOODBYE, myMessage : message )thenSystem.out.println( myMessage );end我们可以看到。规则文件里面有两条规则,分别是“Hello World”和“GoodBye”。每条规则里面有一个LHS(Left hand side 即When语句)和RHS(Right hand side即Then语句)。当一个事实传进来时,他会先去LHS匹配,如果匹配成功就执行RHS的代码;否则,就不执行RHS。然后,该事实再去匹配下一个规则,直到匹配完成或者被retract语句从Working Memory中移除为止。现在我们回过头来看看这

19、个例子的执行结果吧。右击DroolsTest.Java文件,在弹出菜单中选择Run As Java Application 来执行测试例子。我们可以在控制窗口中看到运行的结果:我们一起来解析一下这个例子的运行步骤:1.程序中给Working Memory插入了一个,message为Hello World, status 为Message.Hello的Message对象。在Working Memory中Message被封装成一个事实(Fact)。2.Message这个事实就会去匹配各个规则,当匹配到“Hello World”规则的时候,他就符合LHT,RHT会被执行。在RHS中是先输出了Mess

20、age的message,然后把message属性改为Goodbye cruel world, 把status属性改为Message.GOODBYE。实际上,直到现在Working Memory中的Message还没有被更改,当用户调用update方法时,事实才被修改,通知也会通知Working Memory,Message这个事实已经被更新,要求进行新一轮的规则匹配。3.在新一轮的规则匹配当中,规则“GoodBye” 匹配成功。然后执行其RHS,输出message。讲到这里相信大家都已经对Drools规则引擎的运行有了初步了解。接下来我们先学习一下Drools文件里的语法吧。 规则语言规则文件

21、规则文件通常是以drl扩展名结尾。在一个drl文件中可以包含多个规则,函数等等。但是你也可以将规则分开到多个规则文件中(在这种情况下建议采用.rule扩展名,但不是必需的),分散规则利于管理巨量规则的情况。DRL是简单的text文件格式。规则文件的完整结构是:package package-nameimportsglobalsfunctionsqueriesrules这些元素的声明顺序不重要,处理package的名称如果声明的话必须是规则文件的第一个元素。所有的元素都是可选的,因此你只要用你所需要的就行了。我们将在下面的内容中对它们逐一讨论。规则构成规则具有如下主体结构:rulenameatt

22、ributeswhenLHSthenRHSend规则的结构是非常简单的,许多符号都是不需要的,甚至“name”两边的引号也是可选的。ATTRIBUTES(通常是可选项)指出规则的行为表现。LHS是规则的条件部分,它遵循下面将提到的语法。RHS是允许Java语义代码(很快将支持其它语言和C#)执行的块。仅有的特别的关键字是为了设置,删除和修改facts所用。任何在LHS中绑定的变量可以在RHS中使用。特别注意的是,空白是不重要的,除非在DSL中使用,在DSL中每一行会先于下一行处理(空白在这里可能有很重要的作用)。保留字在规则语言中使用了一些保留字。避免在你的领域对象,属性,方法,函数以及规则的

23、其它部分中使用保留字是明智的。接下来的列表是你应该在规则内容中避免使用的保留字(如果使用了,大多数时候可以正常工作,但有时会引起解析错误)。当然你可以将这也关键字用作方法等定义的一部分,例如notSomething(),这样没有问题。下面的保留字是在编写规则时应当尽力避免使用的:l rulel queryl whenl thenl endl nulll andl orl notl existsl collectl accumulatel froml foralll truel falsel eval下面的列表是你在编写规则时应当尽量避免使用的,但是如果你不得不在某些地方使用它们,语法分析器也可

24、以正常工作。l packagel functionl globall importl templatel attributesl enabledl saliencel durationl initl actionl reversel resultl containsl excludesl memberOfl matchesl inl date-effectivel date-expiresl no-loopl auto-focusl activation-groupl agenda-groupl dialectl rule-flow-group当然,你可以将它们用作方法名称的一部分,如notS

25、omething()这完全没有问题。注释你可以使用# 或者/建立单行注释。语法分析器会自动忽略注释的内容。例如:/ this is a single line comment.# this is a single line comment.多行注释使用/* */符号。/* this is a multi-line comment in the left hand side of a rule */Package包是规则以及其它相关结构的一个集合,如import和global。包的成员应该彼此有一定联系,如人力资源的规则包。一个包通过名称空间描绘,这样很好的保持了一组规则的独立性。包名也就是名称

26、空间名,与文件或目录名称无关。运行时的规则包可以从多个规则源码处组装,当组装完成时,所有的规则被放入一个顶级的Package配置中。但是不可能将不同名称的Package的内容放入同样的Package资源下。在一个RuleBase上可以建立多个Package。通常情况是将所有同名Package下的规则放在一个文件中(这样它就是完全自包含的)。下面的蓝图显示一个包中可能包含的所有组件。注意,包必须有一个名称空间,并且使用标准的java约定进行命名;例如包名不允许空格,不像规则名称可以有空格。除了package和expander标记必须放在文件的顶部,在其它规则之前,其它关键字元素的使用没有任何顺序

27、要求,可以使用在文件的任何地方。分号是可选用的。ImportImport标记就像java中的含义一样。对于任何要用在规则中的对象,你需要指定完整的路径和类型名。Drools从同名的java包中自动导入类。ExpanderExpander标记是可选的,用来指定DSL配置(通常保存在独立文件中)。这为解析器提供了如何理解你自定义的规则语言。要注意的是在Drools4.0中(这里与Drools3.x中不同),expander声明强制工具提供你的上下文环境并且避免错误报告,但是API允许用编程方式附加DSL模板,如果expander没有声明在源文件中。Global全局变量Global是全局变量。如果多

28、个包定义了同样名称的全局变量,它们必须使用同样的类型,并且全部指向同一个全局值。全部变量通常用来返回数据,如一个动作的记录,获得提供数据或服务给规则使用。Global不会插入到Working Memory中,因此当全局变量发生改变时,引擎不会得知;因为这个原因,全局变量不能用在条件约束上,除非这个值不会发生改变。在条件约束中错误使用全局变量会导致意想不到的结果。Globals是全局的变量。他们常用来将应用程序的对象提供给规则使用,通常是将数据或服务提供给规则使用(指定使用在规则推论中的应用服务),从规则处返回数据(如日志或在规则推论中增加的值)或者从规则中对应用进行回调。全局变量不会被插入Wo

29、rking Memory,因此它们从来不会参与推论,如果全局变量是一个不变的常量,则只在LHS中使用它们。引擎不会通知和跟踪全局变量的值变更。不正确的在约束中使用全局变量会带来让人惊讶的结果糟糕的惊讶,就像医生对你的X光片说“那里有些有趣的东西”一样。如果多个Package声明了同样的全局变量,那么它们必须有相同的类型,并指向同一个全局变量。为了使用全局变量,你必须:在规则文件中声明全局变量并使用它,如:global java.util.List myGlobalList; rule Using a globalwhen eval( true )then myGlobalList.add( H

30、ello World );end在working memory上设置全局变量的值。最好是在将fact插入working memory之前设置完所有全局变量,如:List list = new ArrayList();WorkingMemory wm = rulebase.newStatefulSession();wm.setGlobal( myGlobalList, list );注意,这些全局变量只是从你的应用传到Working Memory的对象的实例。这意味着你可以传入任何你想要的对象:你可以传递一个服务的位置代理,或者可能是一个服务本身。随着新的from元素现在可以传递一个Hibern

31、ate Session对象作为全局变量,允许from通过一个命名的Hibernate查询中将数据拉进来。可能的一个例子是Email服务。在你的规则引擎的集成代码中,你获得你的email服务对象,并且将它引入到working memory。在DRL文件中,声明你已经有了一个EmailService类型的全局变量,并给它一个名称为email。然后在规则的推论中,你就可以使用类似email.sendSMS(number,message)这样的调用。全局变量不是被设计用来在规则之间共享数据的,并且它们永远都不应该用于这个目的。规则经常对working memory进行推论和删除fact,因此如果你想在

32、规则间共享数据,将数据插入working memory就可以。从规则中设置全局变量的值是非常不合适的,我们建议你在应用程序中通过working memory的接口设置这个值。Function相对于正常的java类,函数是在你的规则代码中放置语言代码的方法。它们不可能做任何超过你可以在帮助类(在java中定义,被设置入规则的Working Memory中的类)中做到的事情(实际上,编译器为后面的场景产生帮助类,那样帮助不大)。主要使用函数的优点是可以将逻辑保存在一个地方,并且你可以在需要的时候改变函数(这样做各有优缺点)。函数最大的用处是被规则的推论(then)部分中的行为所调用,特别是当一个行

33、为操作需要反复被调用时如发送邮件。典型的函数声明如下所示:function String hello(String name) return Hello +name+!;注意function关键字的使用,虽然它并不真的是java的一部分。传入function的参数就像普通的方法一样(如果不需要参数可以为空)。返回值的概念也和普通方法相同。作为使用函数的另一种方法,你可以在辅助类中使用一个静态方法:Foo.hello()。Drools4.0支持静态方法导入,因此你只需要做下面的事情:import static my.package.Foo.hello对于上面的情况,要使用函数只需要在推论或代码块

34、中通过函数名称来调用它,例如:rule using a static functionwhen eval( true )then System.out.println( hello( Bob ) );end规则规则指定“when”作为一系列条件的集合(称为LHS),然后在“then”中指定一系列操作(称为RHS)。一个用户经常问的问题是“为什么使用when代替if”。“when”之所以取代“if”是因为“if”通常是程序执行过程中的一部分,在某一个特定的时间点它对条件进行检查。而“when”代表着它不约束在特定的评估顺序或时间点,在引擎生命周期的任何时候“when”都可以执行。规则必须有一个名

35、称,并且在一个包中是唯一的。如果你在同一个DRL中定义同名规则两次,在装载时将产生一个错误。如果你新增的DRL包含一个存在于Packaage中的规则,那新的规则将替换旧规则。如果规则名称中有空格,需要使用双引号包含(好习惯是定义名称时都使用双引号)。特性是可选的,最好保持每行一条,如下描述:规则的LHS部分跟随when关键字(when最好在单独的一行上),RHS部分跟随then关键字(最好也单独一行)。规则使用end关键字结尾。规则不能进行嵌套。Example规则语法rule *when *then *endExample规则示例rule Approve if not rejected sal

36、ience -100 agenda-group approval when not Rejection() p : Policy(approved = false, policyState:status) exists Driver(age 25) Process(status = policyState) then log(APPROVED: due to no objections.); p.setApproved(true);end规则属性规则属性提供了影响规则行为的一种声明式的方法,有些十分简单,而另一些是复杂子系统的一部分,如规则流。要从Drools中获得最大的收获,你必须十分的了解

37、每一个属性。no-loop默认值 : false类型 : Boolean当规则在推论中对fact进行修改后,可能会导致该规则的重新激活,引起递归。设置no-loop为true可以阻止该规则被再次激活。salience默认值 : 0类型 : integer每一个规则有一个整数类型的优先级属性,默认为0,这个整数可以使正负数。优先级数字高的规则会比优先级低的规则先执行。agenda-group默认值 : MAIN类型 : StringAgenda group允许用户对分隔Agenda执行区提供更多的控制。只有在具有焦点的agenda group中的规则才能够激发。auto-focus自动获取焦点默

38、认值 false类型 : Boolean当规则的auto-focus属性为true时,如果该规则符合激活条件,则该规则所在agenda-group自动获得焦点,允许规则激发。activation-group默认值 :N/A类型 : String在同名activation-group中的规则将以互斥的方式激发。这个意思时在这个组中第一条被激发的规则将取消其它规则的激发,即使它们已经在激发队列中。Activation-group属性可以是任何字符,只要所有你需要放在同一个组中的规则中的activation-group属性是相同的即可。dialect默认值 : 由Package指定 类型: Stri

39、ng可能值: java or mvelDialect指定在LHS代码表达式或RHS代码块中使用的语言。当前两种语言有效,Java和MVEL。Dialect可以在Package级别统一指定,而Rule属性中指定的dialect将局部覆盖掉Package中的定义。date-effective默认值 : N/A类型: String, 包含日期/时间定义规则只能在date-effective指定的日期和时间之后激活。date-exptires默认值 : N/A类型: String, 包含日期/时间定义如果当前时间在date-expires指定的时间之后,规则不能激活。duration默认值 : N/A

40、类型: longDuration指出规则将在指定的一段时间后激发,如果那个时候规则的激活条件还是处于true的情况下。LHS (when) 条件元素LHS是规则条件部分的常用名称。它包含0个或更多的条件元素。如果LSH是空的,那它被重写为eval(true),这意味着规则一直是true状态,并且将在working memory一建立时就被激发。Example:Rule Syntax Overview Examplerule no CEswhenthen *end在内部被重写为:rule no CEswhen eval( true )then *end条件元素工作在一种或多种模式下(将在下面介绍

41、)。常用的一种是“and”,它是当LHS中的多个条件元素之间没有任何连接时的默认情况。注意在“and”之前不能使用像“or”这样的声明,你想一下就知道这是必然的。一个声明只能指向一个单独的Fact,当and被满足是,它匹配超过一个fact哪一个是它绑定的fact呢?Pattern模式模式元素是条件元素中最重要的。下面的实体关系图给出了一个构建模式约束的不同部分以及它们是如何一起工作的一个概要图,每一个都会使用蓝图和例子详细说明。Figure6.11.模式实体关系图在ER图的最顶部,你可以看到模式包含0.n个约束,并且可以有一个可选的模式绑定。下面的蓝图显示了关于这点的语法。Figure6.12

42、.Pattern在最简单情况下,没有约束,它只是简单的匹配一个类型,下面的例子中这个类型是“Cheese”。这意味着模式将匹配working memory中的每一个Cheese对象。Example6.6.PatternCheese( )为了能够引用匹配的对象,使用一个模式绑定变量如$c。变量的前缀使用的$是可选的,但是在复杂的规则中它会很方便用来区别变量与字段的不同。Example6.7.Pattern$c : Cheese( )在模式的圆括号范围内是所有操作发生的地方。一个约束可以是字段约束,内部Eval(在3.0中称为断言)或一个约束组。约束之间可以使用,, & 或者 |符号分隔。Figu

43、re6.13.ConstraintsFigure6.14.ConstraintFigure6.15.Group Constraint逗号(,)被用来分隔约束组,它隐含着and的连接语法。Example6.8.逗号连接的约束组# Cheese 类型是stilton并且price 10并且age=mature.Cheese( type = stilton, price type = stiltongroup 2: price is less than 10 - price age = mature& (and) 和| (or)约束连接符允许约束组有多个约束,如:Example6.9.& 和| 约束

44、连接符Cheese( type = stilton & price 10, age = mature ) / Cheese type is stilton and price 10, and age is matureCheese( type = stilton | price 10, age = mature ) / Cheese type is stilton or price 10, and age is mature上面例子有两个约束组,第一个有两个约束而第二个组有一个约束。连接符按照以下顺序求值,从高到低:&|,在任何逻辑或数学表达式中,可以通过圆括号来改变求值的顺序。如:Examp

45、le6.10.使用圆括号改变求值优先级# Cheese type is stilton and ( price is less than 20 or age is mature ).Cheese( type = stilton & ( price 20 | age = mature ) ) 在上面的例子中,圆括号使得|连接符在&连接符之前被求值。要特别注意的是,&和逗号虽然有着同样的语义,但是逗号不能被包含在复杂的约束表达式中。Example6.11.不等价的连接Cheese( ( type = stilton, price 10 ) | age = mature ) / 无效!因为 , 不能

46、用于表达式绑定Cheese( ( type = stilton & price 60 ) Person( sex = m, age 65 ) 中缀or与圆括号一起使用。|符号作为or的同义操作,不推荐使用,只是因为历史的原因在语法中保留。Figure6.34.infixOrExample6.34.infixOrCheese( cheeseType : type ) or Person( favouriteCheese = cheeseType ) /infixOr(Cheese( cheeseType : type ) or (Person( favouriteCheese = cheeseT

47、ype ) and Person( favouriteCheese = cheeseType ) ) /infixOr with groupingor条件元素也允许使用模式绑定,这意味着每一个结果子规则将绑定它的模式到模式绑定。Example6.35.or with bindingpensioner : (or Person( sex = f, age 60 ) Person( sex = m, age 65 ) )也允许显式绑定每一个模式。(or pensioner : Person( sex = f, age 60 ) pensioner : Person( sex = m, age 65

48、 ) )or条件元素从多个规则中产生结果,称为子规则,对每一个可能的逻辑输出。上面的例子将在内部产生的两个规则中获得结果。这两个规则独立工作在Working Memory中,这意味着都可以进行匹配,激活和激发那里没有简捷的方式。最好的考虑方法是将OR条件元素看成产生两个额外规则的快捷方式。当你按照这种思路思考时,对于一个规则如果OR两边的条件都为true时能够被激活多次就很清晰了。evalFigure6.35.evalEval本质上是一个大杂烩(catch all),它允许任何语义代码被执行,只要最后返回一个boolean值。这可以涉及在规则LHS中绑定的变量和在规则Package中定义的函数

49、。使用eval可以减少规则的声明情况以及用一个低性能的引擎获得结果。eval可以在模式的任意位置使用,但最好的方式是作为规则LHS中最后的条件元素增加。Eval不能被索引,因此不能对使用eval的字段约束进行优化。因此最好只是在函数的返回值随时发生变化的情况下使用它。普通的字段约束中不能调用drools中定义的函数。对于熟悉Drools2.x体系的用户,旧的Drools参数和条件标签等同于绑定变量到适当的类型,然后在一个eval节点中使用它。Example6.36.evalp1 : Parameter() p2 : Parameter()eval( p1.getList().containsK

50、ey(p2.getItem() )eval( isValid(p1, p2) ) /只是如何在LHS中调用函数的方法 函数名是 isValidnotFigure6.36.notnot是一阶逻辑的存在判断量词,检查在Working Memory中某些Fact的存在性。括号是可选的。将not理解为那里必须没有任何。Example6.37.No Bussesnot Bus()Example6.38.No red Bussesnot Bus(color = red)not ( Bus(color = red, number = 42) ) /brackets are optionalnot ( Bus

51、(color = red) and Bus(color = blue) / not with nested and infix used here as ony two patternsexistsFigure6.37.existsexists是一阶逻辑的存在判断量词,检查在Working Memory中某些Fact的存在性。将exist理解为至少有一个。如果你将模式与exist一起使用,那么不管在working memory中有多少数据匹配约束,规则只激活一次。Example6.39.Atleast one Busexists Bus()Example6.40.Atleast one red

52、 Busexists Bus(color = red)exists ( Bus(color = red, number = 42) ) /brackets are optionalexists ( Bus(color = red) and Bus(color = blue) / exists with nested and infix used here as ony two patternsforallFigure6.38.forallForall条件元素在Drools中完全支持一阶逻辑。Forall条件元素在所有匹配最初模式的fact也同时匹配后面的模式的情况下为true。rule All

53、 english buses are redwhen forall( $bus : Bus( type = english) Bus( this = $bus, color = red ) )then # all english buses are redend在上面的规则中,我们选择所有类型为english的Bus对象,然后对每一个匹配的fact进行接下来的模式匹配,如果它们都匹配,则forall条件元素被求值为true。要声明在working memory中给定类型的所有fact必须匹配一组约束,forall可以简单的使用单模式。Example6.41.Single Pattern For

54、allrule All Buses are Redwhen forall( Bus( color = red ) ) / 这里省略了最初的Bus()模式then # all asserted Bus facts are redend上面的例子与下面的多重模式写法类同:Example6.42.Multi-Pattern Forallrule all employees have health and dental care programswhen forall( $emp : Employee() HealthCare( employee = $emp ) DentalCare( employ

55、ee = $emp ) )then # all employees have health and dental careendforall可以嵌套在其它条件元素中组成完整的表达式。例如:Example6.43.Combining Forall with Not CErule not all employees have health and dental carewhen not forall( $emp : Employee() HealthCare( employee = $emp ) DentalCare( employee = $emp ) )then # not all emplo

56、yees have health and dental careend作为一个边注,forall条件元素等价于写为:not( and not ( and ) )要注意的是forall是一个范围界定符,因此在它之前定义的变量都可以使用,但是在它之内绑定的变量不能用在外面。fromFigure6.39.from from条件元素允许你为模式声明一个推论的来源。这允许引擎使用不在Working Memory中的数据进行推论。源数据可能是绑定变量的子字段,或者方法调用的结果。它是一种强大的结构,允许在盒子(指Drools的运行环境)的外面与其它应用程序组件和框架集成。一个常见的例子是使用hibernate命名查询从数据库中返回需要的数据。用来定义对象源的表达式可以是任何符合MVEL语法的表达式。例如,它允许你容易的使用对象特性导航,执行方法调用以及访问映射和集合元素。这是绑定其它

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!