规则引擎 Drools 模板编译
1.模板编译
1.1依赖
1 2 3 4 5
| <dependency> <groupId>org.drools</groupId> <artifactId>drools-templates</artifactId> <version>7.7.0.Final</version> </dependency>
|
1.2建立模板
新建模板文件 test.drt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template header condition execution
package template
template "this is a test"
rule "test_@{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, 示例
1 2 3 4 5 6 7
| InputStream templateStream = DataDrivenTemplateExample.class.getResourceAsStream("/rules/SimpleTemplateExample.drt");
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: 也可以使用其他的方式编译,这里只是为了简单
1 2 3 4 5 6
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template header condition execution
package template
template "this is a test"
rule "test_@{row.rowNumber}" when @{condition} then System.out.println(@{execution}); end
end template
|
1.5.2 单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class Demo { static KnowledgeBuilder builder; KieBase kieBase;
@BeforeClass public static void beforeClass() { builder = KnowledgeBuilderFactory.newKnowledgeBuilder(); }
@Before public void setUp() {
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);
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
1 2 3 4 5 6 7 8
| package rules.native; dialect "mvel"
rule "native" when then System.out.println("本地加载成功"); end
|
2.2 创建远程DRL文件
创建远程的DRL文件,地址为 http://localhost:8761/remote.drl
1 2 3 4 5 6 7 8
| package rules.remote; dialect "mvel"
rule "remote" when then System.out.println("远程加载成功"); end
|
2.3 单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class Demo {
static KnowledgeBuilder builder; KieBase kieBase;
@BeforeClass public static void beforeClass() { builder = KnowledgeBuilderFactory.newKnowledgeBuilder(); }
@Before public void setUp() {
Resource resourceNative = ResourceFactory.newFileResource("E:\\native.drl");
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)。