1、规则引擎简介
规则引擎可以将活动规则和代码解耦,不管规则如何变化,执行端不用动。java开源的规则引擎有:Drools、Easy Rules、Mandarax、IBM ILOG。使用最为广泛并且开源的是Drools。
2、Drools规则引擎原理
Drools 中的 Rete 算法被称为 ReteOO,表示 Drools 为面向对象系统(Object Oriented systems)增强并优化了 Rete 算法。
Rete 算法
Rete 在拉丁语中译为”net”,即网络。Rete 匹配算法是一种进行大量模式集合和大量对象集合间比较的高效方法,通过网络筛选的方法找出所有匹配各个模式的对象和规则。
其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。Rete 算法可以被分为两个部分:规则编译和规则执行。当Rete算法进行事实的断言时,包含三个阶段:匹配、选择和执行,称做 match-select-act cycle。
rate算法的详细内容可以参考这篇文章:开源规则流引擎实践
Drools架构及原理图
在 Drools 中,规则被存 放在 Production Memory(规则库)中,推理机要匹配的 facts(事实)被存在 Working Memory(工作内存)中。当时事实被插入到工作内存中后,规则引擎会把事实和规则库里的模式进行匹配,对于匹配成功的规则再由 Agenda 负责具体执行推理算法中被激发规则的结论部分,同时 Agenda 通过冲突决策策略管理这些冲突规则的执行顺序,Drools 中规则冲突决策策略有:
- 优先级策略
 - 复杂度优先策略
 - 广度策略
 - 深度策略
 - 装载序号策略
 - 随机策略
 
3、入门例子
计算年龄小例子
age> 0 少年
 age> 12 青年
 age> 24 中年
 age > 60 && age <80 老年
4、开发流程
maven
IDEA可以直接创建drools类型的项目,但是无法和maven很好的集成,建议直接新建maven项目用来开发,pom文件需要添加以下依赖:
<dependencies>
        <!-- drools -->
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-api</artifactId>
            <version>6.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>6.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>6.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-decisiontables</artifactId>
            <version>6.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-templates</artifactId>
            <version>6.5.0.Final</version>
        </dependency>
        <!--log4j-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
  项目结构规范
drools项目的规则文件和kmodule.xml必须在main->resources文件夹中创建,其中kmodule.xml需要位于main->resources->META-INF目录下
 否则运行的时候会出现无法找到资源文件,抛出空指针的异常
 resources目录中,规则文件可以按照分类放在不同的目录中,其所在的目录就是kmodule.xml文件中引用的包名,如
main
 =resources
 ==META-INF
 ===kmodule.xml
 ==rules1
 ===rule.drl
 ==rules2
 ===rule.drl
pojo
package com.us.person;
/** * Created by yangyibo on 16/12/7. */
public class Person {
    private String name;
    private int age;
    private String desc;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public String toString() {
        return "[name=" + name + ",age=" + age + ",desc=" + desc + "]";
    }
}
  rule.drl
package com.us.person;
import com.us.person.Person;
        function void printName(String name,String desc) {
            System.out.println("name:"+name+" desc:"+ desc);
        }
        rule "boy"
            salience 1
            when
                $p : Person(age > 0);
            then
                $p.setDesc("少年");
                retract($p);
                printName($p.getName(),$p.getDesc());
        end
        rule "youth"
            salience 2
            when
                $p : Person(age > 12);
            then
                $p.setDesc("青年");
                retract($p);
                printName($p.getName(),$p.getDesc());
        end
        rule "midlife"
            salience 3
            when
                $p : Person(age > 24);
            then
                $p.setDesc("中年");
                retract($p);
                printName($p.getName(),$p.getDesc());
        end
        rule "old"
        lock-on-active true
          salience 5
            when
                $p : Person(age > 60 && age <80)
            then
                $p.setDesc("老年");
                update($p);
                printName($p.getName(),$p.getDesc());
        end
  kmodule.xml
如果没有 kmodule.xml 文件,在META-INF 文件夹下新建kmodule.xml 文件填写如下内容。
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
	<kbase name="SimpleRuleKBase" packages="com.us.person">
        <ksession name="simpleRuleKSession"/>
	</kbase>
</kmodule>
  Test
package com.us.person;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
/** * Created by yangyibo on 16/12/7. */
public  class PersonTest {
    static KieSession getSession() {
    
        KieServices ks = KieServices.Factory.get();
        KieContainer kc = ks.getKieClasspathContainer();
        return kc.newKieSession("simpleRuleKSession");
    }
    public static void run() {
            KieSession ks = getSession();
            Person p1 = new Person("白展堂", 68);
            Person p2 = new Person("李大嘴", 32);
            Person p3 = new Person("佟湘玉", 18);
            Person p4 = new Person("郭芙蓉", 8);
            Person p5 = new Person("祝无双", 66);
            System.out.println("before p1 : " + p1);
            System.out.println("before p2 : " + p2);
            System.out.println("before p3 : " + p3);
            System.out.println("before p4 : " + p4);
            ks.insert(p1);
            ks.insert(p2);
            ks.insert(p3);
            ks.insert(p4);
            ks.insert(p5);
            int count = ks.fireAllRules();
            System.out.println("总执行了" + count + "条规则------------------------------");
            System.out.println("after p1 : " + p1);
            System.out.println("after p2 : " + p2);
            System.out.println("after p3 : " + p3);
            System.out.println("after p4 : " + p4);
            System.out.println("after p4 : " + p5);
            ks.dispose();
    }
    public static void main(String[] args) {
        run();
    }
}
  输出:
before p1 : [name=白展堂,age=68,desc=null]
 before p2 : [name=李大嘴,age=32,desc=null]
 before p3 : [name=佟湘玉,age=18,desc=null]
 before p4 : [name=郭芙蓉,age=8,desc=null]
 name:祝无双 desc:老年
 name:白展堂 desc:老年
 name:祝无双 desc:中年
 name:李大嘴 desc:中年
 name:白展堂 desc:中年
 name:佟湘玉 desc:青年
 name:郭芙蓉 desc:少年
 总执行了7条规则——————————
 after p1 : [name=白展堂,age=68,desc=中年]
 after p2 : [name=李大嘴,age=32,desc=中年]
 after p3 : [name=佟湘玉,age=18,desc=青年]
 after p4 : [name=郭芙蓉,age=8,desc=少年]
 after p4 : [name=祝无双,age=66,desc=中年]



京公网安备 11010502036488号