差沙的密码 -- SSHWSFC's code
阅读本Blog请自备塑料袋一只
posts - 14,  comments - 59,  trackbacks - 0
这两天在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,目的是希望大家都来了解一下,共同学习。
posted on 2006-05-28 20:53 差沙 阅读(2787) 评论(9)  编辑  收藏 所属分类: avaj

FeedBack:
# re: 关于Drools的初步,迷醉状态认识
2006-05-28 22:46 | 艾尘
开始接触Drools。一起学习! :)  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2006-05-28 23:54 | 差沙
我是刚刚开始,以后多交流。对了,你要用在什么场合?  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2006-05-29 21:20 | C[ETI]O@quaffsoft
$userName : name
表示什么意思?把user的name属性值赋给userName变量?  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2006-05-29 21:34 | C[ETI]O@quaffsoft
@C[ETI]O@quaffsoft

$userName是变量
System.out.println("More Than 50,userName"+$userName);
System.out.println("More Than 50,userName"+$user.getName());  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2006-05-29 22:28 | 差沙
@C[ETI]O@quaffsoft
正解  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2006-05-30 22:15 | C[ETI]O@quaffsoft
如何判断一个Integer?比如要判断一个大于10的Integer
$integer:Integer(),括号里面怎么写,,目前的做法是写一个类弄个Integer类型属性
  回复  更多评论
  
# xuxqqhyo
2007-06-15 05:35 | xuxqqhyo
dbdwwyon http://lvunjlvs.com llokaulb gtskgzvt  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2008-04-22 14:02 | javapon
你好~最近正学Drools呢~可网上的资料并不是很多,特别是.dsl文件网上大部分多是XML文件格式的那种~~~~你有相关的资料吗?或关于Drools的小编程~~~~望能发一份给我~~~谢谢了。邮箱 javapon@163.com  回复  更多评论
  
# re: 关于Drools的初步,迷醉状态认识
2008-04-22 14:05 | javapon
@@本来以为网上应该有不少的讲解了,但是发现几乎全是针对2.0版本讲解的.
恩对找了老半天也找不到新版本的讲解~~~~  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
这家伙很懒,但起码还是写了一句话。

<2006年5月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(8)

随笔分类

随笔档案

文章分类

搜索

  •  

最新评论

阅读排行榜

评论排行榜