posts - 0,  comments - 0,  trackbacks - 0
 

1      Java规则系统简介

在大型商业系统中,业务规则、商业逻辑等等都会比较复杂。而且在很多大型系统当中,很多业务规则、商业逻辑并不是一成不变的。甚至当系统进入生产阶段时,客户的业务规则、商业逻辑也会改变。某些系统要求甚至更高,要求能24小时不停机,并且能够实时修改商业规则。这就对商业系统提出了较大的挑战。如果将这些可变的规则直接编写到代码里面的话,业务规则一旦改变,就要修改代码。并由此带来编译、打包、发布等等问题。这对于生产系统来说是极不方便的。因此,如何考虑把一些可变的业务规则抽取到外面,使这些业务规则独立于程序代码。并最好是能够实时的修改业务规则,这样就可以做到不用打包编译发布等等。

值得庆幸的是现在出现了一些Java规则引擎(Rule Engine),专门解决以上所述的问题。利用它,我们就可以在应用系统中分离客户的商业决策逻辑和应用开发者的技术决策,并把这些商业规额则放在中心数据库或其他统一的地方,让它们能在运行时可以动态地管理和修改。

JbossRules是一个优秀的JAVA规则引擎,其前身是Drools3,后来被Jboss合并并改名为JbossRules

1.1基于规则的专家系统简介

人工智能是一个新兴的学科,它是想让计算机模拟人脑的思维和推理模式。人工智能分成如下几个主要的分学科:

知识表示

神经网络

基因算法

决策树

专家系统

等等几个学科

知识表示是人工智能中的一个基础领域,其目的是如何更好的在计算机当中描述已存在的事实。专家系统就是使用知识表示,来做规则推理,得出最后的结论来。

Java规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的其中一个分支。专家系统属于人工智能的范畴,它模仿人类的推理方式,使用试探性的方法进行推理,并使用人类能理解的术语解释和证明它的推理结论。为了更深入地了解Java规则引擎,下面简要地介绍基于规则的专家系统。RBES包括三部分:Rule Baseknowledge base)、Working Memoryfact base)和Inference Engine。它们的结构如下系统所示:

如上图所示,推理引擎包括三部分:模式匹配器(Pattern Matcher)、议程(Agenda)和执行引擎(Execution Engine)。推理引擎通过决定哪些规则满足事实或目标,并授予规则优先级,满足事实或目标的规则被加入议程。模式匹配器决定选择执行哪个规则,何时执行规则;议程管理模式匹配器挑选出来的规则的执行次序;执行引擎负责执行规则和其他动作。

和人类的思维相对应,推理引擎存在两者推理方式:演绎法(Forward-Chaining)和归纳法(Backward-Chaining)。演绎法从一个初始的事实出发,不断地应用规则得出结论(或执行指定的动作)。而归纳法则是根据假设,不断地寻找符合假设的事实。Rete算法是目前效率最高的一个Forward-Chaining推理算法,许多Java规则引擎都是基于Rete算法来进行推理计算的。

正向推理:

 

正向推理图形如下:

正向推理引擎的推理步骤如下:

将初始数据(fact)输入Working Memory

使用Pattern Matcher比较规则库(rule base)中的规则(rule)和数据(fact)。

如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。

解决冲突,将激活的规则按顺序放入Agenda

使用执行引擎执行Agenda中的规则。重复步骤25,直到执行完毕所有Agenda中的规则。

直到得出最终的结果为止

反向推理:

 

反向推理是目标驱动的推理方式。从目标出发,找出所有能满足该目

标的子目标。这样一直推导下去,直到所有的子目标都已经满足为止。

1.2Java规则引擎

Java规则引擎是一种嵌入在Java程序中的组件,它的任务是把当前提交给引擎的Java数据对象与加载在引擎中的业务规则进行测试和比对,激活那些符合当前数据状态下的业务规则,根据业务规则中声明的执行逻辑,触发应用程序中对应的操作。

一般来说,一条规则的形式如下:

when

    <conditions>

then

    <actions>

也就是说,当conditions成立的话,就做下面的actions。其中actions可以为生成新的事实、或者做其他动作,比如,发送email通知、执行一些本地任务等等。

1.3    JAVA规则引擎的优点

声明式编程

声明式编程,规则引擎让我们直到“做什么”,而不用直到“怎么做”。我们只要把一系列规则表示出来后。具体的推理动作就交给规则引擎来处理。

逻辑和数据分开

将可变的业务逻辑和数据分开。虽然,这违背了面向对象原则。面向对象强调数据和业务逻辑耦合。但是,对于一些易变而复杂的业务规则。如果散步在程序的各个地方、各个层次。那么一旦业务规则更改的话,就会出现“牵一发而动全身”的局面。因此,将可变的业务逻辑独立出来管理,将有助于后面的业务变更。

性能

Rete算法的性能比较高。

知识集中表示

通过使用规则,我们把规则集中存放起来,从而使系统知识能够集中表示。

可读性

规则的可读性比较高。对于熟悉业务规则。但不会程序开发的业务专家,只要熟悉规则的标示,也可以编写和修改业务规则。

