1. 程式人生 > >規則引擎 Drools 模板編譯

規則引擎 Drools 模板編譯

規則引擎 Drools 模板編譯

1.模板編譯

1.1依賴

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-templates</artifactId>
    <version>7.7.0.Final</version>
</dependency>

1.2建立模板

新建模板檔案 test.drt

template header
condition
execution

package
template template "this is a test" rule "[email protected]{row.rowNumber}" when @{condition} then System.out.println(@{execution}); end end template

說明
規則模板主要由兩部分構成:

Template header 定義了在模板中使用的變數。
模板中以 “template name” 開頭, 以”end template” 結尾, 中間定義了模板的內容。變數佔位符使用 @{variable_name} .
@{row.rowNumber}是一個特殊的變數, 每次會按順序生成一個行號, 可用於區分規則名。

1.3 渲染模板生成規則檔案

渲染模板的流程,先將資料封裝為 DataProvider,然後通過 DataProviderCompiler 使用 DataProvider 將模板編譯為 DRL。

Drools支援陣列型別的DataProvider, ArrayDataProvider實現了DataProvider,
示例

InputStream templateStream = DataDrivenTemplateExample.class.getResourceAsStream("/rules/SimpleTemplateExample.drt");
// @{row.rowNumber}=陣列下標, @{condition}=規則條件, @{execution}=規則動作
DataProvider data = new ArrayDataProvider(new String[][]{ new String[]{"String(this == \"規則條件\")", "\"規則動作\""} }); DataProviderCompiler converter = new DataProviderCompiler(); String drl = converter.compile(data, templateStream);

1.4 編譯規則

在模板渲染、編譯成規則檔案後,就可以正常的編譯DRL規則檔案, 新建會話等。
KieHelper 是 Drools提供的工具類, 可用於編譯DRL規則檔案, 新建會話等。
ps: 也可以使用其他的方式編譯,這裡只是為了簡單

KieHelper helper = new KieHelper();
helper.addContent(drl, ResourceType.DRL);
KieSession kieSession = helper.build().newKieSession();
kieSession.insert(new String("Hello, World!"));
kieSession.fireAllRules();
kieSession.dispose();

1.5 模板編譯示例

1.5.1 DRT模板檔案 template.drt

template header
condition
execution

package template

template "this is a test"

    rule "[email protected]{row.rowNumber}"
        when
            @{condition}
        then
            System.out.println(@{execution});
    end

end template

1.5.2 單元測試

public class Demo {
    static KnowledgeBuilder builder;
KieBase kieBase;

    @BeforeClass
    public static void beforeClass() {
        builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    }

    @Before
    public void setUp() {
        /**
         * 1. 從本地模板DRT檔案得到輸入流
         * 2. 建立一個 ArrayDataProvider , 二維陣列中元素按順序與DRT檔案中定義的變數一一對應
         * 3. 建立一個 DataProviderCompiler 物件用compile()方法渲染, 將二維陣列中的元素一一填充到DRT模板中, 得到DRL(規則)字串
         * 4. 載入DRL(規則)字串
         */
        String pathToDrt = "E:\\template.drt";
        try (InputStream stream = new FileInputStream(pathToDrt)) {
            DataProvider dataProvider = new ArrayDataProvider(new String[][]{
                    new String[]{"String(this == \"規則條件\")", "\"規則動作\""}
            });
            DataProviderCompiler compiler = new DataProviderCompiler();
            String DRL = compiler.compile(dataProvider, stream);
            System.out.println("-----模板DRT渲染後的DRL-----");
            System.out.println(DRL);
            System.out.println("-----模板DRT渲染後的DRL-----");
            byte[] drlBytes = DRL.getBytes("UTF-8");
            Resource resourceTemplate = ResourceFactory.newByteArrayResource(drlBytes);
            builder.add(resourceTemplate, ResourceType.DRL);
        } catch (IOException e) {
            e.printStackTrace();
        }
        builder.add(resourceNative, ResourceType.DRL);
//        builder.add(resourceRemote, ResourceType.DRL);
        kieBase = builder.newKieBase();
    }

    @Test
    public void testTemplate() {
        KieSession kieSession = kieBase.newKieSession();
        kieSession.insert("規則條件");
        kieSession.fireAllRules();
        kieSession.dispose();
    }
}

1.5.3 輸出

-----模板DRT渲染後的DRL-----
package template
rule “test_0”
when
String(this == “規則條件”)
then
System.out.println(“規則動作”);
end
-----模板DRT渲染後的DRL-----
規則動作

2 本地載入與遠端載入

2.1 建立本地DRL檔案

建立遠端的DRL檔案,地址為 E:\native.drl

package rules.native;
dialect  "mvel"

rule "native"
    when
    then
        System.out.println("本地載入成功");
end

2.2 建立遠端DRL檔案

建立遠端的DRL檔案,地址為 http://localhost:8761/remote.drl

package rules.remote;
dialect  "mvel"

rule "remote"
    when
    then
        System.out.println("遠端載入成功");
end

2.3 單元測試

public class Demo {

    static KnowledgeBuilder builder;
    KieBase kieBase;

    @BeforeClass
    public static void beforeClass() {
        builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    }

    @Before
    public void setUp() {
        /**
         * 本地載入DRL
         */
        Resource resourceNative = ResourceFactory.newFileResource("E:\\native.drl");
        /**
         * 遠端載入URL
         */
        String url = "http://localhost:8761/remote.drl";
Resource resourceRemote = ResourceFactory.newUrlResource(url );
// 載入方式的不同
builder.add(resourceNative, ResourceType.DRL);
builder.add(resourceRemote, ResourceType.DRL);
    }

    @Test
    public void testNativeAndRemote() {
        KieSession kieSession = kieBase.newKieSession();
        kieSession.fireAllRules();
        kieSession.dispose();
    }}

2.4 輸出

遠端載入成功
本地載入成功

3 總結

關鍵API:
Resource: 資源類,規則檔案的載入
KnowledgeBuilder: 收集編譯已經編寫好的規則檔案(drl)

從整體的收集、編譯、執行上看,遠端載入與本地載入大同小異,無非就是在使用Resource時載入規則檔案上的不同。使用模板則在此基礎上,需要將模板(drt)編譯成規則(drl)。