• Drools入门


    文章转载自:http://cwqcwq.iteye.com/blog/397869

    一、背景知识: 
    1、什么是规则引擎 
    Java规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的其中一个分支。专家系统属于人工智能的范畴,它模仿人类的推理方式,使用试探性的方法进行推理,并使用人类能理解的术语解释和证明它的推理结论。 
    推理引擎包括三部分:模式匹配器(Pattern Matcher)、议程(Agenda)和执行引擎(Execution Engine)。推理引擎通过决定哪些规则满足事实或目标,并授予规则优先级,满足事实或目标的规则被加入议程。模式匹配器决定选择执行哪个规则,何时执行规则;议程管理模式匹配器挑选出来的规则的执行次序;执行引擎负责执行规则和其他动作。 
    和人类的思维相对应,推理引擎存在两者推理方式:演绎法(Forward-Chaining)和归纳法(Backward-Chaining)。演绎法从一个初始的事实出发,不断地应用规则得出结论(或执行指定的动作)。而归纳法则是根据假设,不断地寻找符合假设的事实。Rete算法是目前效率最高的一个 Forward-Chaining推理算法,许多Java规则引擎都是基于Rete算法来进行推理计算的。 
    推理引擎的推理步骤如下: 
    (1)将初始数据(fact)输入Working Memory。 
    (2)使用Pattern Matcher比较规则库(rule base)中的规则(rule)和数据(fact)。 
    (3)如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。 
    (4)解决冲突,将激活的规则按顺序放入Agenda。 
    (5)使用执行引擎执行Agenda中的规则。重复步骤2至5,直到执行完毕所有Agenda中的规则。 
    上述即是规则引擎的原始架构,Java规则引擎就是从这一原始架构演变而来的。 
    Drools是基于正向推理的规则引擎。正向推理是数据驱动的,facts事实被传递到工作空间中,在那里有一个或多个规则与这些事实匹配,并由Agenda安排执行—我们从一个事实开始,传递事实,最后得到一个结论。 
    产生式规则是一个用一阶逻辑进行知识呈现的二元结构。 
    when 
        
    then 
        
    Drools中的Rete算法被称为ReteOO,表示Drools为面向对象系统(Object Oriented systems)增强并优化了Rete算法。 

    2、规则引擎的优点 
    声明式编程:使用规则更加容易对复杂的问题进行表述,并得到验证 
    逻辑与数据分离:数据保存在系统对象中,逻辑保存在规则中。这根本性的打破了面向对象系统中将数据和逻辑耦合起来的局面 
    速度及可测量性:Drools的Rete、Leaps算法,提供了对系统数据对象非常有效率的匹配,这些算法经过了大量实际考验的证明 
    3、何时使用 
    业务逻辑经常发生改变 
    代码中有很多”if””else””switch”和其它凌乱的逻辑,且总是易变的 

    二、开始 

    目前drools的最新版本是5.0(2009年5月19日发布),本文使用4.0.7。 

    1、导入jar包: 

    drools-core-4.0.7.jar 
    drools-compiler-4.0.7.jar 
    antlr3-runtime-3.0 
    mvel-1.3.1-java1.4 
    core-3.2.3.v_686_R32x :在eclipse中编译.drl文件时需要 

    2、从HelloWorld开始: 

    一个通用的规则引擎类: 

    Java代码 复制代码 收藏代码

    1. import java.io.InputStreamReader;   
    2. import java.io.Reader;   
    3.   
    4. import org.drools.RuleBase;   
    5. import org.drools.RuleBaseFactory;   
    6. import org.drools.WorkingMemory;   
    7. import org.drools.compiler.DroolsParserException;   
    8. import org.drools.compiler.PackageBuilder;   
    9. import org.drools.event.DebugWorkingMemoryEventListener;   
    10. import org.drools.rule.Package;   
    11.   
    12. public class RuleEngine {   
    13.   
    14.  private RuleBase rules;   
    15.   
    16.  private boolean debug = false;   
    17.   
    18.  public RuleEngine(String rulesFile) throws DroolsParserException {   
    19.   super();   
    20.   try {   
    21.    //读取规则文件,*.drl   
    22.    Reader source = new InputStreamReader(RuleEngine.class.getResourceAsStream("/" + rulesFile));   
    23.       
    24.    //PackageBuilder用来构建Package   
    25.    PackageBuilder builder = new PackageBuilder();   
    26.   
    27.    //解析和编译规则文件   
    28.    builder.addPackageFromDrl(source);   
    29.   
    30.    //获取包中的规则集合   
    31.    Package pkg = builder.getPackage();   
    32.   
    33.    //RuleBase是运行时组件,包含一个或多个Package   
    34.    rules = RuleBaseFactory.newRuleBase();   
    35.   
    36.    rules.addPackage(pkg);   
    37.   } catch (Exception e) {   
    38.    throw new DroolsParserException("Could not load/compile rules file: " + rulesFile, e);   
    39.   }   
    40.  }   
    41.   
    42.  public void executeRules(WorkingEnvironmentCallback callback) {   
    43.   WorkingMemory workingMemory = rules.newStatefulSession();   
    44.   if (debug) {   
    45.    workingMemory.addEventListener(new DebugWorkingMemoryEventListener());   
    46.   }   
    47.   callback.initEnvironment(workingMemory);//用来向Working Memory中设置Facts对象   
    48.   workingMemory.fireAllRules();//触发规则引擎   
    49.  }   
    50.   
    51. }  
    Java代码  收藏代码

    1. import java.io.InputStreamReader;  
    2. import java.io.Reader;  
    3.   
    4. import org.drools.RuleBase;  
    5. import org.drools.RuleBaseFactory;  
    6. import org.drools.WorkingMemory;  
    7. import org.drools.compiler.DroolsParserException;  
    8. import org.drools.compiler.PackageBuilder;  
    9. import org.drools.event.DebugWorkingMemoryEventListener;  
    10. import org.drools.rule.Package;  
    11.   
    12. public class RuleEngine {  
    13.   
    14.  private RuleBase rules;  
    15.   
    16.  private boolean debug = false;  
    17.   
    18.  public RuleEngine(String rulesFile) throws DroolsParserException {  
    19.   super();  
    20.   try {  
    21.    //读取规则文件,*.drl  
    22.    Reader source = new InputStreamReader(RuleEngine.class.getResourceAsStream("/" + rulesFile));  
    23.      
    24.    //PackageBuilder用来构建Package  
    25.    PackageBuilder builder = new PackageBuilder();  
    26.   
    27.    //解析和编译规则文件  
    28.    builder.addPackageFromDrl(source);  
    29.   
    30.    //获取包中的规则集合  
    31.    Package pkg = builder.getPackage();  
    32.   
    33.    //RuleBase是运行时组件,包含一个或多个Package  
    34.    rules = RuleBaseFactory.newRuleBase();  
    35.   
    36.    rules.addPackage(pkg);  
    37.   } catch (Exception e) {  
    38.    throw new DroolsParserException("Could not load/compile rules file: " + rulesFile, e);  
    39.   }  
    40.  }  
    41.   
    42.  public void executeRules(WorkingEnvironmentCallback callback) {  
    43.   WorkingMemory workingMemory = rules.newStatefulSession();  
    44.   if (debug) {  
    45.    workingMemory.addEventListener(new DebugWorkingMemoryEventListener());  
    46.   }  
    47.   callback.initEnvironment(workingMemory);//用来向Working Memory中设置Facts对象  
    48.   workingMemory.fireAllRules();//触发规则引擎  
    49.  }  
    50.   
    51. }  

    3、编写drl文件:test.drl

    Java代码 复制代码 收藏代码

    1.   
    2. package org.drools.tutorials.banking   
    3.   
    4. rule "Rule 01"      
    5.     when   
    6.         String (toString=="jack") //含义:如果插入的Facts对象是String类型,且调用其toString()方法后的值等于"jack",则为true   
    7.     then   
    8.         System.out.println("HelloWorld!");   
    9. end  
    Java代码  收藏代码

    1. package org.drools.tutorials.banking  
    2.   
    3. rule "Rule 01"     
    4.     when  
    5.         String (toString=="jack") //含义:如果插入的Facts对象是String类型,且调用其toString()方法后的值等于"jack",则为true  
    6.     then  
    7.         System.out.println("HelloWorld!");  
    8. end  

    4、测试:

    Java代码 复制代码 收藏代码

    1. public class Test {   
    2.   
    3.  public static void main(String[] args) {    
    4.   RuleEngine engine = null;   
    5.   try {   
    6.    engine = new RuleEngine("test.drl");   
    7.   } catch (DroolsParserException e) {   
    8.    // process Exception   
    9.   }   
    10.   engine.executeRules(new WorkingEnvironmentCallback(){   
    11.    public void initEnvironment(WorkingMemory workingMemory) throws FactException {       
    12.     workingMemory.insert("jack"); //向Working Memory中设置Facts对象      
    13.    }      
    14.   });     
    15.  }   
    16. }  
    Java代码  收藏代码

    1. public class Test {  
    2.   
    3.  public static void main(String[] args) {   
    4.   RuleEngine engine = null;  
    5.   try {  
    6.    engine = new RuleEngine("test.drl");  
    7.   } catch (DroolsParserException e) {  
    8.    // process Exception  
    9.   }  
    10.   engine.executeRules(new WorkingEnvironmentCallback(){  
    11.    public void initEnvironment(WorkingMemory workingMemory) throws FactException {      
    12.     workingMemory.insert("jack"); //向Working Memory中设置Facts对象     
    13.    }     
    14.   });    
    15.  }  
    16. }  

    三、简单介绍 

    1、术语解释 

    Rule:一条规则可以看作是IF…THEN…语句块,或者一个简单的IPO(即输入、处理和输出),描述了一组输入,一组判断和一组输出; 
    RuleBase: RuleBase包含一个或多个规则包,它们已经被校验和编译完成,是可以序列化的 
    Package: 规则包,是规则以及其它相关结构的一个集合,包必须有一个名称空间,并且使用标准的java约定进行命名 
    WorkingMemory: 用户工作区,包含用户的数据和相关Rule的引用 
    Facts: Facts就是规则中用到的输入,Facts可以是任何规则可以存取的Java对象,规则引擎完全不会克隆对象,它仅仅是保存对对象的一个引用/指针 

    2、规则文件详解 
    规则文件通常是以drl扩展名结尾。在一个drl文件中可以包含多个规则,函数等等,DRL是简单的text文件格式。 

    规则文件的构成: 

    package package-name //定义包名 
    imports   //导入java包 
    globals   //定义全局变量,如 global java.util.List myGlobalList; 
    functions  //定义函数 
    rules   //一系列的规则 

    规则的构成: 

    rule "name" 
        attributes 
        when 
            LHS 
        then 
            RHS 
    end 

    说明: 
    LHS是规则的条件部分,可以定义变量 
    RHS是允许Java语义代码,RHS中的多条语句实质上是一个规则,只有满足全部语句才符合规则 
    任何在LHS中绑定的变量可以在RHS中使用 

    3、规则文件示例解读 

    rule “Rule 01”   
        when 
    //$date定义一个变量,其值为Cashflow对象getDate()的值 
    //$cashflow定义一个指向Cashflow对象的引用 
            $cashflow : Cashflow( $date : date, $amount : amount ) 
            not Cashflow( date < “27-Oct-2007”) //not 意为不存在,只有不存在date < “27-Oct-2007″的Cashflow对象才为true 
        then 
            System.out.println(“Cashflow: “+$date+” :: “+$amount); 
    $cashflow.setAmount($cashflow.getAmount()+$amount); //设置Cashflow对象的amount值 
            retract($cashflow);//当retract一个fact,WorkingMemory将不再跟踪该fact 
    end 

    public class Cashflow { 
        private Date   date; 
        private double amount; 
        //省略getter.. setter.. 
    } 

    重要:规则引擎完全不会克隆对象,它仅仅是保存对对象的一个引用/指针 
    即,在规则定义中对fact的修改,就是对代码中fact对象的修改。 
    也即,规则的根本目的是产生一个供使用的输出结果,即修改后的JavaBean

  • 相关阅读:
    const用法详解(转)
    [转]Scintilla开源库使用指南
    javascript 流程控制语句 if 语句
    knockout.js 练习一
    深入Node.js的模块机制
    js本地存储解决方案(localStorage与userData)
    linear-gradient 渐变 css3新属性
    制作响应式网站时,用来测试不同宽度下网页展示效果的方法
    zepto.js, django和webpy
    attachEvent 与 addEventListener 的用法、区别
  • 原文地址:https://www.cnblogs.com/jpfss/p/12016873.html
Copyright © 2020-2023  润新知