{{ v.name }}
{{ v.cls }}类
{{ v.price }} ¥{{ v.price }}
复杂企业级项目的开发以及其中随外部条件不断变化的业务规则(businesslogic),迫切需要分离商业决策者的商业决策逻辑和应用开发者的技术决策,并把这些商业决策放在中心数据库或其他统一的地方,让它们能在运行时(即商务时间)可以动态地管理和修改从而提供软件系统的柔性和适应性。规则引擎正是应用于上述动态环境中的一种解决方法。
本文第一部分简要介绍了规则引擎的产生背景和基于规则的专家系统,第二部分介绍了什么是规则引擎及其架构和算法,第三部分介绍了商业产品和开源项目实现等各种java规则引擎,第四部分对java规则引擎api(jsr-94)作了详细介绍,讲解了其体系结构,管理api和运行时api及相关安全问题,第五部分则对规则语言及其标准化作了探讨,第六部分给出了一个使用java规则引擎api的简单示例,第七部分给予小结和展望。
企业管理者对企业级it系统的开发有着如下的要求:(1)为提高效率,管理流程必须自动化,即使现代商业规则异常复杂(2)市场要求业务规则经常变化,it系统必须依据业务规则的变化快速、低成本的更新(3)为了快速、低成本的更新,业务人员应能直接管理it系统中的规则,不需要程序开发人员参与。
而项目开发人员则碰到了以下问题:(1)程序=算法+数据结构,有些复杂的商业规则很难推导出算法和抽象出数据模型(2)软件工程要求从需求->设计->编码,然而业务规则常常在需求阶段可能还没有明确,在设计和编码后还在变化,业务规则往往嵌在系统各处代码中(3)对程序员来说,系统已经维护、更新困难,更不可能让业务人员来管理。
基于规则的专家系统的出现给开发人员以解决问题的契机。规则引擎由基于规则的专家系统中的推理引擎发展而来。下面简要介绍一下基于规则的专家系统。
专家系统是人工智能的一个分支,它模仿人类的推理方式,使用试探性的方法进行推理,并使用人类能理解的术语解释和证明它的推理结论。专家系统有很多分类:神经网络、基于案例推理和基于规则系统等。
rbes包括三部分:rulebase(knowledgebase)、workingmemory(factbase)和inferenceengine(推理引擎)。它们的结构如下所示:
如上图所示,推理引擎包括三部分:patternmatcher、agenda和executionengine。patternmatcher何时执行哪个规则;agenda管理patternmatcher挑选出来的规则的执行次序;executionengine负责执行规则和其他动作。
推理引擎通过决定哪些规则满足事实或目标,并授予规则优先级,满足事实或目标的规则被加入议程。存在两者推理方式:演绎法(forward-chaining正向链)和归纳法(backward-chaining反向链)。演绎法从一个初始的事实出发,不断地应用规则得出结论(或执行指定的动作)。而归纳法则是从假设出发,不断地寻找符合假设的事实。
回页首
一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑。业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技术人员使用面向对象的技术语言或脚本来定制。业务规则的理论基础是:设置一个或多个条件,当满足这些条件时会触发一个或多个操作。
什么是规则引擎?规则引擎是如何执行规则的?这可以称之为"什么"与"如何"的问题。到底规则引擎是什么还是目前业界一个比较有争议的问题,在jsr-94种也几乎没有定义。可以这样认为充分定义和解决了"如何"的问题,"什么"问题本质上也迎刃而解。也许这又是一种"先有蛋还是先有鸡"哲学争论。今后标准规则语言的定义和推出及相关标准的制定应该可以给这样的问题和争论划上一个句号。本文中,暂且这样述说什么是规则引擎:规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据规则做出业务决策。
由于规则引擎是软件组件,所以只有开发人员才能够通过程序接口的方式来使用和控制它,规则引擎的程序接口至少包含以下几种api:加载和卸载规则集的api;数据操作的api;引擎执行的api。开发人员在程序中使用规则引擎基本遵循以下5个典型的步骤:创建规则引擎对象;向引擎中加载规则集或更换规则集;向引擎提交需要被规则集处理的数据对象集合;命令引擎执行;导出引擎执行结果,从引擎中撤出处理过的数据。使用了规则引擎之后,许多涉及业务逻辑的程序代码基本被这五个典型步骤所取代。
一个开放的业务规则引擎应该可以"嵌入"在应用程序的任何位置,不同位置的规则引擎可以使用不同的规则集,用于处理不同的数据对象。此外,对使用引擎的数量没有限制。
规则引擎的架构如下图所示:
规则引擎的推理步骤如下:a.将初始数据(fact)输入至工作内存(workingmemory)。b.使用patternmatcher将规则库(rulesrepository)中的规则(rule)和数据(fact)比较。c.如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。d.解决冲突,将激活的规则按顺序放入agenda。e.执行agenda中的规则。重复步骤b至e,直到执行完毕agenda中的所有规则。
任何一个规则引擎都需要很好地解决规则的推理机制和规则条件匹配的效率问题。
当引擎执行时,会根据规则执行队列中的优先顺序逐条执行规则执行实例,由于规则的执行部分可能会改变工作区的数据对象,从而会使队列中的某些规则执行实例因为条件改变而失效,必须从队列中撤销,也可能会激活原来不满足条件的规则,生成新的规则执行实例进入队列。于是就产生了一种"动态"的规则执行链,形成规则的推理机制。这种规则的"链式"反应完全是由工作区中的数据驱动的。
规则条件匹配的效率决定了引擎的性能,引擎需要迅速测试工作区中的数据对象,从加载的规则集中发现符合条件的规则,生成规则执行实例。1982年美国卡耐基·梅隆大学的charlesl.forgy发明了一种叫rete算法,很好地解决了这方面的问题。目前世界顶尖的商用业务规则引擎产品基本上都使用rete算法。
大部分规则引擎产品的算法,基本上都来自于dr.charlesforgy在1979年提出的rete算法及其变体,rete算法是目前效率最高的一个forward-chaining推理算法,drools项目是rete算法的一个面向对象的java实现,rete算法其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。详情请见cis587:theretealgorithm,theretealgorithm,rete演算法,《专家系统原理与编程》中第11章等。
回页首
目前主流的规则引擎组件多是基于java和c++程序语言环境,已经有多种java规则引擎商业产品与开源项目的实现,其中有的已经支持jsr94,有的正朝这个方向做出努力,列出如下:
java规则引擎商业产品主要有(jess不是开源项目,它可以免费用于学术研究,但用于商业用途则要收费):
开源项目的实现主要包括:
drools-drools规则引擎应用rete算法的改进形式rete-ii算法。从内部机制上讲,它使用了和forgy的算法相同的概念和方法,但是增加了可与面向对象语言无缝连接的节点类型。
mandarax基于反向推理(归纳法)。能够较容易地实现多个数据源的集成。例如,数据库记录能方便地集成为事实集(factssets),reflection用来集成对象模型中的功能。目前不支持jsr94
ofbizruleengine-支持归纳法(backwardchaining).最初代码基于stevenjohnmetsker的"buildingparsersinjava",不支持jsr94
jlisa-jlisa是用来构建业务规则的强大框架,它有着扩展了lisp优秀特色的优点,比clips还要强大.这些特色对于多范例软件的开发是至关重要的.支持jsr94
其它的开源项目实现有诸如algernon,tyruba,jtp,jeops,infosapient,rdfexpert,jena2,euler,jlog,pelletowlreasoner,prova,openrules,sweetrules,jshop2等等。
回页首
过去大部分的规则引擎开发并没有规范化,有其自有的api,这使得其与外部程序交互集成不够灵活。转而使用另外一种产品时往往意味需要重写应用程序逻辑和api调用,代价较大。规则引擎工业中标准的缺乏成为令人关注的重要方面。2003年11月定稿并于2004年8月最终发布的jsr94(java规则引擎api)使得java规则引擎的实现得以标准化。
java规则引擎api由javax.rules包定义,是访问规则引擎的标准企业级api。java规则引擎api允许客户程序使用统一的方式和不同厂商的规则引擎产品交互,就像使用jdbc编写独立于厂商访问不同的数据库产品一样。java规则引擎api包括创建和管理规则集合的机制,在workingmemory中添加,删除和修改对象的机制,以及初始化,重置和执行规则引擎的机制。
java规则引擎api分为两个主要部分:运行时客户api(theruntimeclientapi)和规则管理api(therulesadministrationapi)。
4.2.1规则管理api
规则管理api在javax.rules.admin中定义,包括装载规则以及与规则对应的动作(执行集executionsets)以及实例化规则引擎。规则可以从外部资源中装载,比如说uri,inputstreams,xmlstreams和readers等等.同时管理api提供了注册和取消注册执行集以及对执行集进行维护的机制。使用admin包定义规则有助于对客户访问运行规则进行控制管理,它通过在执行集上定义许可权使得未经授权的用户无法访问受控规则。
管理api使用类ruleserviceprovider来获得规则管理(ruleadministrator)接口的实例.规则管理接口提供方法注册和取消注册执行集.规则管理器(ruleadministrator)提供了本地和远程的ruleexecutionsetprovider.在前面已提及,ruleexecutionsetprovider负责创建规则执行集.规则执行集可以从如xmlstreams,inputstreams等来源中创建.这些数据来源及其内容经汇集和序列化后传送到远程的运行规则引擎的服务器上.大多数应用程序中,远程规则引擎或远程规则数据来源的情况并不多见.为了避免这些情况中的网络开销,api规定了可以从运行在同一jvm中规则库中读取数据的本地ruleexecutionsetprovider.
规则执行集接口除了拥有能够获得有关规则执行集的方法,还有能够检索在规则执行集中定义的所有规则对象.这使得客户能够知道规则集中的规则对象并且按照自己需要来使用它们。
4.2.2运行时api
运行时api定义在javax.rules包中,为规则引擎用户运行规则获得结果提供了类和方法。运行时客户只能访问那些使用规则管理api注册过的规则,运行时api帮助用户获得规则对话并且在这个对话中执行规则。
运行时api提供了对厂商规则引擎api实现的类似于jdbc的访问方法.规则引擎厂商通过类ruleserviceprovider(类ruleserviceprovider提供了对具体规则引擎实现的运行时和管理api的访问)将其规则引擎实现提供给客户,并获得ruleserviceprovider唯一标识规则引擎的url.
url推荐标准用法是使用类似"com.mycompany.myrulesengine.rules.ruleserviceprovider"这样的internet域名空间,这将有助于访问url的唯一性.类ruleserviceprovider内部实现了规则管理和运行时访问所需的接口.所有的ruleserviceprovider要想被客户所访问都必须用ruleserviceprovidermanager进行注册。注册方式类似于jdbcapi的drivermanager和driver。
运行时接口是运行时api的关键部分.运行时接口提供了用于创建规则会话(rulesession)的方法,规则会话如前所述是用来运行规则的.运行时api同时也提供了访问在serviceprovider注册过的所有规则执行集(ruleexecutionsets).规则会话接口定义了客户使用的会话的类型,客户根据自己运行规则的方式可以选择使用有状态会话或者无状态会话。
无状态会话的工作方式就像一个无状态会话bean.客户可以发送单个输入对象或一列对象来获得输出对象.当客户需要一个与规则引擎间的专用会话时,有状态会话就很有用.输入的对象通过addobject()方法可以加入到会话当中.同一个会话当中可以加入多个对象.对话中已有对象可以通过使用updateobject()方法得到更新.只要客户与规则引擎间的会话依然存在,会话中的对象就不会丢失。
ruleexecutionsetmetadata接口提供给客户让其查找规则执行集的元数据(metadata).元数据通过规则会话接口(rulesessioninterface)提供给用户。
使用运行时runtimeapi的代码片断如下所示: