規則引擎 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)。