关于Drools的初步,迷醉状态认识

关于Drools的初步,迷醉状态认识
这两天在 springside受白衣的影响开始关注drools。说他是平民的脚本引擎一点都不假,使用起来极为方便,本来以为网上应该有不少的讲解了,但是发现几乎全是针对2.0版本讲解的。而drools加入jboss后有了质的变化,下面来看一下最新的3.0使用起来有什么不同:

首先我们要取得rule,规则引擎、规则引擎,取得规则是必要的。
private   static  RuleBase readRule()  throws  Exception  {
        
//read in the source
        Reader source = new InputStreamReader( DroolsTest.class.getResourceAsStream( "/aclcreat.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;
    }

这里在官方的例子基础上做了自己的实现(其实什么都没改)。

可以看到,第一步是取得文件IO,这个文件就是我们要写得规则脚本,这个等下再说,大家可以假象一下脚本是个什么样子,现在只说怎么在程序中取得Rule。
接下来,是使用Builder取得一个package,既然builder都上来了说明能输入的脚本不止一个了。用addPackageFromDrl向这个builder压缩机里面输入脚本,当然还有另外一个文件dsl,这个后面再说。利用builder取得package。

最后构造一个BaseRule,利用Factory取得的时候是有选择的,RuleBaseFactory.newRuleBase(int type)其中的type可以为不同的Algorithm,有RETE和Leaps 两种。对这两种Algorithm的具体解释可以参看 http://citeseer.ist.psu.edu/context/505087/0 或是 drools的文档,其实我也不太懂。

把刚才的package添到ruleBase里面一个Rule就大功告成了。

接下来看看怎么执行它:
            WorkingMemory workingMemory  =  ruleBase.newWorkingMemory();
            
            
// go !
            Order order  =   new  Order();
            order.setId(
1 );
            order.setName(
" testOrder " );
            order.setTotlePrice(
10 );
                        
            User user 
=   new  User();
            user.setName(
" testAdmin " );
            user.setAuth(
" USER_ADMIN " );
            List
< String >  roles  =   new  ArrayList < String > ();
            roles.add(
" ADMIN " );
            user.setRoles(roles);
            

            User user1 
=   new  User();
            user1.setName(
" testUser " );
            user1.setAuth(
" USER_USER " );
            List
< String >  roles1  =   new  ArrayList < String > ();
            roles1.add(
" USER " );
            user1.setRoles(roles1);
            
            workingMemory.assertObject(order);
            workingMemory.assertObject(user);
            workingMemory.assertObject(user1);
            
            workingMemory.fireAllRules();        
            
            List
< AclEntry >  acls  =  workingMemory.getObjects(AclEntry. class );

用ruleBase生成一个WorkingMemory,WorkingMemory是Rule的执行引擎,装载rule和事实(很重要的概念),并统一执行他们。接下来我就在写我的事实,事实是什么,事实就是今天是什么天?订单总价多少?就是要告诉脚本的java对象。然后把事实一一压入WorkingMemory这个大压缩机。就瞧好吧。

OK可以执行了,fireAllRules!(真TM,COOL的名字)。当然有全部执行就有部分执行。你可以把规则分组,然后按组执行,或是指定rule的名字来执行(这里还是大家自己看看吧)。

???究竟执行了什么。当然是执行了我们的脚本,脚本在这里、看看它可不是xml了:
#created on:  2006 - 5 - 19
package  com.sample;

#list any 
import  classes here.

import  com.sample.domain.Order;
import  com.sample.domain.User;

import  com.sample.AclEntry;
#expander mylang.dsl

#declare any global variables here

rule 
" Order TotlePrice more than $1000 "     
    when
        #conditions
        $order : Order( totlePrice 
>   1000  )
        $user : User( roles contains 
" ADMIN "  , $userName : name)
    then 
        #actions
        System.out.println(
" More Than " );
        
assert ( new  AclEntry($order, $user,  1 ));
end

rule 
" Order TotlePrice less or equl than $1000 "     
    when
        #conditions
        $order : Order( totlePrice 
<=   1000  )
        $user : User( $userName : name )
    then 
        #actions
        System.out.println(
" Less Than " );
        
assert ( new  AclEntry($order, $user,  2 ));
end

每一个rule就是一个规则,所有的事实要一一过一遍这些规则。when是规则提出的条件,如果哪个事实符合这个条件,就进入then的环节,进行相应的处理。

分析一下条件:$order : Order( totlePrice  >   1000  )。一看就知道是总价超过1000的订单。$order是把这个订单邦定,后面可以使用。
分析一下then: System.out.println就不解释了。assert(new AclEntry($order, $user, 2)); 这里的assert的意义就是告诉WorkingMemory一个事实,其实跟前面的加入事实一个道理。打个比方,如果有闪电,那么就有雷。

这样走完一个rule后大家很容易发现,其实是根据订单和用户的角色不同产生了不同的acl,然后我要拿到这些由事实得到的事实。

List < AclEntry >  acls  =  workingMemory.getObjects(AclEntry. class );
这样就能在workingMemory里面掏出我们需要的事实来,新鲜出炉的哦。

相当粗略的讲了一下drools,目的是希望大家都来了解一下,共同学习。

你可能感兴趣的:(关于Drools的初步,迷醉状态认识)