﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Junky's IT Notebook-随笔分类-规则引擎</title><link>http://www.blogjava.net/junky/category/23629.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 28 Jun 2007 23:30:34 GMT</lastBuildDate><pubDate>Thu, 28 Jun 2007 23:30:34 GMT</pubDate><ttl>60</ttl><item><title>drools和spring的集成</title><link>http://www.blogjava.net/junky/archive/2007/06/28/126696.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Thu, 28 Jun 2007 00:57:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/06/28/126696.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/126696.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/06/28/126696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/126696.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/126696.html</trackback:ping><description><![CDATA[<div><strong>规则引擎简介</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎是推理引擎的一种，它起源于基于规则的专家系统。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎将业务决策从应用程序代码中分离出来，并使用预定义的语义模块编写业务决策。Java规则引擎接受数据输入，解释业务规则，并根据规则作出业务决策。从这个意义上来说，它是软件方法学在"关注点分离"上的一个重要的进展。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSR-94规范定义了独立于厂商的标准API，开发人员可以通过这个标准的API使用Java规则引擎规范的不同产品实现。但值得注意的是，这个规范并没有强制统一规则定义的语法，因此，当需要将应用移植到其他的Java规则引擎实现时，可能需要变换规则定义。</div>
<div><br><strong>基于规则的专家系统（RBES）<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 专家系统是人工智能的一个分支，它模仿人类的推理方式，使用试探性的方法进行推理，并使用人类能理解的术语解释和证明它的推理结论。专家系统有很多分类：神经网络、基于案例推理和基于规则系统等。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 规则引擎则是基于规则的专家系统的一部分。为了更深入的了解Java规则引擎，下面简要地介绍基于规则的专家系统（RBES）。</div>
<div align=left><br>&nbsp; <strong>RBES的技术架构<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RBES包括三部分：Rule Base（knowledge base）、Working Memory（fact base）和Rule Engine（推理引擎）。它们的结构如下所示：</div>
<div align=left>&nbsp;</div>
<div align=center><img onmousewheel="return bbimg(this)" title=点击新窗口查看大图 alt="" src="http://starrynight.blogdriver.com/diary/starrynight/inc/ruleengine.gif" width=200 onload="java_script_:if(this.width>200)this.width=200" border=0><br>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如上图所示，规则引擎包括三部分：Pattern Matcher、Agenda和Execution Engine。Pattern Matcher决定选择执行哪个规则，何时执行规则；Agenda管理PatternMatcher挑选出来的规则的执行次序；Execution Engine负责执行规则和其他动作。</div>
<div><br>&nbsp; <strong>RBES的推理（规则）引擎<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 和人类的思维相对应，规则引擎存在两者推理方式：演绎法（Forward-Chaining）和归纳法（Backward-Chaining）。演绎法从一个初始的事实出发，不断地应用规则得出结论（或执行指定的动作）。而归纳法则是从假设出发，不断地寻找符合假设的事实。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rete算法是目前效率最高的一个Forward-Chaining推理算法，Drools项目是Rete算法的一个面向对象的Java实现。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 规则引擎的推理步骤如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp;将初始数据（fact）输入Working Memory。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp;使用Pattern Matcher比较规则（rule）和数据（fact）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp;如果执行规则存在冲突（conflict），即同时激活了多个规则，将冲突的规则放入冲突集合。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.&nbsp;解决冲突，将激活的规则按顺序放入Agenda。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5.&nbsp;使用规则引擎执行Agenda中的规则。重复步骤2至5，直到执行完毕所有Agenda中的规则。</div>
<div><br><strong>JSR 94：Java规则引擎API</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基于规则编程是一种声明式的编程技术，这种技术让你可以使用试探性的规则而不是过程性的指令来解决问题。规则引擎是一个软件模块，它决定了如何将规则作用于推理数据。在保险业和金融服务业都广泛地使用了基于规则的编程技术，当需要在大量的数据上应用复杂的规则时，规则引擎技术特别有用。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎API由javax.rules包定义，是访问规则引擎的标准企业级API。Java规则引擎API允许客户程序使用统一的方式和不同厂商的规则引擎产品交互，就像使用JDBC编写独立于厂商访问不同的数据库产品一样。Java规则引擎API包括创建和管理规则集合的机制，在Working Memory中添加，删除和修改对象的机制，以及初始化，重置和执行规则引擎的机制。</div>
<div><br><strong>使用Java规则引擎API</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎API把和规则引擎的交互分为两类：管理活动和运行时活动。管理活动包括实例化规则引擎和装载规则。而运行时活动包括操作Working Memory和执行规则。如果你在J2SE环境中使用Java规则引擎，你可能需要在代码中执行以上所有的活动。相反，在J2EE环境中，Java规则引擎的管理活动是应用服务器的一部分。JSR 94的参考实现包括了一个JCA连接器，用于通过JNDI获得一个RuleServiceProvider。</div>
<div><br>&nbsp; <strong>设置规则引擎</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎的管理活动阶段开始于查找一个合适的javax.rules.RuleServiceProvider对象，这个对象是应用程序访问规则引擎的入口。在J2EE环境中，你可能可以通过JNDI获得RuleServiceProvider。否则，你可以使用javax.rules.RuleServiceProviderManager类：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javax.rules.RuleServiceProviderManager class: </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String implName = "org.jcp.jsr94.ri.RuleServiceProvider";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName(implName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleServiceProvider serviceProvider =&nbsp;RuleServiceProviderManager.getRuleServiceProvider(implName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一旦拥有了RuleServiceProvider对象，你可以获得一个javax.rules.admin.RuleAdministrator类。从RuleAdministrator类中，你可以得到一个RuleExecutionSetProvider，从类名可以知道，它用于创建javax.rules.RuleExecutionSets对象。RuleExecutionSet基本上是一个装入内存的，准备好执行的规则集合。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包javax.rules.admin包括两个不同的RuleExecutionSetProvider类。RuleExecutionSetProvider类本身包括了从Serializable对象创建RuleExecutionSets的方法，因此在规则引擎位于远程服务器的情况下，仍然可以使用RuleExecutionSetProvider类，构造器的参数可以通过RMI来传递。另一个类是LocalRuleExecutionSetProvider，包含了其他方法，用于从非Serializable资源（如java.io.Reader－本地文件）创建RuleExectionSets。假设拥有了一个RuleServiceProvider对象，你可以从本地文件rules.xml文件创建一个RuleExectionSet对象。如以下的代码所示：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleAdministrator admin = serviceProvider.getRuleAdministrator();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HashMap properties = new HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; properties.put("name", "My Rules");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; properties.put("description", "A trivial rulebase");</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileReader reader = new FileReader("rules.xml");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleExecutionSet ruleSet = null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; LocalRuleExecutionSetProvider lresp =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; admin.getLocalRuleExecutionSetProvider(properties);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ruleSet = lresp.createRuleExecutionSet(reader, properties);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reader.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来，你可以使用RuleAdministrator注册获得的RuleExecutionSet，并给它分配一个名称。在运行时，你可以用同一个名称创建一个RuleSession；该RuleSession使用了这个命名的RuleExecutionSet。参见下面的例子：<br>admin.registerRuleExecutionSet("rules", ruleSet, properties);</div>
<div><br>&nbsp; <strong>执行规则引擎</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在运行时阶段，你可以参见一个RuleSession对象。RuleSession对象基本上是一个装载了特定规则集合的规则引擎实例。你从RuleServiceProvider得到一个RuleRuntime对象，接下来，从javax.rules.RuleRuntime得到RuleSession对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleSession分为两类：stateful和stateless。它们具有不同的功能。StatefulRuleSession的Working Memory能够在多个方法调用期间保存状态。你可以在多个方法调用期间在Working Memory中加入多个对象，然后执行引擎，接下来还可以加入更多的对象并再次执行引擎。相反，StatelessRuleSession类是不保存状态的，为了执行它的executeRules方法，你必须为Working Memory提供所有的初始数据，执行规则引擎，得到一个内容列表作为返回值。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面的例子中，我们创建一个StatefulRuleSession实例，添加两个对象（一个Integer和一个String）到Working Memory，执行规则，然后得到Working Memory中所有的内容，作为java.util.List对象返回。最后，我们调用release方法清理RuleSession：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RuleRuntime runtime = rsp.getRuleRuntime();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StatefulRuleSession session = (StatefulRuleSession)<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; runtime.createRuleSession("rules", properties,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleRuntime.STATEFUL_SESSION_TYPE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.addObject(new Integer(1));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.addObject("A string");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.executeRules();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List results = session.getObjects();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.release();</div>
<div><br><strong>集成JSR 94产品实现<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 支持JSR 94规范的产品实现既有收费的商业产品，也有免费的开源项目。目前最为成熟，功能最强大的商业产品是ILOG公司的JRules，该公司也是JSR 94规范的积极推动者之一。支持JSR 94规范的开源项目目前很少，只有Drools和JLisa项目。值得注意的是，Jess不是开源项目，它可以免费用于学术研究，但用于商业用途则要收费。<br><br>&nbsp; <strong>JSR 94的产品实现</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java规则引擎商业产品有：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l. ILOG公司的JRules<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;BlazeSoft公司的Blaze<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp;Rules4J<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;Java Expert System Shell （JESS）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开源项目的实现包括：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l.&nbsp;Drools项目</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. JLisa项目<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;OFBiz Rule Engine（不支持JSR 94）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.&nbsp;Mandarax（目前不支持JSR 94）</div>
<div><br>&nbsp; <strong>使用Spring集成</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 集成Java规则引擎的目标是，使用标准的Java规则引擎API封装不同的实现，屏蔽不同的产品实现细节。这样做的好处是，当替换不同的规则引擎产品时，可以不必修改应用代码。<br>&nbsp; &nbsp; <strong>封装JSR94实现</strong></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RuleEngineFacade类封装Java规则引擎，使用ruleServiceProviderUrl和ruleServiceProviderImpl两个参数，屏蔽了不同产品的配置。代码如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public class RuleEngineFacade {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private RuleAdministrator ruleAdministrator;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private RuleServiceProvider ruleServiceProvider;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private LocalRuleExecutionSetProvider ruleSetProvider;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private RuleRuntime ruleRuntime;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // configuration parameters<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String ruleServiceProviderUrl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Class ruleServiceProviderImpl;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setRuleServiceProviderUrl(String url) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ruleServiceProviderUrl = url;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void setRuleServiceProviderImpl(Class impl) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ruleServiceProviderImpl = impl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void init() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;RuleServiceProviderManager.registerRuleServiceProvider(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruleServiceProviderUrl, ruleServiceProviderImpl);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ruleServiceProvider =&nbsp;RuleServiceProviderManager.getRuleServiceProvider(ruleServiceProviderUrl);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ruleAdministrator = ruleServiceProvider.getRuleAdministrator();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ruleSetProvider =&nbsp;ruleAdministrator.getLocalRuleExecutionSetProvider(null);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void addRuleExecutionSet(String bindUri,InputStream resourceAsStream)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throws Exception {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Reader ruleReader = new InputStreamReader(resourceAsStream);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;RuleExecutionSet ruleExecutionSet =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;ruleSetProvider.createRuleExecutionSet(ruleReader, null);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ruleAdministrator.registerRuleExecutionSet(bindUri,ruleExecutionSet,null);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public StatelessRuleSession getStatelessRuleSession(String key)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;throws Exception {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ruleRuntime = ruleServiceProvider.getRuleRuntime();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return (StatelessRuleSession) ruleRuntime.createRuleSession(key, null, RuleRuntime.STATELESS_SESSION_TYPE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public StatefulRuleSession getStatefulRuleSession(String key)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;throws Exception {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ruleRuntime = ruleServiceProvider.getRuleRuntime();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return (StatefulRuleSession) ruleRuntime.createRuleSession(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;key, null, RuleRuntime.STATEFUL_SESSION_TYPE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public RuleServiceProvider getRuleServiceProvider() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return this.ruleServiceProvider;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp;&nbsp; }</div>
<div><br>&nbsp;&nbsp;&nbsp; <strong>封装规则<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rule类封装了具体的业务规则，它的输入参数ruleName是定义规则的配置文件名，并依赖于RuleEngineFacade组件。代码如下：<br>&nbsp;&nbsp;&nbsp; public class Rule {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String ruleName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private RuleEngineFacade engineFacade;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void init() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream is = Rule.class.getResourceAsStream(ruleName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;engineFacade.addRuleExecutionSet(ruleName, is);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;is.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setRuleName(String name) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ruleName = name;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public void setEngineFacade(RuleEngineFacade engine) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.engineFacade = engine;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public StatelessRuleSession getStatelessRuleSession()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return engineFacade.getStatelessRuleSession(ruleName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public StatefulRuleSession getStatefuleRuleSession()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return engineFacade.getStatefulRuleSession(ruleName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }</div>
<div><br>&nbsp;&nbsp;&nbsp; <strong>组装规则组件</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 组装规则的配置文件如下：<br>&lt;bean id="ruleEngine" class="spring.RuleEngineFacade" init-method="init" singleton="false"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="ruleServiceProviderUrl"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;value&gt;http://drools.org/&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="ruleServiceProviderImpl"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;org.drools.jsr94.rules.RuleServiceProviderImpl&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;/property&gt;<br>&lt;/bean&gt;<br>&lt;bean id="fibonacci" class="spring.Rule" init-method="init"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="ruleName"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;/test/fibonacci.drl&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="engineFacade"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;ref local="ruleEngine"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br>&lt;/bean&gt;</div>
<div><br><strong>&nbsp;&nbsp;&nbsp; 测试用例</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后，我们编写测试用例，代码如下：<br>public class JSRTest extends TestCase {</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext ctx = null;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;protected void setUp() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.setUp();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ctx = new FileSystemXmlApplicationContext("testrule.xml");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public void testGetRuleSession() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rule rule = (Rule)ctx.getBean("fibonacci");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;assertNotNull(rule.getStatefuleRuleSession());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;assertNotNull(rule.getStatelessRuleSession());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void testStatelessRule() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;Rule rule = (Rule)ctx.getBean("fibonacci");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;Fibonacci fibonacci = new Fibonacci(50);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List list = new ArrayList();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;list.add(fibonacci);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;StatelessRuleSession session = rule.getStatelessRuleSession();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;session.executeRules(list);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;session.release();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void testStatefulRule() throws Exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rule rule = (Rule)ctx.getBean("fibonacci");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;Fibonacci fibonacci = new Fibonacci(50);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;StatefulRuleSession session = rule.getStatefuleRuleSession();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;session.addObject(fibonacci);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.executeRules();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;session.release();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行测试用例，出现绿条，测试通过。</div>
<div><br><strong>规则定义语言之间的变换</strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为JSR 94规范并没有强制统一规则定义的语法，因此，当需要将应用移植到其他的Java规则引擎实现时，可能需要变换规则定义，如将Drools私有的DRL规则语言转换成标准的ruleML，Jess规则语言转换成ruleML等。这个工作一般由XSLT转换器来完成。</div>
<br>
<img src ="http://www.blogjava.net/junky/aggbug/126696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-06-28 08:57 <a href="http://www.blogjava.net/junky/archive/2007/06/28/126696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>drools之helloworld</title><link>http://www.blogjava.net/junky/archive/2007/06/28/126697.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Thu, 28 Jun 2007 00:57:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/06/28/126697.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/126697.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/06/28/126697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/126697.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/126697.html</trackback:ping><description><![CDATA[所有项目都是被需求变更累死的，eXtreme Programing提供了一种哲学，一种态度，但更实际的，是那些能够应付需求变更的技术。 <br>比如用OLAP支持复杂报表的快速定制，用script语言如Groovy支持客户自定义公式， <br>还有Rule Engine，我们一天到晚挂在口上的亲爱的商业规则。 <br>Rule Engine并不新鲜，但通常只要一些名词已经足够把所有普通项目组震退，CLisp、Rete、前向推导.... 惟有Drools，终于把java和xml带回我们身边，让规则引擎简单到和JSP一样可以进入所有的程序组。 <br><br>先看一段精简又实用的HelloWorld，由两部分组成， 一个是调用规则的test.jsp ： <br><br>//设置一个测试用的VO <br>Vo vo = new Vo(); <br>vo.setPoStatus("A:draft"); <br><br>//读入规则 <br>RuleBase ruleBase = RuleBaseBuilder.buildFromURL("rule.drl"); <br><br>//把vo放入WorkingMemory中并执行 <br>WorkingMemory workingMemory = ruleBase.newWorkingMemory( ); <br>workingMemory.assertObject( vo ); <br>workingMemory.fireAllRules( ); <br><br>//显示结果 <br>out.print(po.getPoStatus()); <br><br>一个是规则文件rule.drl： <br><br>&lt;rule-set name="test rules" <br>&lt;rule name="Bob Likes Cheese"&gt; <br>&lt;parameter identifier="vo"&gt; <br>&lt;java:class&gt;com.ito.vo&lt;/java:class&gt; <br>&lt;/parameter&gt; <br><br>&lt;java:condition&gt;vo.getStatus().equals("A:draft")&lt;/java:condition&gt; <br><br>&lt;java:consequence&gt; <br>vo.setStatus("B:order"); <br>&lt;/java:consequence&gt; <br>&lt;/rule&gt; <br>&lt;/rule-set&gt; <br><br>整个规则分成三段， 第一段定义刚刚放入的对象； 第二段用Java语法判断条件； 第三段为条件符合时的执行语句 <br>真的非常简单吧 <br><br><br>经过小范围的试用，发现没有这么简单，因为Drools主要提供了一个RETE的规则匹配算法和一个Script Engine，具体怎么用，还很靠自己。如果drl文件的定义方式和RETE算法能够使条件的表达大大简化，那么它就是有用的。否则，一段重构后的代码能够达到和drl文件相仿的功能。所以，还是要多看点基础，把Business Rules用在正确的地方。 <br><br><br><br>提供一个eclipse的插件 url: http://www.zymose.com/index.html<br>
<img src ="http://www.blogjava.net/junky/aggbug/126697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-06-28 08:57 <a href="http://www.blogjava.net/junky/archive/2007/06/28/126697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Drools- 商务逻辑框架的选择</title><link>http://www.blogjava.net/junky/archive/2007/06/27/126646.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 27 Jun 2007 10:16:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/06/27/126646.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/126646.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/06/27/126646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/126646.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/126646.html</trackback:ping><description><![CDATA[<center>作者：保罗.布朗</center><br>
<center>译者:<a href="http://www.matrix.org.cn/user.shtml?username=greenbright" target=_new><u><font color=#0000ff>greenbright</font></u></a></center><br><br><br><br><br><span style="COLOR: red">版权声明：任何获得Matrix授权的网站，转载时请<strong><u>务必</u></strong>以超链接形式标明文章原始出处和作者信息及本声明</span><br>作者:保罗.布朗;<a href="http://www.matrix.org.cn/user.shtml?username=greenbright" target=_new><u><font color=#0000ff>greenbright</font></u></a><br>原文地址:<a href="http://www.onjava.com/pub/a/onjava/2005/08/03/drools.html" target=_new><u><font color=#0000ff>http://www.onjava.com/pub/a/onjava/2005/08/03/drools.html</font></u></a><br>中文地址:<a href="http://www.matrix.org.cn/resource/article/44/44046_Drools+Framework+Business.html" target=_new><u><font color=#800080>http://www.matrix.org.cn/resource/article/44/44046_Drools+Framework+Business.html</font></u></a><br>关键词： Drools Framework Business<br><br><br>大多数网络及企业级Jave应用可以分为三部分：和用户交互的前端，和后端系统（比如数据库）交互的服务层和这两部分之间的商务逻辑层。通常使用框架（像Struts, Cocoon, Spring, Hibernate, JDO, 和实体Beans）可以实现前端和后端的功能，但对于商务逻辑层却没有一个标准的构建方法。像EJB和Spring只能在高端实现商务逻辑构建，但却不能组织代码。如果我们使用在配置性，可读性和重用性方面带我们极大利益的框架代替那些纷繁复杂的if...then语句，那不是很好吗？在其他领域我们已经验证了这种利益。这篇文章建议使用<a href="http://www.drools.org/" target=_new><u><font color=#0000ff>Drools规则引擎</font></u></a>作为框架来解决问题。<br><br>下面的代码是我们试图避免的问题的例子。说明一个典型Java应用中的一些商务逻辑。<br>
<pre class=overflow>if ((user.isMemberOf(AdministratorGroup)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; user.isMemberOf(teleworkerGroup))<br>&nbsp;&nbsp;&nbsp;&nbsp; || user.isSuperUser(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 更多对特殊案例的检查<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if((expenseRequest.code().equals("B203")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ||(expenseRequest.code().equals("A903")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;(totalExpenses&lt;200)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;(bossSignOff&gt; totalExpenses))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp;(deptBudget.notExceeded)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //付款<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //检查许多其他的条件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>} else {<br>&nbsp;&nbsp;&nbsp;&nbsp; //更多商务逻辑<br>}</pre>
<br><br>我们都曾经历过相类似或者更为复杂的商务逻辑。当试图在Java中采用标准方法来实施商务逻辑时，就有很多问题随之而来。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果商务人员提出需要在本已很难理解的代码中加入另外一个表单（"C987"）怎么办？一旦所有的最初开发人员都在开发中，你愿意成为一个维护人员吗？<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如何确认这些规则的正确与否？对技术人员来说（从来不关注商务人员），检查规则的正确性是非常困难的。那么，有什么方法论来测试商务逻辑那？<br>许多应用有着类似的商务逻辑。如果其中一个规则发生了变化，我们能够确认所有系统中的相关部分都要改变吗？如果一个新应用使用了一些规则，但是也加入了一些新规则，我们需要彻底重写逻辑吗？ <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;商务逻辑嵌入在Java代码中，每次哪怕是很小的改变都需要再编译/再部署这些代码，这些商务逻辑容易配置吗?<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果其他的（脚本）语言想平衡现有投资在商务规则逻辑中怎么办？<br><br>J2EE/EJB和倒置控制的框架（像Spring, Pico和Avalon）让我们有能力在高端组织代码。他们很提供很好的重用性，配置性和安全性，但却不能替代上面例子中的<a href="http://en.wikipedia.org/wiki/Spaghetti_code" target=_new><u><font color=#0000ff>&#8220;意大利面条式代码&#8221;</font></u></a>。理想地，无论我们选择那个框架，不仅要和J2EE应用，而且要和通常Java编程(J2SE—标准版本)及广泛使用的表现和持续性框架相一致。这种框架让我们能够做到：<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;商务用户很容易的读和验证商务逻辑。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在应用中，商务规则是可重用的和可配置的。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在重负荷下，框架是可扩展的和性能良好的。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java编程人员对已存在的前端（Struts, Spring）和后端框架（对象关系映射）很容易使用这种框架。<br><br>另一个问题是在不同的应用中，组织页面，数据库访问和商务逻辑的方法也是多种多样的。我们的框架能够处理这个问题，并能始终提升代码的重用性。理想地，我们的应用使用&#8220;适用所有方式的框架&#8221;。以这种方式使用框架，能够让我们许多的应用构建的更好，让我们可以仅关注那些对用户更有价值的部分。<br><br><strong><span style="FONT-SIZE: 16px">规则引擎的营救</span></strong><br><br>如何解决这个问题那? 一个解决方案是使用规则引擎。规则引擎是组织商务逻辑的框架。它让开发者集中精力在他们有把握的事情上，而不是在一些低级机制上作决定。<br>通常，商务用户对那些能让他们理解是正确的事情感到更加舒服，相对于那些诸如用<span style="COLOR: blue">if...then </span>形式来表达的事情。你从商务专家那里听到的一些事情如下<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;10A表单用于申请超过200欧元的花费.&#8221;<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;我们仅对数量1万或超过1万的交易提供分成.&#8221;<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;超过10m英镑的采购需要公司总监的批准.&#8221;<br><br>通过关注于商务用户知道是正确的事情上，而不是怎样用Jave代码来表达它，上面的说明比以前我们的代码例子要清楚的多。尽管他们已经很清楚了，我们仍然需要一种机制，将这些规则应用到商务用户已知和作决定的事实中去。这种机制就是规则引擎。<br><br><span style="COLOR: red">相关文章：</span><br><a href="http://www.matrix.org.cn/resource/article/43/43782_Drools.html" target=_new><u><font color=#0000ff>在企业级Java应用中使用Drools</font></u></a><br>企业级Java应用开发者在表现和持续层有很多好的框架可供选择。但对于处在中间层的商务逻辑有好的框架吗？你希望每次经理给你一个新的命令就不得不重编译那些复杂的if ... then 意大利面条代码吗？这篇文章中，保罗布朗推荐的Drools的规则引擎或许是完成这类任务的最好选择。<br><br><strong><span style="FONT-SIZE: 16px">Jave规则引擎</span></strong><br><br><a href="http://javaboutique.internet.com/tutorials/rules_engine/" target=_new><u><font color=#0000ff>JSR 94</font></u></a>- javax.rules API制定了与规则引擎交互的通用标准，就像JDBC能够与各种类型的数据库交互。JSR-94并不是详细说明实际规则到底是怎么写的，而是最大限度的使用Java规则引擎来做这种详细说明。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Jess可能是最成熟的Java规则引擎，有很多好的工具（包括Eclipse）和文档。然而它是一个商业产品，并且它的规则是以序言样式符号写的，这对许多Java编程者都是一个挑战。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Jena是开源框架，始于HP.它有规则引擎，并且对那些关注于语义的网页特别支持。但它并不完全遵守JSR-94。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Drools是完全遵守JSR-94的规则引擎。而且是Apache模式许可下的完全开源框架。它不仅用大家熟知的Java 和XML语法来表示规则，而且有很强的用户和开发者团体。本文章中的例子中，我们将使用Drools。Drools使用像Java的语法，并且有最开放的许可。<br><br><strong><span style="FONT-SIZE: 16px">用Drools开始开发Java应用</span></strong><br><br>想象一下这种情景：就在读了这篇文章几分钟后，你的老板让你给股票交易应用建原型。尽管商务用户还没有定义好商务逻辑，一个可以想到的好主意就是用规则引擎来实现。最终的系统将通过网络访问，并且需要和后端数据库和信息系统交流。为了开始使用这个框架，需要下载Drools框架（有依赖性）。如图1所示，在你喜欢的IDE中建一个新项目并确保所有的.jars文件都被引用了。<br><br><img style="DISPLAY: inline" onclick=javascript:imgClick(this); alt=image src="http://www.matrix.org.cn/resource/upload/forum/2005_12_12_230601_HHjSitMOHT.gif" onload=javascript:imgLoad(this); border=0 resized="0"><br>图1。运行Drools必需的类库<br><br>由于潜在可能的巨大损失，如果我们的股票交易系统想要成功，在系统中循序渐进的使用一系列模拟器就显得很重要。这样的模拟器能够让你确信，即使规则改变了，由系统的作的决定也是正确的。我们将借用灵活工具箱的一些工具，并用JUnit框架作为模拟器。<br><br>如下例所示，我们所写的第一段代码是Junit测试/模拟器。尽管我们不能测试所有输入系统的值的组合，由测试总比什么都不测好。在这个例子中，所有的文档和classes（包括单元测试）又在一个文件夹/包中；但事实上，由应该创建合适的包和文件夹结构。在代码中，我们用Log4j代替System.out调用。<br><br><strong>清单1:</strong><br>
<pre class=overflow>import junit.framework.TestCase;<br>/*<br> * 应用中商务规则的JUnit测试<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* 这也扮演商务规则的&#8220;模拟器&#8220;-让我们说明输入，检验输出；并在代码发*布前看看是否达到我的期望值。<br>*/<br>public class BusinessRuleTest extends TestCase {<br>/**<br>*股票购买测试<br>*/<br>&nbsp;&nbsp;public void testStockBuy() throws Exception{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//用模拟值创建股票<br>&nbsp;&nbsp;&nbsp;&nbsp;StockOffer testOffer = new StockOffer();<br>&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockName("MEGACORP");<br>&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockPrice(22);<br>&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockQuantity(1000);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//运行规则<br>&nbsp;&nbsp;&nbsp;&nbsp;BusinessLayer.evaluateStockPurchase(testOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//达到我们的期望吗？<br>&nbsp;&nbsp;&nbsp;&nbsp;assertTrue(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.getRecommendPurchase()!=null);<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;assertTrue("YES".equals(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.getRecommendPurchase()));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp; }<br>}</pre>
<br><br>这是个基本Junit测试，我们知道这个简单系统应该买进所有价格低于100欧元的股票。很显然，没有数据类（StockOffer.java）和商务层类（BusinessLayer.java）这个测试用例是不能编译成功的。<br><br><strong>清单2:</strong><br>
<pre class=overflow>/**<br>*示例商务逻辑的正面<br>*这个简单示例里，所有的商务逻辑都包含在一个类中。<br>*但在现实中，按需要代理给其他的类。<br>*/<br>public class BusinessLayer {<br> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**<br>&nbsp;&nbsp; *评价购买这支股票是否是个好主意<br>&nbsp;&nbsp; *@参数 stockToBuy<br>&nbsp;&nbsp; *@return 如果推荐购买股票返回真，否则返回假<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public static void evaluateStockPurchase<br>&nbsp;&nbsp;&nbsp;&nbsp;(StockOffer stockToBuy){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br>&nbsp;&nbsp;}<br>}<br>StockOffer类如下所示：<br>/**<br>* 简单的JavaBean保存StockOffer值。<br>* 一个&#8217;股票出价&#8217;就是别人卖出股票（公司股份）所给出的价格。<br>*/<br>public class StockOffer {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;//常量<br>&nbsp;&nbsp;public final static String YES="YES";<br>&nbsp;&nbsp;public final static String NO="NO";<br><br>&nbsp;&nbsp;//内部变量<br>&nbsp;&nbsp;private String stockName =null;<br>&nbsp;&nbsp;private int stockPrice=0;<br>&nbsp;&nbsp;private int stockQuantity=0;<br>&nbsp;&nbsp;private String recommendPurchase = null;<br><br>/**<br>&nbsp;&nbsp; * @返回股票名称<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public String getStockName() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return stockName;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @参数 stockName 设置股票名称.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public void setStockName(String stockName) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.stockName = stockName;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @return 返回股票价格.<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public int getStockPrice() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return stockPrice;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @参数 stockPrice设置股票价格.<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public void setStockPrice(int stockPrice) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.stockPrice = stockPrice;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @return 返回股票数量.<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public int getStockQuantity() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return stockQuantity;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @参数 stockQuantity 设置股票数量.<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public void setStockQuantity(int stockQuantity){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.stockQuantity = stockQuantity;<br>&nbsp;&nbsp;}<br>/**<br>&nbsp;&nbsp; * @return 返回建议购买.<br>&nbsp;&nbsp; */<br><br>&nbsp;&nbsp;public String getRecommendPurchase() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return recommendPurchase;<br>&nbsp;&nbsp;}<br>}</pre>
<br><br>在我们熟悉的IDE的Junit中运行BusinessRuleTest。如果你不太熟悉Junit，可以从Junit网站获取更多信息。如图2所示，毫不奇怪的是，由于没有准备好适当的商务逻辑，测试在第二个申明处失败了。这个确信了模拟器/单元测试重点加强了他们应该有的问题。<br><br><img style="DISPLAY: inline" onclick=javascript:imgClick(this); alt=image src="http://www.matrix.org.cn/resource/upload/forum/2005_12_12_230733_CsZnSMdDeO.gif" onload=javascript:imgLoad(this); border=0 resized="0"><br>图2。Junit测试结果<br><br><strong><span style="FONT-SIZE: 16px">用规则描述商务逻辑</span></strong><br><br>现在，我们需要描述一些商务逻辑，像&#8220;如果股票价格低于100欧元，应该购买。&#8221;<br>这样我们将修改BusinessLayer.java为：<br><br><strong>清单3:</strong><br>
<pre class=overflow>import java.io.IOException;<br>import org.drools.DroolsException;<br>import org.drools.RuleBase;<br>import org.drools.WorkingMemory;<br>import org.drools.event.DebugWorkingMemoryEventListener;<br>import org.drools.io.RuleBaseLoader;<br>import org.xml.sax.SAXException;<br>/**<br>*示例商务逻辑的正面<br>*这个简单示例里，所有的商务逻辑都包含在一个类中。<br>*但在现实中，按需要代理给其他的类。<br>*@作者 缺省<br>*/<br>public class BusinessLayer {<br>//包含规则文件的名字<br>&nbsp;&nbsp;private static final String BUSINESS_RULE_FILE=<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"BusinessRules.drl";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//内部处理的规则基础<br>&nbsp;&nbsp;private static RuleBase businessRules = null;<br>/**<br>* 如果还没有装载商务规则的话就装载它。<br>*@抛出异常 -通常从这里恢复<br>*/<br>&nbsp;&nbsp;private static void loadRules()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws Exception{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (businessRules==null){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;businessRules = RuleBaseLoader.loadFromUrl(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BusinessLayer.class.getResource(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUSINESS_RULE_FILE ) );<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>/**<br>&nbsp;&nbsp; *评价是否购买这支股票<br>&nbsp;&nbsp; *@参数 stockToBuy<br>&nbsp;&nbsp; *@return 如果推荐购买股票返回真，否则返回假<br>&nbsp;&nbsp; *@抛出异常<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public static void evaluateStockPurchase<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (StockOffer stockToBuy) throws Exception{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//确保商务规则被装载<br>&nbsp;&nbsp;&nbsp;&nbsp;loadRules();<br>//一些程序进行的日志<br>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "FIRE RULES" );<br>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "----------" );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//了解以前运行的状态<br>&nbsp;&nbsp;&nbsp;&nbsp;WorkingMemory workingMemory <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= businessRules.newWorkingMemory();<br>//小规则集可以添加调试侦听器<br>&nbsp;&nbsp;&nbsp;&nbsp;workingMemory.addEventListener(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new DebugWorkingMemoryEventListener());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//让规则引擎了解实情<br>&nbsp;&nbsp;&nbsp;&nbsp;workingMemory.assertObject(stockToBuy);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//让规则引擎工作<br>&nbsp;&nbsp;&nbsp;&nbsp;workingMemory.fireAllRules();<br>&nbsp;&nbsp;}<br>}</pre>
<br><br>这个类有许多重要的方法：<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadRules()方法装载BusinessRules.drl文件中的规则。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;更新的evaluateStockPurchase()方法评价这些商务规则。这个方法中需要注意的是：<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;同一个RuleSet可以被重复使用（内存中的商务规则是无状态的）。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于以我们的知识我们知道什么是正确的，每次评价我们使用一个新的WorkingMemory类。在内存中用assertObject()方法存放已知的实事（作为Java对象）。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Drools有一个事件侦听模式，能让我们&#8220;看到&#8220;事件模式内到底发生了什么事情。在这里我们用它打印出调试信息。Working memory类的fireAllRules()方法让规则被评价和更新（在这个例子中，stock offer）。<br><br>再次运行例子之前，我们需要创建如下BusinessRules.drl文件：<br><br><strong>清单4:</strong><br>
<pre class=overflow>&lt;?xml version="1.0"?&gt;<br>&lt;rule-set name="BusinessRulesSample"<br>&nbsp;&nbsp;xmlns="http://drools.org/rules"<br>&nbsp;&nbsp;xmlns:java="http://drools.org/semantics/java"<br>&nbsp;&nbsp;xmlns:xs<br>&nbsp;&nbsp;&nbsp;&nbsp;="http://www.w3.org/2001/XMLSchema-instance"<br>&nbsp;&nbsp;xs:schemaLocation<br>&nbsp;&nbsp;&nbsp;&nbsp;="http://drools.org/rules rules.xsd<br>&nbsp;&nbsp;http://drools.org/semantics/java java.xsd"&gt;<br>&nbsp;&nbsp;&lt;!-- Import the Java Objects that we refer <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to in our rules --&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;java.lang.String<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.StockOffer<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;!-- A Java (Utility) function we reference <br>&nbsp;&nbsp;&nbsp;&nbsp;in our rules--&gt;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;java:functions&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;public void printStock(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.StockOffer stock)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Name:"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+stock.getStockName()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+" Price: "+stock.getStockPrice()&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+" BUY:"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+stock.getRecommendPurchase());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&lt;/java:functions&gt;<br>&lt;rule-set&gt;<br>&nbsp;&nbsp;&lt;!-- Ensure stock price is not too high--&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;rule name="Stock Price Low Enough"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Params to pass to business rule --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Conditions or 'Left Hand Side' <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LHS) that must be met for <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; business rule to fire --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- note markup --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getRecommendPurchase() == null<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockPrice() &lt; 100<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- What happens when the business <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rule is activated --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:consequence&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.setRecommendPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StockOffer.YES);&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printStock(stockOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;<br>&lt;/rule-set&gt;</pre>
<br><br>这个规则文件有几个有意思的部分：<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在XML-Schema定义被引入Java对象后，我们也把它引入到我们的规则中。这些对象来自于所需的Java类库。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;功能和标准的Java代码相结合。这样的话，我们就可以通过功能日志了解到底发生了什么。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;规则设置可以包括一个或多个规则。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;每条规则可以有参数（StockOffer类）。需要满足一个或多个条件，并且当条件满足时就执行相应的结果。<br><br>修改，编译了代码后，再运行Junit测试模拟器。这次，如图3所示，商务规则被调用了，逻辑评价正确，测试通过。祝贺—你已经创建了你的第一个基于规则的应用！<br><br><img style="DISPLAY: inline" onclick=javascript:imgClick(this); alt=image src="http://www.matrix.org.cn/resource/upload/forum/2005_12_12_231602_YUwJXgaqhC.gif" onload=javascript:imgLoad(this); border=0 resized="0"><br>图3。成功的Junit测试<br><br><strong><span style="FONT-SIZE: 16px">灵活的规则</span></strong><br><br>刚建好系统，你示范了上面的原型给商务用户，这时他们想起先前忘了给你提到几个规则了。新规则之一是当数量是负值时，不能够交易股票。你说&#8220;没问题，&#8221;，然后回到你的座位，借可靠的知识，你能迅速的改进系统。<br>第一件要做的事情是更新你的模拟器，把下面的代码加到BusinessRuleTest.java:<br><br><strong>清单5:</strong><br><br>
<pre class=overflow>/**<br>*测试买股票确保系统不接受负值<br>*/<br>&nbsp;&nbsp;public void testNegativeStockBuy() <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws Exception{<br>//用模拟值创建股票<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StockOffer testOffer = new StockOffer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockName("MEGACORP");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockPrice(-22);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.setStockQuantity(1000);<br>//运行规则<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BusinessLayer<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.evaluateStockPurchase(testOffer);<br>//是否达到我们的期望？<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertTrue("NO".equals(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.getRecommendPurchase()));<br>}</pre>
<br><br>这是为商务用户描述的新规则的测试。如果测试这个Junit测试，如预期的新测试失败了。我们需要加这个新规则到.drl文件中，如下所示。<br><br><strong>清单6:</strong><br>
<pre class=overflow>&lt;!-- Ensure that negative prices <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are not accepted--&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;rule name="Stock Price Not Negative"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Parameters we can pass into <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the business rule --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Conditions or 'Left Hand Side' (LHS) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; that must be met for rule to fire --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockPrice() &lt; 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- What happens when the business rule <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is activated --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:consequence&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.setRecommendPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StockOffer.NO);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printStock(stockOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;</pre>
<br><br>这个规则的和前一个类似，期望&lt;java:condition&gt;不同（测试负值）和&lt;java:consequence&gt;设置建议购买为No。再次运行测试/模拟器，这次测试通过。<br><br>这样的话，如果你习惯使用过程编程（象大多数Java 编程者），或许你会发愁挠头：一个文件包含两个独立的商务规则，而且我们也没有告诉规则引擎这两个规则哪个更重要。然而，股票价格（-22）也符合两个规则（它小于0也小于100）。不论如何，我们得到了正确的结果，即使交换规则的顺序。这是怎么工作的那？<br><br>下面控制台输出的摘录帮助我们明白到底发生了什么。我们看到两个规则都被触发了（[activationfired]行）并且Recommend Buy先被置为Yes然后被置为No。Drools是如何以正确的顺序来触发这些规则的那？如果你看Stock Price Low Enough规则，就会看到其中的一个条件recommendPurchase()是null.这就足以让Drools决定Stock Price Low Enough规则应该先于Stock Price Not Negative规则触发。这个过程就是冲突解决方案。<br><br><strong>清单7:</strong><br>
<pre class=overflow>FIRE RULES<br>----------<br>[ConditionTested: rule=Stock Price Not Negative; <br>&nbsp;&nbsp;condition=[Condition: stockOffer.getStockPrice() <br>&nbsp;&nbsp;&lt; 0]; passed=true; tuple={[]}]<br>[ActivationCreated: rule=Stock Price Not Negative; <br>&nbsp;&nbsp;tuple={[]}]<br>[ObjectAsserted: handle=[fid:2];<br>&nbsp;&nbsp; object=net.firstpartners.rp.StockOffer@16546ef]<br>[ActivationFired: rule=Stock Price Low Enough; <br>&nbsp;&nbsp; tuple={[]}]<br>[ActivationFired: rule=Stock Price Not Negative; <br>&nbsp;&nbsp; tuple={[]}]<br>Name:MEGACORP Price: -22 BUY:YES<br>Name:MEGACORP Price: -22 BUY:NO</pre>
<br><br>如果你是个过程编程者，无论你认为这是多聪明，你仍然不能完全的信任它。这是为什么我们使用单元测试/模拟器：&#8220;辛苦的&#8221;Junit测试（使用通用Java代码）保证规则引擎用我们关注的行来做决定。（不要花费上亿在一些无价值的股票上！）同时，规则引擎的强大和灵活性让我们能够迅速开发商务逻辑。<br>稍后，我们将看到更多冲突解决方案的经典的方式。<br><br><strong><span style="FONT-SIZE: 16px">冲突解决方案</span></strong><br><br>在商务这边，人们真的印象深刻并别开始通过可能的选择来思考。他们看到XYZ公司股票的问题并且决定执行一条新规则:如果XYZ公司的股价低于10欧元，就仅仅买XYZ公司的股票。<br>象上次，加测试到模拟器中，在规则文件中加入新的商务规则，如下所列。首先，在BusinessRuleTest.java中添加新方法。<br><br><strong>清单8:</strong><br>
<pre class=overflow>/**<br>*确保系统系统在XYZ公司股价便宜时就购买他们的股票<br>*/<br>public void testXYZStockBuy() throws Exception{<br>//用模拟值创建股票<br>&nbsp;&nbsp;StockOffer testOfferLow = new StockOffer();<br>&nbsp;&nbsp;StockOffer testOfferHigh = new StockOffer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;testOfferLow.setStockName("XYZ");<br>&nbsp;&nbsp;testOfferLow.setStockPrice(9);<br>&nbsp;&nbsp;testOfferLow.setStockQuantity(1000);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;testOfferHigh.setStockName("XYZ");<br>&nbsp;&nbsp;testOfferHigh.setStockPrice(11);<br>&nbsp;&nbsp;testOfferHigh.setStockQuantity(1000);<br>//运行规则<br>&nbsp;&nbsp;BusinessLayer.evaluateStockPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;testOfferLow);<br>&nbsp;&nbsp;assertTrue("YES".equals(<br>&nbsp;&nbsp;&nbsp;&nbsp;testOfferLow.getRecommendPurchase()));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;BusinessLayer.evaluateStockPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;testOfferHigh);<br>&nbsp;&nbsp;assertTrue("NO".equals(<br>&nbsp;&nbsp;&nbsp;&nbsp;testOfferHigh.getRecommendPurchase()));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>}</pre>
<br><br>然后，在BusinessRules.drl中加个新&lt;规则&gt;:<br><br><strong>清单10:</strong><br>&nbsp;&nbsp;
<pre class=overflow>&lt;rule name="XYZCorp" salience="-1"&gt;<br>&nbsp;&nbsp; &lt;!-- Parameters we pass to rule --&gt;<br>&nbsp;&nbsp; &lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp; &lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; stockOffer.getStockName().equals("XYZ")<br>&nbsp;&nbsp; &lt;/java:condition&gt; <br>&nbsp;&nbsp; &lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; stockOffer.getRecommendPurchase() == null<br>&nbsp;&nbsp; &lt;/java:condition&gt;<br>&nbsp;&nbsp; &lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; stockOffer.getStockPrice() &gt; 10<br>&nbsp;&nbsp; &lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp; &lt;!-- What happens when the business <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rule is activated --&gt;<br>&nbsp;&nbsp; &lt;java:consequence&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp; stockOffer.setRecommendPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StockOffer.NO);&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; printStock(stockOffer);<br>&nbsp;&nbsp; &lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;</pre>
<br><br>注意到商务规则文件中，规则名字后，我们设置salience为-1（比如，到现在我们说明的所有规则中的最低优先级）。系统冲突（意味着Drools在触发那个规则的顺序上作决定）的大多数规则给出了将达到的规则的条件。缺省的决定方法如下：.<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;显著性:如上列出的我们分配的值。 <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;崭新性：我们使用规则的次数。 <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;复杂性：第一次触发的更复杂的特定规则。 <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;装载顺序：那个规则被装载的顺序。<br>如果我们不说明这个例子中规则的显著性，将会发生的是： <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XYZ公司规则（&#8220;如果股票价格超过10欧元买XYZ&#8221;）将被首先触发（推荐买标记的状态被置为No）。 <br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后是更多的普通规则被触发（&#8220;买所有低于100的股票&#8221;），推荐买标记的状态被置为yes。<br><br>这将得到我们不期望的结果。然而，我们的例子设置了显著性因素，用例及商务规则就会如我们期望的运行了。<br><br>大多数情况下，书写清楚的规则且设置显著性将为Drools提供足够的信息来选择触发规则的顺序。有时，我们想整个的改变解决规则冲突的方式。以下是一个如何改变的例子，其中我告诉规则引擎首先触发最简单的规则。要注意的是，改变冲突解决方案是要小心，因为它能根本的改变规则引擎的规则—用清楚的写得恰当的规则能预先解决许多问题。<br><br><strong>清单11:</strong><br>
<pre class=overflow>//生成冲突解决者的列表<br>&nbsp;&nbsp;ConflictResolver[] conflictResolvers = <br>&nbsp;&nbsp;&nbsp;&nbsp;new ConflictResolver[] {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SalienceConflictResolver.getInstance(),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RecencyConflictResolver.getInstance(),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SimplicityConflictResolver.getInstance(),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LoadOrderConflictResolver.getInstance()<br>&nbsp;&nbsp;&nbsp;&nbsp;};<br>//包装成合成解决者<br>&nbsp;&nbsp;CompositeConflictResolver resolver = <br>&nbsp;&nbsp;&nbsp;&nbsp;new CompositeConflictResolver(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conflictResolvers); <br>//当装载规则时，说明这个解决者<br>&nbsp;&nbsp;businessRules = RuleBaseLoader.loadFromUrl(<br>&nbsp;&nbsp;&nbsp;&nbsp;BusinessLayer.class.getResource( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUSINESS_RULE_FILE),resolver);</pre>
<br><br>对于我们的简单的应用，由Junit测试驱动，我们不需要改变Drools解决规则冲突的方式。了解冲突解决方案是如何工作的对我们是非常有帮助的，尤其是当应用需要满足更复杂根严格的需求试。<br><br><strong><span style="FONT-SIZE: 16px">结论</span></strong><br><br>这篇文章论证了许多编程者遇到过的问题：如何定制复杂的商务逻辑。我们示范了一个用Drools为解决方案的简单应用并介绍了基于规则编程的概念，包括在运行时这些规则是如何被处理的。稍后，接下来的文章将以这些为基础来展示在企业级Java应用中是如何使用它的。<br><br><br><span style="FONT-SIZE: 16px"><strong>资源</strong></span><br>&#183;下载例子所有源代码:<a href="http://sourceforge.net/project/showfiles.php?group_id=99476&amp;package_id=158438" target=_new><u><font color=#0000ff>源代码</font></u></a><br>&#183;Matrix-Java开发者社区:<a href="http://www.matrix.org.cn/" target=_new><u><font color=#0000ff>http://www.matrix.org.cn</font></u></a><br>&#183;onjava.com:<a href="http://onjava.com/" target=_new><u><font color=#0000ff>onjava.com</font></u></a><br>&#183;<a href="http://www.drools.org/" target=_new><u><font color=#0000ff>Drools项目主页</font></u></a><br>&#183;<a href="http://www.jroller.com/page/eu/20040810" target=_new><u><font color=#0000ff>Drools规则信息</font></u></a><br>&#183;<a href="http://www.theserverside.com/articles/article.tss?l=Drools" target=_new><u><font color=#0000ff>&#8220;Drools和规则引擎介绍&#8221;由Drools项目领导 </font></u></a><br>&#183;<a href="http://www.geocities.com/CapitolHill/5910/drltk/instructions.htm" target=_new><u><font color=#0000ff>Drools规则计划文件</font></u></a><br>&#183;<a href="http://javaboutique.internet.com/tutorials/rules_engine/" target=_new><u><font color=#0000ff>JSR-94, Java规则引擎，概略 </font></u></a><br>&#183;<a href="http://herzberg.ca.sandia.gov/jess/index.shtml" target=_new><u><font color=#0000ff>Jess Jave规则引擎</font></u></a><br>&#183;<a href="http://jena.sourceforge.net/" target=_new><u><font color=#0000ff>Jena语义和规则引擎</font></u></a><br>&#183;<a href="http://jcp.org/aboutJava/communityprocess/review/jsr094/" target=_new><u><font color=#0000ff>JSR-94主页</font></u></a><br>&#183;<a href="http://www.manning.com/friedman-hill" target=_new><u><font color=#0000ff>Jess在Action主页</font></u></a><br>&#183;<a href="http://herzberg.ca.sandia.gov/jess/zen.shtml" target=_new><u><font color=#0000ff>&#8220;商务规则思想&#8221;（基于Jess）</font></u></a> <br>&#183;<a href="http://www.aaai.org/AITopics/html/expert.html" target=_new><u><font color=#0000ff>&#8220;规则系统的一般介绍&#8221; </font></u></a><br>&#183;<a href="http://herzberg.ca.sandia.gov/jess/docs/61/rete.html" target=_new><u><font color=#0000ff>&#8220;Rete算法的Jess执行&#8221;</font></u></a><br><br>保尔 布朗已经通过FirstPartners.net网站为企业级Java咨询了约7年的时间。<br>
<img src ="http://www.blogjava.net/junky/aggbug/126646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-06-27 18:16 <a href="http://www.blogjava.net/junky/archive/2007/06/27/126646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在你的企业级java应用中使用Drools</title><link>http://www.blogjava.net/junky/archive/2007/06/27/126645.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 27 Jun 2007 10:09:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/06/27/126645.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/126645.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/06/27/126645.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/126645.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/126645.html</trackback:ping><description><![CDATA[<span style="COLOR: purple">版权声明</span>：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明<br>原文地址:<br><a href="http://www.onjava.com/pub/a/onjava/2005/08/24/drools.html" target=_new><u><font color=#0000ff>http://www.onjava.com/pub/a/onjava/2005/08/24/drools.html</font></u></a><br>中文地址:<br><a href="http://www.matrix.org.cn/resource/article/43/43782_Drools.html" target=_new><u><font color=#0000ff>http://www.matrix.org.cn/resource/article/43/43782_Drools.html</font></u></a><br>关键词： Drools J2ee<br><br><br><strong><span style="FONT-SIZE: 16px">什么是Drools</span></strong><br>(译者增加：什么是Drools, 摘自drools.org)<br>Drools 是一个基于Charles Forgy's的Rete算法的，专为Java语言所设计的规则引擎。Rete算法应用于面向对象的接口将使基于商业对象的商业规则的表达更为自然。Drools是用Java写的，但能同时运行在Java和.Net上。<br><br><strong>Drools</strong><br>Drools 被设计为可插入式的语言实现。目前规则能用Java, Python和Groovy实现。更为重要的是，Drools提供了声明式程序设计(Declarative Programming),并且使用域描述语言(Domain Specific Languages (DSL))－专为你的问题域定义了某种模式的Xml, 它已经足够灵活到可以用来描述你的问题域。DSLs包含的XML元素(Element)和属性(Attribute)代表了问题域中各种要素。<br><br>(原文开始)<br>这 段时间企业级Java简直能让你睡着。有多少J2EE-EJB应用程序只是从网页提取数据并把它们存入到数据库中?但开发者真正应该开发和维护的却是他们 应用程序中复杂的商业逻辑。这个问题不仅仅适用于将要新应用，而且渐渐地，也适用于那些长期运行的商业核心应用，它们的内部逻辑也需要经常改变，而且往往 要求在一个非常短的时间内。<br><br>在以前的文章中，&#8220;用Drools让你的商业逻辑使用框架&#8221;,我介绍了Drools框架，展示了它如何用来组 织复杂的商业逻辑。Drool用一组简单的，众所周知的事物替换了许多缠杂的if&#8230;then表达式。如果你经历过和商业客户的会议，并为他们提出的想要实 现的东西的复杂程度搞得头痛，或许你应该考虑一下像Drools这样的规则引擎了。这篇文章将向你展示如何在企业级Java应用中使用Drools.<br><br><strong><span style="FONT-SIZE: 16px">一路到底的框架</span></strong><br><br>大 多数开发者都有自己喜爱的框架。无特定顺序，它们包括表现层框架（Struts, JSF, Cocoon和Spring）,持久化框架（JDO, Hibernate, Cayenne and Entity Beans）以及结构框架(EJB, 又是Spring, Pico和Excalibur), 还有其它很多。每种框架都各有所长，给开发者提供子许多&#8220;即开即用&#8221;的功能。使用框架来部署应用意味着你避免了许多让人厌烦的细节，让你集中注意力到关键 之处。<br>到目前为直，在框架所能做的事中仍然有一个缺口，那就是商业逻辑没有框架。像EJB和Spring这样的工具虽好，但它们却几乎没有提及怎 么组织你的那些if &#8230;then语句。把Drools加到你的开发工具箱中意味着现在你可以&#8220;一路到底&#8221;的使用框架来构建你的应用程序。图1显示了这样的一个应用<br><br><img style="DISPLAY: inline" onclick=javascript:imgClick(this); alt=image src="http://www.matrix.org.cn/resource/upload/content/2005_09_19_001100_GUdrMLtFaq.gif" onload=javascript:imgLoad(this); border=0> <br>图1. 用于Java应用的框架<br><br>这篇文章将基于我们已经了解的Drools框架的功能，这些功能可以让我们构建这样的一个应用。]<br><br><strong><span style="FONT-SIZE: 16px">我什么时候应该使用规则引擎？</span></strong><br>&#8220;如果你有一把锤子，那所有的东西都看起来都像钉子&#8221;，这句话在软件工程领域几乎成了陈词滥调了。虽然规则引擎能解决我们的许多问题，但确实值得认真考虑一下规则引擎对我们的企业级Java应用是否合适。需要问的问题有：<br><br>● <strong>我的应用程序有多复杂?</strong>对于那些只是把数据从数据库中传入传出，并不做更多事情的应用程序，最好不要使用规则引擎。但是，当在Java中有一定量的商业逻辑处理的话，可以考虑Drools的使用。这是因为很多应用随着时间的推移越来越复杂，而Drools可以让你轻松应对这一切。<br><br>● <strong>我的应用的生命周期有多久？</strong>这个问题的正确答案往往是&#8220;令人惊讶的长&#8221;――还记得那些认为他们的程序不会苟活到2000年的大型机的程序员吗？使用规则引擎将会在中长期得到好处。像这篇文章所展示的那样，甚至原型都能从Drools与灵活方法的组合中获益，让&#8220;原型系统&#8221;转化成生产系统。<br><br>● <strong>我的应用需要改变吗？</strong>唯一能确定的是你的需求将会改变，无论是在开发过程中或是在开发完成以后。Drools使用一个或多个简单易配的XML文件帮你来应对这一切。<br><br><strong><span style="FONT-SIZE: 16px">那么性能呢？</span></strong><br>如 果你正在写一个企业级应用，很有可能它会扩展到成百（如果不是成千）的用户。你已经知道现有的Java和J2EE应用能做到这一点，但一个使用了 Drools的应用对这一压力的表现如何？答案是：&#8220;令人吃惊的好&#8221;。大多数开发者只是因为不愿&#8220;失控&#8221;而依赖于他人的代码（比如：某种框架），想想这 个：Drools不仅可以让你的应用和&#8220;传统&#8221;的编程方法一样快，甚至可以更快,看下面：<br><br>● <strong>避免糟糕的代码</strong>：Drools引导开发者去做&#8220;正确的事&#8221;。你可以确定你正在写的代码是好的，但你的开发伙伴呢？你可以同样这样说吗？使用框架可以让你更轻松地写出更快，更好的代码。<br><br>● <strong>优化过的框架</strong>：你有多少次看见商业逻辑重复地从数据库中提取相同的信息，从而降低了整个应用的速度？如果正确使用的话，Drools不仅仅能够记住信息，而且还能记住以往使用该信息进行测试的结果，从而大幅提升应用的速度。<br><br>● <strong>Rete算法</strong>： 很多次我们并不是真正需要使用&#8220;if&#8221;条件。被Drools实现的Rete算法，可以用一个优化的方法替换掉所有的&#8220;if&#8230;then&#8221;表达式。需要重点提 及的是：Rete算法在使用更多的内存来降低运行时延迟方面作了折衷。当然这在现代的应用服务器中并不是一个问题，我们也并不推荐你在移动手机上使用 Drools!<br><br><strong><span style="FONT-SIZE: 16px">我们到哪里了？</span></strong><br><br>在 我们上一篇文章中，我们写了一个基于Drools引擎的简单的股票交易程序。我们实现了不同的商业规则，展示了我们可以如何迅速地改变规则去适应商业需 求，并且JUnit测试给了我们高度自信可以确认系统确实是像我们设想的那样运作的。但是这个应用几乎没有用户介面，而且用硬编码代替了数据库。为了把我 们的程序提升到企业级的水平，我们需要增加两个主要的东西。<br><br>● 某种用户介面，最理想的是基于标准的Web表现层的框架。<br>● 一个数据存取对象(DAO)让Drools与数据库（或其它后端）交互。<br><br><strong>从现有表现框架中实现规则引擎</strong><br><br>大 多数企业级Java应用是通过Web介面进行交互的，其中最被广泛使用的Web表现层框架是Apache的Struts。理想的结果是：我们写的应用可以 从表现层知道它下面的应用层,而不是通过相反的方向。它的好处在于不仅仅可以使我们将来变换其它的表现层（比如Ajax或web service界面），而且意味着示例代码可以非常容易地应用于其它像Spring的框架。<br><br>下面的代码片断演示了始何从Web表现层调用 商业逻辑（通过规则引擎），并根据返回结果显示不同的页面。这一例子中，我们使用了一个Struts行为，但其代码是和使用其它表现层框架甚至一个 Servlet或一个Jsp页面是很类似的。这个片断使用了struts-config.xml配置文件，JSP页面来上传/显示数据，并且生成WAR文 件来进行布署。片断展示了怎样把规则引擎和web框架集成使用。<br><br>
<pre class=overflow>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import org.apache.struts.action.Action;<br>import org.apache.struts.action.ActionForm;<br>import org.apache.struts.action.ActionForward;<br>import org.apache.struts.action.ActionMapping;<br>import BusinessLayer;<br>/**<br> * Sample Struts action with Pseudocode<br> * 使用伪代码的Struts行为示例<br> */<br>public class SampleStrutsAction extends Action{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Standard Struts doPerfom method <br>&nbsp;&nbsp; * 标准的Struts doPerform方法<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public ActionForward doPerform(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionMapping mapping,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionForm form,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest request,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse response)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws InvalidEntryPointException {<br>//Local Variables<br>//本地变量<br>&nbsp;&nbsp;&nbsp;&nbsp;StockOffer userOffer =null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//Get any previous values from the session<br>//从session取得以前的数据<br>&nbsp;&nbsp;&nbsp;&nbsp;userOffer=(StockOffer)request.getSession()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getAttribute("PREVIOUS_STOCK_OFFER");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//create this object if it is null<br>//如为null则创建新对象<br>&nbsp;&nbsp;&nbsp;&nbsp;if (null==userOffer){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userOffer = new StockOffer();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>//Update with the incoming values <br>//用上送的数据更新<br>//These values match those on the form&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//这些数据是与form中的数据相对应的<br>&nbsp;&nbsp;&nbsp;&nbsp;userOffer.setStockName(request.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getParameterValue("STOCK_NAME"));<br>&nbsp;&nbsp;&nbsp;&nbsp;userOffer.setStockPrice(request<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getParameterValue("STOCK_PRICE"));<br>&nbsp;&nbsp;&nbsp;&nbsp;userOffer.setStockQuantity(request<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getParameterValue("STOCK_QTY"));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//Reset the output value<br>//重置输出数据<br>&nbsp;&nbsp;&nbsp;&nbsp;userOffer.setRecommendPurchase(null);<br>//Call the Business Layer<br>//调用商业层<br>&nbsp;&nbsp;&nbsp;&nbsp;BusinessLayer<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.evaluateStockPurchase(userOffer);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//Forward to the appropriate page <br>//转向合适的页面<br>&nbsp;&nbsp;&nbsp;&nbsp;if ("YES".equals(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testOffer.getRecommendPurchase()){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mapping.findForward("YES_WEB_PAGE");<br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>//otherwise default to the no page<br>//否则指向无此页面<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return mapping.findForward("NO_WEB_PAGE");<br>&nbsp;&nbsp;}<br>}</pre>
<br><br>这个例子包含了几个东西。经常，我们需要的数据是用户通过好几个网页传来的，因此在这一例子中展示了通过session中的StockOffer对象来保存过去以来的数据。<br><br>下一步，如果用户改变了一些值，我们更新StockOffer对象。然后我们重置了rcommendPurchase标志用以在调用商业逻辑层之前清除以前的结果。最后我们使用商业逻辑层的返回来决定让用户转向哪一页面。<br><br>在 这一例子中，需要注意我们将商业逻辑（买或不买一支股票）与表现层逻辑（决定转向哪一页面）分离开来。这将使我们可以在不同的应用中重用我们的商业规则。 另外，看一下状态信息（用户已经告知我们的东西）是存储在Session中的StockOffer对象中的，并没有在商业层中。这样就保证了商业层的无状 态性，这将使整个应用更具扩展性和性能。<br><br><strong><span style="FONT-SIZE: 16px">集成规则引擎与数据库层</span></strong><br><br>到 目前为止，我们的应用已经有一个web表现层和一个商业层的规则引擎，但还没有方法与数据库进行交互。这一节的例子将展示如何实现。我们的例子是基于数据 访问对象（DAO）模式的，它把所有与数据库（或后端数据源）交互的代码包装在了一个可插入，可配置的类中。同样的，这一例子一样适用于其它持久性框　 架，比如Hibernate和Cayenne。<br>关于如何组织数据导有几个要点：<br><br>● 应该只有商业层与数据层交互。如果表现层（前端）需要一些数据，它首先应通过商业层。这将使我们的代码更容易组织和阅读。<br>● 尽可能地，我们应让我们的数据层无状态－我们应该在其它的地方存放客户端数据（比如：web前端的session，就像前面的例子）。这不同于我们可以在 这一层做的数据缓存。两者的区别在于状态信息经常是用户定义的，而我们在数据层缓存的数据应该是整个应用共享的。这样的层次提升了性能。<br>● 我们应该让商业逻辑决定数据是否需要――如不需要，提取数据的调用就不应该执行。<br><br>为了实现我们简单的数据访问对象，我们创建三个新对象：StockNameDao, DaoImplementation,和 DaoFactory<br><br>StockNameDao是一个定义了两个方法的接口：getStockName()返回一个我们可以处理的股票名称的列表,isOnStockList()检查一个给定的股票是否在处理列表中。我们的商业层在需要这些信息时会调用这些方法。<br><br>DaoImplementation是StockNameDao的一个实现。这里的数据是硬编码的，但我们可以通过查询数据库或通过像Bloomberg这样的web service提取信息。<br><br>DaoFactory 我们用来生成合适的StockNameDao实例。不直接创建对象而使用这一小骤的好处在于，它充许我们在运行时刻决定使用哪一个DAO实现（这是像 Spring这样的框架特别擅长的）.一个factory（工厂）可以返回多种类型的DAO(比如：StockNameDao, StockPriceDao, StockHistoryDao),这意味着我们可以通过我们的DaoFactory,让规则自己决定需要什么数据和DAO.<br><br>这是StockNameDao接口：<br><br>
<pre class=overflow>/**<br> * Defines a Data Access Object - a non data <br> * source specific way of obtaining data.<br> * 定义一个数据存取对象－一种非数据源获取数据的方法<br> */ <br>public interface StockNameDao {<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Get a list of stock names for the application <br>&nbsp;&nbsp; * @return String[] array of stock names<br>&nbsp;&nbsp; * 得到一个股票名字的列表<br>&nbsp;&nbsp; * 返回股票名称的String[]数组<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public String [] getStockNames();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Check if our stock is on the list<br>&nbsp;&nbsp; * 检查股票是否在列表中<br>&nbsp;&nbsp; * @param stockName<br>&nbsp;&nbsp; * @return<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public boolean isOnStockList(String stockName);<br>}<br>And here's the DaoImplementation:<br>这是DaoImplementation:<br><br>/**<br> * Concrete Definition of a Data Access Object <br> * 数据存取对象的具体定义<br> */ <br>public class DaoImplementation<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;implements StockNameDao {<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Constructor with package level access only <br>&nbsp;&nbsp; * to encourage use of factory method<br>&nbsp;&nbsp; * 这里的构造器只是让你使用工厂(factory)方法<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;DaoImplementation(){}<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Get a list of stock names for the app.<br>&nbsp;&nbsp; * This is a hard coded sample <br>&nbsp;&nbsp; * normally we would get this from<br>&nbsp;&nbsp; * a database or other datasource.<br>&nbsp;&nbsp; * 得到一个股票名字的列表，这只是一个硬编码的例子，一般来<br>　 * 说我们应该从数据库或其它数据源取得数据<br>&nbsp;&nbsp; * @return String[] array of stock names<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public String[] getStockNames() {<br>&nbsp;&nbsp;&nbsp;&nbsp;String[] stockNames=<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{"XYZ","ABC","MEGACORP","SOMEOTHERCOMPANY"};<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;return stockNames;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Check if our stock is on the list <br>&nbsp;&nbsp; * 检查我们的股票是否在列表中<br>&nbsp;&nbsp; * @param stockName<br>&nbsp;&nbsp; * @return true / false as appropriate<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public boolean isOnStockList(String stockName){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>//Get our list of stocks&nbsp;&nbsp;<br>//获取股票列表&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;String stockList[] = getStockNames();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;//Loop and see if our stock is on it<br>// done this way for clarity . not speed!<br>//循环看股票是否存在，这样做是为了清晰不是速度!<br>&nbsp;&nbsp;&nbsp;&nbsp;for (int a=0; a&lt;stockList.length;a++){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(stockList[a].equals(stockName)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;//Default return value<br>&nbsp;&nbsp;&nbsp;&nbsp;return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;}<br>}</pre>
<br><br>简单的DaoFactory,只是返回DaoImplementation：<br><br>
<pre class=overflow>package net.firstpartners.rp;<br>/**<br> * Factory Method to get the Data Access Object.<br> * Normally we could replace this with a <br> * framework like Spring or Hibernate <br> * 得到数据存取对象的工厂方法，通常我们可以将它替换为像Spring或<br>*&nbsp;&nbsp;Hibernatte这样的框架<br> */<br>public class DaoFactory {<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * Get the stock name Dao<br>&nbsp;&nbsp; * This sample is hardcoded - in reality <br>&nbsp;&nbsp; * we would make this configurable / cache<br>&nbsp;&nbsp; * instances of the Dao as appropriate<br>&nbsp;&nbsp; * 得到股票名字的Dao,这个例子是硬编码的－实际上我们可以让它成为<br>　 * 可配的，缓存的合适的Dao对象。<br>&nbsp;&nbsp; * @return an instance of StockNameDao<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public static StockNameDao getStockDao(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new DaoImplementation();<br>&nbsp;&nbsp;}<br>}</pre>
<br><br>现在我们有了简单的DAO实现来作为我们的数据库层，那如何将它与Drools商业层集成在一起呢？最新的商业规则文件，BusinessLayer.xml将会向我们展示：<br><br>
<pre class=overflow>&lt;?xml version="1.0"?&gt;<br>&lt;rule-set name="BusinessRulesSample"<br>&nbsp;&nbsp;xmlns="http://drools.org/rules"<br>&nbsp;&nbsp;xmlns:java="http://drools.org/semantics/java"<br>&nbsp;&nbsp;xmlns:xs="<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.w3.org/2001/XMLSchema-instance"<br>&nbsp;&nbsp;xs:schemaLocation="<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://drools.org/rules rules.xsd<br>&nbsp;&nbsp;http://drools.org/semantics/java java.xsd"&gt;<br>&nbsp;&nbsp;&lt;!-- Import the Java Objects that <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;we refer to in our rules --&gt; <br>&lt;!-- 导入规则中使用的对象 --&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;java.lang.String<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.StockOffer<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.DaoFactory<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;java:import&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.StockNameDao<br>&nbsp;&nbsp;&lt;/java:import&gt;<br>&nbsp;&nbsp;&lt;!-- Application Data not associated --&gt;<br>&nbsp;&nbsp;&lt;!-- with any particular rule --&gt;<br>&nbsp;&nbsp;&lt;!-- In this case it's our factory --&gt;<br>&nbsp;&nbsp;&lt;!-- object which gives us back --&gt;<br>&nbsp;&nbsp;&lt;!-- a handle to whatever Dao (Data --&gt;<br>&nbsp;&nbsp;&lt;!-- access object) that we need --&gt;<br>&nbsp;&nbsp;&lt;!-- 没有和任何规则联系的应用数据，这里是我们的工厂对象，--&gt;<br>&nbsp;&nbsp;&lt;!—它向我们提供向后的操作,告诉我们什么Dao 是我们需要的。--&gt;<br><br>&nbsp;&nbsp;&lt;application-data <br>&nbsp;&nbsp;&nbsp;&nbsp;identifier="daoFactory"&gt;DaoFactory<br>&nbsp;&nbsp;&lt;/application-data&gt;<br>&nbsp;&nbsp;&lt;!-- A Java (Utility) function --&gt;<br> &lt;!-- 一个Java方法 --&gt;<br>&nbsp;&nbsp;&lt;!-- we reference in our rules --&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&lt;!-- 在我们的规则中打印跟踪信息 --&gt;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;java:functions&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;public void printStock(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.firstpartners.rp.StockOffer stock)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Name:"+stock.getStockName()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+" Price: "+stock.getStockPrice()&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+" BUY:"+stock.getRecommendPurchase());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&lt;/java:functions&gt;<br>&nbsp;&nbsp;&lt;!-- Check for XYZ Corp--&gt;&nbsp;&nbsp; <br>&lt;!-- 检查XYZ公司 --&gt;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;rule name="XYZCorp" salience="-1"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Parameters we can pass into--&gt; <br>&lt;!-- the business rule --&gt;<br>&lt;!-- 可以传入规则中的参数 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/parameter"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Conditions that must be met for --&gt;<br>&lt;!-- business rule to fire --&gt;&nbsp;&nbsp; <br>&lt;!-- 激活规则必须满足的条件 --&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockName().equals("XYZ")<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getRecommendPurchase() == null<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockPrice() &gt; 10<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- What happens when the business --&gt;<br>&lt;!-- rule is activated --&gt;<br>&lt;!-- 规则激活后执行的步骤 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:consequence&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.setRecommendPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StockOffer.NO); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printStock(stockOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;<br>&nbsp;&nbsp;&lt;!-- Ensure that negative prices --&gt;<br>&nbsp;&nbsp;&lt;!-- are not accepted --&gt;&nbsp;&nbsp;<br>&nbsp;&nbsp;&lt;!-- 确定负数不被接受 --&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&lt;rule name="Stock Price Not Negative"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Parameters we can pass into the --&gt;<br>&lt;!-- business rule --&gt;<br>&lt;!-- 可以传入规则中的参数 --&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/parameter&gt;<br>&lt;!-- Conditions for rule to fire --&gt;<br>&lt;!-- 激活规则必须满足的条件 --&gt;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockPrice() &lt; 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;<br>&lt;!--When rule is activated then ... --&gt;<br>&lt;!-- 规则激活后执行的步骤 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:consequence&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.setRecommendPurchase<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(StockOffer.NO);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printStock(stockOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;<br>&nbsp;&nbsp;&lt;!-- Check for Negative Prices--&gt;&nbsp;&nbsp; <br>&lt;!-- 寻找低价 --&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&lt;rule name="Stock Price Low Enough"&gt;<br>&nbsp;&nbsp;&lt;!-- Parameters for the rule --&gt;<br>&lt;!-- 可以传入规则中的参数 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter identifier="stockOffer"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;StockOffer&lt;/class&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&lt;!-- Now uses Dao to get stock list --&gt;<br>&lt;!-- 现在使用Dao获取股票列表 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daoFactory.getStockDao().isOnStockList(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockName())<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getRecommendPurchase() == null<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:condition&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.getStockPrice() &lt; 100<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:condition&gt;<br>&lt;!-- When rule is activated do this --&gt;<br>&lt;!-- 规则激活后执行的步骤 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;java:consequence&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stockOffer.setRecommendPurchase(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StockOffer.YES);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printStock(stockOffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java:consequence&gt;<br>&nbsp;&nbsp;&lt;/rule&gt;<br>&lt;/rule-set&gt;</pre>
<br><br>为了与数据访问层集成，该文件(相对于上一篇文章)有几处改变：<br>● 在最上面，我们有几个新的&lt;java:import&gt;来把StockNameDao, DaoImplementation, 和 DaoFactory类引入系统。<br>● 我们有一个新的标记&lt;application-data&gt;,它把DaoFactory的实例赋给一个变量。&lt;application-data&gt;标记类似于参数，只不过它是运用于所有商业规则，而不只是一个。<br>● &#8220;股价足够低&#8221;的规则有一个新条件，它用DaoFactory和StockNameDao来检查股票是否在处理列表中。<br><br>我 们又一次运行BusinessRulesTest(模拟器)。模拟单元测试没有问题，既使我们改变了程序的结构，我们仍然没有改变它在做什么。从输出的日 志来看，我们可以看到我们的商业规则使用StockNameDao作为他们评估的一部份，并且 DaoImplementation.isOnStockList()被调用了。<br>虽然这个例子展示的是从数据源读取信息，其实写信息也是一样的原 理。如果某个规则决定应该做的话。区别在于我们的DAO将会有一些setSomeInformation()的方法，一旦条件满足，这个方法将会在商业规 则的&lt;java:consequence&gt;部分被调用。<br><br><strong><span style="FONT-SIZE: 16px">总结</span></strong><br>这 篇文章中，我们展示了大多数Java服务器端的应用有的三层：表现层，商业逻辑层和数据持久化层。当框架被广泛地使用在表现层和持久层中，直到目前为止还 没有框架可以包装低级的商业逻辑。就像我们在这些例子中看的，Drools和JSR-94是降低java应用复杂度，提高开发速度的理想候选者。我希望这 些例程能鼓励你去进一步接近规则引擎，他们将会为你的应用的开发和维护节省不少时间。<br>资源<br>● <a href="http://sourceforge.net/project/showfiles.php?group_id=99476&amp;package_id=158438" target=_new><u><font color=#0000ff>本文的范例代码</font></u></a><br>● <a href="http://www.drools.org/" target=_new><u><font color=#0000ff>Drools项目主页</font></u></a> <br>● [ur=http://www.jroller.com/page/eu/20040810]Drools规则的信息[/url] <br>● <a href="http://www.theserverside.com/articles/article.tss?l=Drools" target=_new><u><font color=#0000ff>"Introduction to Drools and Rule Engines," Drools项目组提供</font></u></a><br>● <a href="http://www.geocities.com/CapitolHill/5910/drltk/instructions.htm" target=_new><u><font color=#0000ff>Drools规则的schema文件</font></u></a> <br>● <a href="http://javaboutique.internet.com/tutorials/rules_engine/" target=_new><u><font color=#0000ff>JSR-94: Java规则引擎概述</font></u></a> <br>● <a href="http://struts.apache.org/" target=_new><u><font color=#0000ff>Struts框架主页</font></u></a> <br>● <a href="http://www.springframework.org/" target=_new><u><font color=#0000ff>Spring框架主页</font></u></a> <br>● <a href="http://www.hibernate.org/" target=_new><u><font color=#0000ff>Hibernate主页</font></u></a> <br>● <a href="http://www.junit.org/" target=_new><u><font color=#0000ff>JUnit测试框架</font></u></a> <br>● <a href="http://www.matrix.org.cn/resource/article/43/%5DJess%20Java%E8%A7%84%E5%88%99%E5%BC%95%E6%93%8E%5B/url" target=_new><br><u><font color=#0000ff>● [url=http://herzberg.ca.sandia.gov/jess/index.shtml]Jena语义与规则引擎</font></u></a> <br>● <a href="http://jcp.org/aboutJava/communityprocess/review/jsr094/" target=_new><u><font color=#0000ff>JSR-94主页</font></u></a> <br>● <a href="http://www.manning.com/friedman-hill" target=_new><u><font color=#0000ff>Jess in Action主页</font></u></a> <br>● <a href="http://herzberg.ca.sandia.gov/jess/zen.shtml" target=_new><u><font color=#0000ff>"Business Rule Thinking" (基于Jess) </font></u></a><br>●<a href="http://www.aaai.org/AITopics/html/expert.html" target=_new><u><font color=#0000ff>规则系统的概述</font></u></a> <br>● <a href="http://herzberg.ca.sandia.gov/jess/docs/61/rete.html" target=_new><u><font color=#0000ff>"Jess implementation of the Rete algorithm" </font></u></a><br><br>Paul Browne 已经为 FirstPartners.net在企业级Java应用方面作了差不多7年的顾问&nbsp;&nbsp;<br>
<img src ="http://www.blogjava.net/junky/aggbug/126645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-06-27 18:09 <a href="http://www.blogjava.net/junky/archive/2007/06/27/126645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>