`
duyangsss
  • 浏览: 124146 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Drools 5 模板技术应用(drools template)

 
阅读更多
引用自[http://cutelion.blog.hexun.com/72268803_d.html]

    开发环境: Drools 5.3.0, 必需的lib: drools-templates-5.3.0.Final.jar

    在利用Drools 5编写规则时,如果发现有一组规则遵守相同布置的模式、约束和在RHS中的动作,只是
常量、对象或字段名字不同,可以考虑为产生实际的规则,启用Drools的规则模板功能。我们可以编写一个
规则模板文件,包含规则文字骨架,并使用Drools模板编译器,为实例规则的内容组合一个提供实际值的对
象集合。以下是一个简单的例子。

1. 新建一个java包,如 template
2. 在其中建枚举: ItemCode.java
package template;

public enum ItemCode {
    LOCK, STOCK, BARREL
}


3. 建一个项目类 Item.java
package template;

public class Item {
    private String name;
    private int weight;
    private ItemCode itemCode;
    private int price;
    
    public Item(String name, int price, int weight, ItemCode itemCode) {
        super();
        this.name = name;
        this.price = price;
        this.weight = weight;
        this.itemCode = itemCode;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }

    public ItemCode getItemCode() {
        return itemCode;
    }

    public void setItemCode(ItemCode itemCode) {
        this.itemCode = itemCode;
    }

    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
}



4. 建一个参数集的类: ParamSet.java
package template;

import java.util.EnumSet;

public class ParamSet {
    private String field;
    private int lower;
    private int upper;
    private EnumSet<ItemCode> codeSet;
    
    public ParamSet(String field, int lower, int upper,
            EnumSet<ItemCode> codeSet) {
        super();
        this.field = field;
        this.lower = lower;
        this.upper = upper;
        this.codeSet = codeSet;
    }

    public String getField() {
        return field;
    }

    public int getLower() {
        return lower;
    }

    public int getUpper() {
        return upper;
    }

    public String getCodes() {
        StringBuilder sb = new StringBuilder();
        String conn = "";
        for (ItemCode ic : codeSet) {
            sb.append(conn).append(" == ItemCode.").append(ic);
            conn = " ||";
        }
        return sb.toString();
    }
}



5. 建一个规则展开器类,用于展开模板规则。Expander.java
package template;

import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collection;

import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.template.ObjectDataCompiler;

public class Expander {
    public void expand(KnowledgeBase kBase, InputStream is, Collection<?> act)
            throws Exception {
        ObjectDataCompiler converter = new ObjectDataCompiler();
        String drl = converter.compile(act, is);
        KnowledgeBuilder kBuilder = KnowledgeBuilderFactory
                .newKnowledgeBuilder();
        Reader rdr = new StringReader(drl);
        kBuilder.add(ResourceFactory.newReaderResource(rdr), ResourceType.DRL);
        if (kBuilder.hasErrors()) {
            for (KnowledgeBuilderError err : kBuilder.getErrors()) {
                System.err.println(err.toString());
            }
            throw new IllegalStateException("DRL errors");
        }
        kBase.addKnowledgePackages(kBuilder.getKnowledgePackages());
    }
}



6. 建一个规则模板文件: Item.drl
template header
field
lower
upper
codes

package range;

import template.Item
import template.ItemCode

template "inRange"
rule "is in range @{row.rowNumber}"
when 
    Item($name : name, $v : @{field} >= @{lower} && <= @{upper}, $code : itemCode @{codes})
then
    System.out.println("Item " + $name + " @{field} in range: " + $v + " itemCode: " + $code);
end
end template


说明: $code : itemCode @{codes} 中的 @{codes} 是应用的 getCodes()方法, 拼接了字符串形成一个带或(||)的逻辑表达式。也就是 Item.getCodes()这个方法。

7. 到这里就可以开始写测试代码了。TestItemTemplate.java
package template;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;

public class TestItemTemplate {
    public static void main(String args[]) throws Exception {
        Collection<ParamSet> cfl = new ArrayList<ParamSet>();
        cfl.add(new ParamSet("price", 10, 50, EnumSet.of(ItemCode.BARREL)));
        cfl.add(new ParamSet("weight", 10, 99, EnumSet.of(ItemCode.LOCK,ItemCode.STOCK)));
        KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
        Expander ex = new Expander();
        InputStream dis = ResourceFactory.newClassPathResource("template/Item.drl", TestItemTemplate.class).getInputStream();
        ex.expand(kBase, dis, cfl);
        StatefulKnowledgeSession session = kBase.newStatefulKnowledgeSession();
        
        session.insert(new Item("A", 130, 42, ItemCode.LOCK));
        session.insert(new Item("B", 44, 140, ItemCode.STOCK));
        session.insert(new Item("C", 23, 80, ItemCode.BARREL));
        session.insert(new Item("D", 85, 9, ItemCode.LOCK));
        session.insert(new Item("E", 146, 189, ItemCode.STOCK));
        session.insert(new Item("F", 16, 90, ItemCode.STOCK));
        session.insert(new Item("G", 44, 140, ItemCode.BARREL));
        session.fireAllRules();
    }
}




得出如下测试结果:
Item G price in range: 44 itemCode: BARREL
Item F weight in range: 90 itemCode: STOCK
Item C price in range: 23 itemCode: BARREL
Item A weight in range: 42 itemCode: LOCK
分享到:
评论
1 楼 ZhaojieSmall 2015-11-18  

相关推荐

Global site tag (gtag.js) - Google Analytics