本⽂对Java规则引擎与其API(JSR-94)及相关实现做了较详细的介绍,对其体系结构和API应⽤有较详尽的描述,并指出Java规则引擎,规则语⾔,JSR-94的相互关系,以及JSR-94的不⾜之处和展望。
复杂企业级项⽬的开发以及其中随外部条件不断变化的业务规则(business logic),迫切需要分离商业决策者的商业决策逻辑和应⽤开发者的技术决策,并把这些商业决策放在中⼼数据库或其他统⼀的地⽅,让它们能在运⾏时(即商务时间)可以动态地管理和修改从⽽提供软件系统的柔性和适应性。规则引擎正是应⽤于上述动态环境中的⼀种解决⽅法。
本⽂第⼀部分简要介绍了规则引擎的产⽣背景和基于规则的专家系统,第⼆部分介绍了什么是规则引擎及其架构和算法,第三部分介绍了商业产品和开源项⽬实现等各种Java规则引擎,第四部分对Java规则引擎API(JSR-94)作了详细介绍,讲解了其体系结构,管理API和运⾏时API及相关安全问题,第五部分则对规则语⾔及其标准化作了探讨,第六部分给出了⼀个使⽤Java规则引擎API的简单⽰例,第七部分给予⼩结和展望。 1、 介绍
1.1 规则引擎产⽣背景
企业管理者对企业级IT系统的开发有着如下的要求:(1)为提⾼效率,管理流程必须⾃动化,即使现代商业规则异常复杂(2)市场要求业务规则经常变化,IT系统必须依据业务规则的变化快速、低成本的更新(3)为了快速、低成本的更新,业务⼈员应能直接管理IT系统中的规则,不需要程序开发⼈员参与。
⽽项⽬开发⼈员则碰到了以下问题:(1)程序=算法+数据结构,有些复杂的商业规则很难推导出算法和抽象出数据模型(2)软件⼯程要求从需求->设计->编码,然⽽业务规则常常在需求阶段可能还没有明确,在设计和编码后还在变化,业务规则往往嵌在系统各处代码中(3)对程序员来说,系统已经维护、更新困难,更不可能让业务⼈员来管理。
基于规则的专家系统的出现给开发⼈员以解决问题的契机。规则引擎由基于规则的专家系统中的推理引擎发展⽽来。下⾯简要介绍⼀下基于规则的专家系统。
1.2 基于规则的专家系统(RBES)
专家系统是⼈⼯智能的⼀个分⽀,它模仿⼈类的推理⽅式,使⽤试探性的⽅法进⾏推理,并使⽤⼈类能理解的术语解释和证明它的推理结论。专家系统有很多分类:神经⽹络、基于案例推理和基于规则系统等。
RBES包括三部分:Rule Base(knowledge base)、Working Memory(fact base)和Inference Engine(推理引擎)。它们的结构如下所⽰:
图1.基于规则的专家系统组成图1.基于规则的专家系统组成
如上图所⽰,推理引擎包括三部分:Pattern Matcher、Agenda和Execution Engine。Pattern Matcher何时执⾏哪个规则;Agenda管理PatternMatcher挑选出来的规则的执⾏次序;Execution Engine负责执⾏规则和其他动作。
推理引擎通过决定哪些规则满⾜事实或⽬标,并授予规则优先级,满⾜事实或⽬标的规则被加⼊议程。存在两者推理⽅式:演绎法(Forward-Chaining正向链)和归纳法(Backward-Chaining反向链)。演绎法从⼀个初始的事实出发,不断地应⽤规则得出结论(或执⾏指定的动作)。⽽归纳法则是从假设出发,不断地寻找符合假设的事实。 2、 规则引擎
2.1 业务规则
⼀个业务规则包含⼀组条件和在此条件下执⾏的操作,它们表⽰业务规则应⽤程序的⼀段业务逻辑。业务规则通常应该由业务分析⼈员和策略管理者开发和修改,但有些复杂的业务规则也可以由技术⼈员使⽤⾯向对象的技术语⾔或脚本来定制。业务规则的理论基础是:设置⼀个或多个条件,当满⾜这些条件时会触发⼀个或多个操作。 2.2 规则引擎
什么是规则引擎?规则引擎是如何执⾏规则的?这可以称之为\"什么\"与\"如何\"的问题。到底规则引擎是什么还是⽬前业界⼀个⽐较有争议的问题,在JSR-94种也⼏乎没有定义。可以这样认为充分定义和解决了\"如何\"的问题,\"什么\"问题本质上也迎刃⽽解。也许这⼜是⼀种\"先有蛋还是先有鸡\"哲学争论。今后标准规则语⾔的定义和推出及相关标准的制定应该可以给这样的问题和争论划上⼀个句号。本⽂中,暂且这样述说什么是规则引擎:规则引擎由推理引擎发展⽽来,是⼀种嵌⼊在应⽤程序中的组件,实现了将业务决策从应⽤程序代码中分离出
来,并使⽤预定义的语义模块编写业务决策。接受数据输⼊,解释业务规则,并根据规则做出业务决策。 2.3 规则引擎的使⽤⽅式
由于规则引擎是软件组件,所以只有开发⼈员才能够通过程序接⼝的⽅式来使⽤和控制它,规则引擎的程序接⼝⾄少包含以下⼏种
API:加载和卸载规则集的API;数据操作的API;引擎执⾏的API。开发⼈员在程序中使⽤规则引擎基本遵循以下5个典型的步骤:创建规则引擎对象;向引擎中加载规则集或更换规则集;向引擎提交需要被规则集处理的数据对象集合;命令引擎执⾏;导出引擎执⾏结果,从引擎中撤出处理过的数据。使⽤了规则引擎之后,许多涉及业务逻辑的程序代码基本被这五个典型步骤所取代。
⼀个开放的业务规则引擎应该可以\"嵌⼊\"在应⽤程序的任何位置,不同位置的规则引擎可以使⽤不同的规则集,⽤于处理不同的数据对象。此外,对使⽤引擎的数量没有。 2.4 规则引擎架构与推理 规则引擎的架构如下图所⽰:图2. 业务规则引擎架构图2. 业务规则引擎架构
规则引擎的推理步骤如下: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算法。
2.5 规则引擎的算法
⼤部分规则引擎产品的算法,基本上都来⾃于Dr. Charles Forgy在1979年提出的RETE算法及其变体,Rete算法是⽬前效率最⾼的⼀个Forward-Chaining推理算法,Drools项⽬是Rete算法的⼀个⾯向对象的Java实现,Rete算法其核⼼思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。
3、 Java规则引擎
⽬前主流的规则引擎组件多是基于Java和C++程序语⾔环境,已经有多种Java规则引擎商业产品与开源项⽬的实现,其中有的已经⽀持JSR94,有的正朝这个⽅向做出努⼒,列出如下: 3.1 Java规则引擎商业产品
Java规则引擎商业产品主要有(Jess不是开源项⽬,它可以免费⽤于学术研究,但⽤于商业⽤途则要收费):
3.2 Java规则引擎开源项⽬ 开源项⽬的实现主要包括:
Drools - Drools规则引擎应⽤Rete算法的改进形式Rete-II算法。从内部机制上讲,它使⽤了和Forgy的算法相同的概念和⽅法,但是增加了可与⾯向对象语⾔⽆缝连接的节点类型。
Mandarax 基于反向推理(归纳法)。能够较容易地实现多个数据源的集成。例如,数据库记录能⽅便地集成为事实集(factssets),reflection⽤来集成对象模型中的功能。⽬前不⽀持JSR 94
OFBiz Rule Engine - ⽀持归纳法(Backward chaining).最初代码基于Steven John Metsker的\"Building Parsers in Java\",不⽀持JSR 94 JLisa - JLisa是⽤来构建业务规则的强⼤框架,它有着扩展了LISP优秀特⾊的优点,⽐Clips还要强⼤.这些特⾊对于多范例软件的开发是⾄关重要的.⽀持JSR 94
其它的开源项⽬实现有诸如Algernon, TyRuBa, JTP, JEOPS, InfoSapient, RDFExpert, Jena 2, Euler, JLog, Pellet OWL Reasoner,Prova, OpenRules, SweetRules, JShop2等等。 4、 Java规则引擎API(JSR-94) 4.1 简介
过去⼤部分的规则引擎开发并没有规范化,有其⾃有的API,这使得其与外部程序交互集成不够灵活。转⽽使⽤另外⼀种产品时往往意味需要重写应⽤程序逻辑和API调⽤,代价较⼤。规则引擎⼯业中标准的缺乏成为令⼈关注的重要⽅⾯。2003年11⽉定稿并于2004年8⽉最终发布的JSR 94(Java规则引擎API)使得Java规则引擎的实现得以标准化。
Java规则引擎API由javax.rules包定义,是访问规则引擎的标准企业级API。Java规则引擎API允许客户程序使⽤统⼀的⽅式和不同⼚商的规则引擎产品交互,就像使⽤JDBC编写独⽴于⼚商访问不同的数据库产品⼀样。Java规则引擎API包括创建和管理规则集合的机制,在Working Memory中添加,删除和修改对象的机制,以及初始化,重置和执⾏规则引擎的机制。 4.2 简介Java规则引擎API体系结构
Java规则引擎API分为两个主要部分:运⾏时客户API(the Runtime client API)和规则管理API(the rules administration API)。 4.2.1规则管理API
规则管理API在javax.rules.admin中定义,包括装载规则以及与规则对应的动作(执⾏集 execution sets)以及实例化规则引擎。规则可以从外部资源中装载,⽐如说URI,Input streams, XML streams和readers等等.同时管理API提供了注册和取消注册执⾏集以及对执⾏集进⾏维护的机制。使⽤admin包定义规则有助于对客户访问运⾏规则进⾏控制管理,它通过在执⾏集上定义许可权使得未经授权的⽤户⽆法访问受控规则。
管理API使⽤类RuleServiceProvider来获得规则管理(RuleAdministrator)接⼝的实例.规则管理接⼝提供⽅法注册和取消注册执⾏集.规则管理器(RuleAdministrator)提供了本地和远程的RuleExecutionSetProvider.在前⾯已提及,RuleExecutionSetProvider负责创建规则执⾏集.规则执⾏集可以从如XML streams, input streams等来源中创建.这些数据来源及其内容经汇集和序列化后传送到远程的运⾏规则引擎的服务器上.⼤多数应⽤程序中,远程规则引擎或远程规则数据来源的情况并不多见.为了避免这些情况中的⽹络开销,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进⾏注册。注册⽅式类似于JDBC API的DriverManager和Driver。
运⾏时接⼝是运⾏时API的关键部分.运⾏时接⼝提供了⽤于创建规则会话(RuleSession)的⽅法,规则会话如前所述是⽤来运⾏规则的.运⾏时API同时也提供了访问在service provider注册过的所有规则执⾏集(RuleExecutionSets).规则会话接⼝定义了客户使⽤的会话的类型,客户根据⾃⼰运⾏规则的⽅式可以选择使⽤有状态会话或者⽆状态会话。
⽆状态会话的⼯作⽅式就像⼀个⽆状态会话bean.客户可以发送单个输⼊对象或⼀列对象来获得输出对象.当客户需要⼀个与规则引擎间的专⽤会话时,有状态会话就很有⽤.输⼊的对象通过addObject() ⽅法可以加⼊到会话当中.同⼀个会话当中可以加⼊多个对象.对话中已有对象可以通过使⽤updateObject()⽅法得到更新.只要客户与规则引擎间的会话依然存在,会话中的对象就不会丢失。
RuleExecutionSetMetaData接⼝提供给客户让其查找规则执⾏集的元数据(metadata).元数据通过规则会话接⼝(RuleSession Interface)提供给⽤户。
使⽤运⾏时Runtime API的代码⽚断如下所⽰:
RuleServiceProvider ruleProvider = RuleServiceProviderManager.getRuleServiceProvider (\"com.mycompany.myrulesengine.rules. RuleServiceProvider\"); RuleRuntime ruleRuntime = ruleProvider.getRuleRuntime();
StatelessRuleSession ruleSession = (StatelessRuleSession)ruleRuntime.createRuleSession(ruleURL, null, RuleRuntime.STTELESS_SESSION_TYPE); List inputRules = new ArrayList(); inputRules.add(new String(\"Rule 1\")); inputRules.add(new Integer(1));
List resultRules = ruleSession.executeRules(inputRules);
4.3 Java规则引擎API安全问题
规则引擎API将管理API和运⾏时API加以分开,从⽽为这些包提供了较好粒度的安全控制.规则引擎API并没有提供明显的安全机制,它可以和J2EE规范中定义的标准安全API联合使⽤.安全可以由以下机制提供,如Java authentication and authorization service (JAAS),the Java
cryptography extension (JCE),Java secure Socket Extension (JSSE),或者其它定制的安全API.JAAS能被⽤来定义规则执⾏集的许可权限,从⽽只有授权⽤户才能访问。 4.4 异常与⽇志
规则引擎API定义了javax.rules.RuleException作为规则引擎异常层次的根类.所有其它异常都继承于这个根类.规则引擎中定义的异常都是受控制的异常(checked exceptions),所以捕获异常的任务就交给了规则引擎。规则引擎API没有提供明确的⽇志机制,但是它建议将JavaLogging API⽤于规则引擎API。 4.5 JSR 94 ⼩结
JSR 94 为规则引擎提供了公⽤标准API,仅仅为实现规则管理API和运⾏时API提供了指导规范,并没有提供规则和动作该如何定义以及该⽤什么语⾔定义规则,也没有为规则引擎如何读和评价规则提供技术性指导.JSR 94规范将上述问题留给了规则引擎的⼚商.在下⼀节我将简要介绍⼀下规则语⾔。 5、 规则语⾔
JSR 94中没有涉及⽤来创建规则和动作的语⾔.规则语⾔是规则引擎应⽤程序的重要组成部分,所有的业务规则都必须⽤某种语⾔定义并且存储于规则执⾏集中,从⽽规则引擎可以装载和处理他们。
由于没有关于规则如何定义的公⽤规范,市场上⼤多数流⾏的规则引擎都有其⾃⼰的规则语⾔,⽬前便有许多种规则语⾔正在应⽤,因此,当需要将应⽤移植到其他的Java规则引擎实现时,可能需要变换规则定义,如将Drools私有的DRL规则语⾔转换成标准的ruleML,Jess规则语⾔转换成ruleML等。这个⼯作⼀般由XSLT转换器来完成。 规则语⾔的详情这⾥不作详细介绍,名称及其⽹址列出如下:
Rule Markup language (RuleML)
http://www.ruleml.org/ Simple Rule Markup Language (SRML)
http://xml.coverpages.org/srml.html Business Rules Markup Language (BRML)
http://xml.coverpages.org/brml.html SWRL: A Semantic Web Rule Language Combining OWL and RuleML http://www.daml.org/2003/11/swrl/
多种规则语⾔的使⽤使得不同规则引擎实现之间的兼容性成为问题.通⽤的规则引擎API或许可以减轻不同⼚家API之间的问题,但公⽤规则语⾔的缺乏将仍然阻碍不同规则引擎实现之间的互操作性.尽管业界在提出公⽤规则语⾔上做出了⼀些努⼒, ⽐如说RuleML,SRML的出现,但距离获得绝⼤部分规则引擎⼚商同意的公⽤标准还有很长的路要⾛。 6、 Java规则引擎API使⽤⽰例
6.1 设置规则引擎
Java规则引擎的管理活动阶段开始于查找⼀个合适的javax.rules.RuleServiceProvider对象,这个对象是应⽤程序访问规则引擎的⼊⼝。在J2EE环境中,你可能可以通过JNDI获得RuleServiceProvider。否则,你可以使⽤javax.rules.RuleServiceProviderManager类:
javax.rules.RuleServiceProviderManager class:
String implName = \"org.jcp.jsr94.ri.RuleServiceProvider\";Class.forName(implName);
RuleServiceProvider serviceProvider = RuleServiceProviderManager.getRuleServiceProvider(implName);
拥有了RuleServiceProvider对象,你就可以获得⼀个javax.rules.admin.RuleAdministrator类。从RuleAdministrator类中,你可以得到⼀个RuleExecutionSetProvider,从类名可以知道,它⽤于创建javax.rules.RuleExecutionSets对象。RuleExecutionSet基本上是⼀个装⼊内存的,准备好执⾏的规则集合。
包javax.rules.admin包括两个不同的RuleExecutionSetProvider类。RuleExecutionSetProvider类本⾝包括了从Serializable对象创建RuleExecutionSets的⽅法,因此在规则引擎位于远程服务器的情况下,仍然可以使⽤RuleExecutionSetProvider类,构造器的参数可以通过RMI来传递。另⼀个类是LocalRuleExecutionSetProvider,包含了其他⽅法,⽤于从⾮Serializable资源(如java.io.Reader-本地⽂件)创建RuleExectionSets。假设拥有了⼀个RuleServiceProvider对象,你可以从本地⽂件rules.xml⽂件创建⼀个RuleExectionSet对象。如以下的代码所⽰:
RuleAdministrator admin = serviceProvider.getRuleAdministrator(); HashMap properties = new HashMap(); properties.put(\"name\
properties.put(\"description\ FileReader reader = new FileReader(\"rules.xml\"); RuleExecutionSet ruleSet = null; try {
LocalRuleExecutionSetProvider lresp =admin.getLocalRuleExecutionSetProvider(properties); ruleSet = lresp.createRuleExecutionSet(reader, properties); } finally {
reader.close(); }
接下来,你可以使⽤RuleAdministrator注册获得的RuleExecutionSet,并给它分配⼀个名称。在运⾏时,你可以⽤同⼀个名称创建⼀个RuleSession;该RuleSession使⽤了这个命名的RuleExecutionSet。参见下⾯的⽤法:admin.registerRuleExecutionSet(\"rules\properties);
6.2 执⾏规则引擎
在运⾏时阶段,你可以参见⼀个RuleSession对象。RuleSession对象基本上是⼀个装载了特定规则集合的规则引擎实例。你从RuleServiceProvider得到⼀个RuleRuntime对象,接下来,从javax.rules.RuleRuntime得到RuleSession对象。
RuleSession分为两类:stateful和stateless。它们具有不同的功能。StatefulRuleSession的Working Memory能够在多个⽅法调⽤期间保存状态。你可以在多个⽅法调⽤期间在Working Memory中加⼊多个对象,然后执⾏引擎,接下来还可以加⼊更多的对象并再次执⾏引擎。相反,StatelessRuleSession类是不保存状态的,为了执⾏它的executeRules⽅法,你必须为Working Memory提供所有的初始数据,执⾏规则引擎,得到⼀个内容列表作为返回值。
下⾯的例⼦中,我们创建⼀个StatefulRuleSession实例,添加两个对象(⼀个Integer和⼀个String)到Working Memory,执⾏规则,然后得到Working Memory中所有的内容,作为java.util.List对象返回。最后,我们调⽤release⽅法清理RuleSession:
RuleRuntime runtime = rsp.getRuleRuntime();
StatefulRuleSession session = (StatefulRuleSession)runtime.createRuleSession(\"rules\ properties,RuleRuntime.STATEFUL_SESSION_TYPE); session.addObject(new Integer(1)); session.addObject(\"A string\"); session.executeRules();
List results = session.getObjects(); session.release();
7、 结束语
Java规则引擎API(JSR-94)允许客户程序使⽤统⼀的⽅式和不同⼚商的规则引擎产品交互,⼀定程度上给规则引擎⼚商提供了标准化规范。但其⼏乎没有定义什么是规则引擎,当然也没有深⼊到规则是如何构建和操纵的,规则调⽤的效⽤,规则与Java语⾔的绑定等⽅⾯。并且JSR-94在对J2EE的⽀持上也不⾜。规则语⾔的标准化,JSR-94的进⼀步的充实深化都有待研究。(转载⽂章请保留出处:)
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务