首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

运用 Drools 规则引擎实现业务逻辑

2012-07-01 
使用 Drools 规则引擎实现业务逻辑转自:http://www.ibm.com/developerworks/cn/java/j-drools/#ibm-pcon使

使用 Drools 规则引擎实现业务逻辑

转自:http://www.ibm.com/developerworks/cn/java/j-drools/#ibm-pcon

使用 Drools 规则引擎实现业务逻辑

使用声明性编程方法编写程序的业务逻辑

简介:?使用规则引擎可以通过降低实现复杂业务逻辑的组件的复杂性,降低应用程序的维护和可扩展性成本。这篇更新的文章展示如何使用开源的 Drools 规则引擎让 Java? 应用程序更适应变化。Drools 项目引入了一个新的本地规则表达式语言和一个 Eclipse 插件,使 Drools 比以前更容易使用。

要求施加在当今软件产品上的大多数复杂性是行为和功能方面的,从而导致组件实现具有复杂的业务逻辑。实现 J2EE 或 J2SE 应用程序中业务逻辑最常见的方法是编写 Java 代码来实现需求文档的规则和逻辑。在大多数情况下,该代码的错综复杂性使得维护和更新应用程序的业务逻辑成为一项令人畏惧的任务,甚至对于经验丰富的开发人员来说也是如此。任何更改,不管多么简单,仍然会产生重编译和重部署成本。

规则引擎试图解决(或者至少降低)应用程序业务逻辑的开发和维护中固有的问题和困难。可以将规则引擎看作实现复杂业务逻辑的框架。大多数规则引擎允许您使用声明性编程来表达对于某些给定信息或知识有效的结果。您可以专注于已知为真的事实及其结果,也就是应用程序的业务逻辑。

有多个规则引擎可供使用,其中包括商业和开放源码选择。商业规则引擎通常允许使用专用的类似英语的语言来表达规则。其他规则引擎允许使用脚本语言(比如 Groovy 或 Python)编写规则。这篇更新的文章为您介绍 Drools 引擎,并使用示例程序帮助您理解如何使用 Drools 作为 Java 应用程序中业务逻辑层的一部分。