1.4    使用JAVA规则系统的场合

那么,在那些场合下适合应用JAVA规则系统呢?总而言之,可以用一句话来概括:当用传统的程序开发,无法得到一种优雅的解决方法的时候,就可以考虑使用规则系统。如下的一些场合:

用传统的代码开发比较复杂、繁琐

问题虽然不复杂,但是用传统的代码开发比较脆弱,也就是经常修改

没有优雅的算法

业务规则频繁改变

有很多业务专家、不懂技术开发

1.5    不适合使用JAVA规则系统场合

虽然规则系统看起来比较不错,但是并不是任何地方都可以使用规则系统。很多简单、固定的业务系统,可以不用使用规则系统。规则系统也不能用来作为标示重要的业务流程、不能用来作为工作流引擎。

有很多程序员把JAVA规则系统当成是一种动态修改配置。也就是把一部分代码逻辑抽取到外面,统一存放起来。这样,当一些配置修改的话,通过修改规则,就能修改代码的一部分逻辑。如果把JAVA规则仅仅用在这个场合下的话,可以考虑采用脚本引擎。比如BeanShellJEXLGroovy等等。

(本文档的全篇可以到博客下面的文件列表下载,地址下面) 
http://www.blogjava.net/jspark/admin/Files.aspx


为了让尽快对
jbossRules有一个感官的认识,下面先开发一个HelloWorld的程序。

建立一个java工程,目录如下:

如上所示,建立一个com包,然后在下面分别建立一个Sample.drl文件和DroolsTest.java文件。

Sample.drl是一个规则文件,内容如下:

package com

 

import com.DroolsTest.Message;

 

rule"Hello World"

    when

       m : Message( status == Message.HELLO, message : message )

    then

       System.out.println( message );

       m.setMessage( "Goodbye cruel world" );

       m.setStatus( Message.GOODBYE );

       update( m );

end

rule"GoodBye"

    no-looptrue

    when

       m : Message( status == Message.GOODBYE, message : message )

    then

       System.out.println( message );

       m.setMessage( message );

      

end

 

DroolsTest.java是测试以上规则的JAVA程序,内部代码如下:

package com;

import java.io.InputStreamReader;

import java.io.Reader;

import org.drools.RuleBase;

import org.drools.RuleBaseFactory;

import org.drools.WorkingMemory;

import org.drools.compiler.PackageBuilder;

import org.drools.rule.Package;

/**

 *Thisisasamplefiletolauncharulepackagefromarulesourcefile.

 */

publicclass DroolsTest {

    publicstaticfinalvoid main(String[] args) {

        try {

       

        //load up the rulebase

            RuleBase ruleBase = readRule();

            WorkingMemory workingMemory = ruleBase.newStatefulSession();

           

            //go !

            Message message = new Message();

            message.setMessage( "Hello World" );

            message.setStatus( Message.HELLO );

            workingMemory.insert( message );

            workingMemory.fireAllRules();  

           

           

        } catch (Throwable t) {

            t.printStackTrace();

        }

    }

    /**

     *Pleasenotethatthisisthe"lowlevel"ruleassemblyAPI.

     */

    privatestatic RuleBase readRule() throws Exception {

       //read in the source

       Reader source = new InputStreamReader( DroolsTest.class.getResourceAsStream( "/com/Sample.drl" ) );

      

       //optionally read in the DSL (if you are using it).

       //Reader dsl = new InputStreamReader( DroolsTest.class.getResourceAsStream( "/mylang.dsl" ) );

       //Use package builder to build up a rule package.

       //An alternative lower level class called "DrlParser" can also be used...

      

       PackageBuilder builder = new PackageBuilder();

       //this wil parse and compile in one step

       //NOTE: There are 2 methods here, the one argument one is for normal DRL.

       builder.addPackageFromDrl( source );

       //Use the following instead of above if you are using a DSL:

       //builder.addPackageFromDrl( source, dsl );

      

       //get the compiled package (which is serializable)

       Package pkg = builder.getPackage();

      

       //add the package to a rulebase (deploy the rule package).

       RuleBase ruleBase = RuleBaseFactory.newRuleBase();

       ruleBase.addPackage( pkg );

       return ruleBase;

    }

   

    publicstaticclass Message {

       publicstaticfinalintHELLO = 0;

       publicstaticfinalintGOODBYE = 1;

      

       private String message;

      

       privateintstatus;

      

       public String getMessage() {

           returnthis.message;

       }

      

       publicvoid setMessage(String message) {

           this.message = message;

       }

      

       publicint getStatus() {

           returnthis.status;

       }

      

       publicvoid setStatus( int status ) {

           this.status = status;

       }

    }

}

运行DroolsTest.java程序,可以看到如下输出结果:

Hello World

Goodbye cruel world

以上就是一个最简单的jbossRules规则系统的例子。下面将具体讲解jbossRules的详细结构和语法。



引于:http://www.blogjava.net/jspark

posted on 2010-09-15 09:33 披着狼皮的羊 阅读(200) 评论(0)  编辑  收藏 所属分类: rule engine
<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

留言簿

随笔分类

文章分类

文章档案

搜索

  •  

最新评论