?
  • 然后选择下载的存档文件并将其导入工作区中。您将在工作区中发现一个名为?DroolsDemo?的新 Java 项目,如图 2 所示:?

    图 2. 导入到工作区中的示例程序

    运用 Drools 规则引擎实现业务逻辑
    ?

    如果启用了?Build automatically?选项,则代码应该已编译并可供使用。如果未启用该选项,则现在构建?DroolsDemo?项目。

    ?

    在清单 4 中可以看到,RulesEngine?类的构造函数接受字符串值形式的参数,该值表示包含业务规则集合的文件的名称。该构造函数使用?PackageBuilder?类的实例解析和编译源文件中包含的规则。(注意:?该代码假设规则文件位于程序类路径中名为 rules 的文件夹中。)然后,使用?PackageBuilder?实例将所有编译好的规则合并为一个二进制?Package?实例。然后,使用这个实例配置 DroolsRuleBase?类的一个实例,后者被分配给?RulesEngine?类的?rules?属性。可以将这个类的实例看作规则文件中所包含规则的内存中表示。

    清单 5 展示了?RulesEngine?类的?executeRules()?方法:


    清单 5.?RulesEngine?类的?executeRules()?方法

    ?

    如清单 10 所示,rule?声明有一个惟一标识它的?name。还可以看到,when?关键词定义规则中的条件块,then?关键词定义结果块。清单 10 中显示的规则有一个引用?Machine?对象的条件元素。如果回到?清单 7?可以看到,?Machine?对象被插入到?WorkingMemory?对象中。这正是这个规则中使用的对象。条件元素对?Machine?实例(知识的一部分)求值,以确定是否应执行规则的结果。如果条件元素等于?true,则启动或执行结果。从清单 10 中还可以看出,结果只不过是一个 Java 语言语句。通过快速浏览该规则,可以很容易地识别出这是下列业务规则的实现:

    • 如果计算机是 Type1,则只能在该机器上执行 Test1、Test2 和 Test5。

      因此,该规则的条件元素检查(?Machine?对象的)?type?属性是否为?Type1。 (在条件元素中,只要对象遵从 Java bean 模式,就可以直接访问对象的属性,而不必调用 getter 方法。)如果该属性的值为?true,那么将?Machine?实例的一个引用分配给?machine?标识符。然后,在规则的结果块使用该引用,将测试分配给?Machine?对象。

      在该规则中,惟一看上去有些奇怪的语句是最后三条结果语句。回忆 “要解决的问题” 小节中的业务规则,应该分配为测试到期日期的值取决于分配给机器的测试。因此,分配给机器的测试需要成为规则执行引擎在对规则求值时所使用的知识的一部分。这正是这三条语句的作用。这些语句使用一个名为?insert?的方法更新规则引擎中的知识。

      lock-on-active truesalience 100when machine : Machine( type == "Type2", functions contains "DNS Server")then Test test5 = testDAO.findByKey(Test.TEST5); Test test4 = testDAO.findByKey(Test.TEST4); machine.getTests().add(test5); machine.getTests().add(test4); update( machine );endrule "Tests for type2, DDNS server machine"lock-on-active truesalience 100when machine : Machine( type == "Type2", functions contains "DDNS Server")then Test test2 = testDAO.findByKey(Test.TEST2); Test test3 = testDAO.findByKey(Test.TEST3); machine.getTests().add(test2); machine.getTests().add(test3); update( machine );endrule "Tests for type2, Gateway machine"lock-on-active truesalience 100when machine : Machine( type == "Type2", functions contains "Gateway")then Test test3 = testDAO.findByKey(Test.TEST3); Test test4 = testDAO.findByKey(Test.TEST4); machine.getTests().add(test3); machine.getTests().add(test4); update( machine );endrule "Tests for type2, Router machine"lock-on-active truesalience 100when machine : Machine( type == "Type2", functions contains "Router")then Test test3 = testDAO.findByKey(Test.TEST3); Test test1 = testDAO.findByKey(Test.TEST1); machine.getTests().add(test3); machine.getTests().add(test1); update( machine );end...

      ?

      如果将清单 16 中第一个规则的定义与?清单 10?中的定义相比较,可以看到,新方法没有将分配给?Machine?对象的?Test?实例插入到工作内存中,而是由规则的结果块调用?update()?方法,让规则引擎知道?Machine?对象已被修改。(Test?实例被添加/指定给它。) 如果看看清单 16 中其他的规则,应该可以看到,每当将测试分配给一个?Machine?对象时,都采用这种方法:一个或多个?Test?实例被分配给一个?Machine?实例,然后,修改工作知识,并通知规则引擎。

      还应注意清单 16 中使用的?active-lock?属性。该属性的值被设为?true;如果不是这样,在执行这些规则时将陷入无限循环。将它设为?true?可以确保当一个规则更新工作内存中的知识时,最终不会导致对规则重新求值并重新执行规则,也就不会导致无限循环。可以将?active-lock?属性 看作?no-loop?属性的加强版。?no-loop?属性确保当修改知识的规则更新后不会再被调用,而?active-lock?属性则确保在修改知识以后,文件中的任何规则(其 active-lock 属性被设为?true)不会重新执行。

      清单 17 展示了其他规则有何更改:


      清单 17. testRules2.drl 中与分配测试到期日期有关的规则

      现在选择?Arguments?选项卡并输入?-t demo.test.TestsRulesEngineTest?作为程序参数(参见图 4)。输入该参数后,单击对话框右下角的?Apply?按钮,保存新的启动配置。然后,可以单击?Debug?按钮,开始以 “Drools Application” 的形式调试TestsRulesEngineTest?JUnit 类。如果之前在 testRules1.drl 或 testRules2.drl 中添加了断点,那么当使用这个启动配置时,调试器应该会在遇到这些断点时停下来。


      图 4.?TestsRulesEngineTest?类的 Drools Application 启动配置(Arguments 选项卡)

      运用 Drools 规则引擎实现业务逻辑

      结束语

      使用规则引擎可以显著降低实现 Java 应用程序中业务规则逻辑的组件的复杂性。使用规则引擎以声明方法表达规则的应用程序比其他应用程序更容易维护和扩展。正如您所看到的,Drools 是一种功能强大的灵活的规则引擎实现。使用 Drools 的特性和能力,您应该能够以声明方式实现应用程序的复杂业务逻辑。Drools 使得学习和使用声明式编程对于 Java 开发人员来说相当容易。

      本文展示的 Drools 类是特定于 Drools 的。如果要在示例程序中使用另一种规则引擎实现,代码需要作少许更改。因为 Drools 是 JSR 94 兼容的,所以可以使用 Java Rule Engine API(如 JSR 94 中所指定)设计特定于 Drools 的类的接口。(Java Rule Engine API 用于 JDBC 在数据库中的规则引擎。)如果使用该 API,则可以无需更改 Java 代码而将规则引擎实现更改为另一个不同的实现,只要这个不同的实现也是 JSR 94 兼容的。JSR 94 不解析包含业务规则的规则文件(在本文示例应用程序中为 testRules1.drl)的结构。文件的结构将仍取决于您选择的规则引擎实现。作为练习,可以修改示例程序以使它使用 Java Rule Engine API,而不是使用 Java 代码引用特定于 Drools 的类。

      ?

      ?

      ?

  • 热点排行