Drools入门之规则模板

规则引擎中,Drools提供了一个规则模板的概念,规则模板是指规则条件比较值是可变的,且可生成多个规则进行规则调用。规则模板可以分为两种:官方提到的以drt扩展名+xls(源数据)的方式和API模板赋值方式。

drt扩展名+xls方式

首选创建一个ExampleCheese.xls文件,其内容如下:

image-20220727145610734

新建Cheese.drt,其内容如下:

template header
age
className

package rules.isDrt

import com.domain.Person

template "cheesefans"

rule "cheese fans_@{row.rowNumber}"
no-loop true
when
    $p:Person(age==@{age})
then
    $p.setClassName("@{className}");
    update($p);
    System.out.println($p);
end
end template

修改kmodule.xml配置文件

<kbase name="drt" packages="rules.isDrt">
    <ruleTemplate dtable="rules/isDrt/ExampleCheese.xlsx" template="rules/isDrt/Cheese.drt" row="2" col="1"/>
    <ksession name="testDrt"/>
</kbase>

创建测试方法:

@Test
public void testDrt() {
    KieServices kieService = KieServices.Factory.get();
    KieContainer kieContainer = kieService.getKieClasspathContainer();
    KieSession kieSession = kieContainer.newKieSession("testDrt");

    Person person = new Person();
    person.setName("张三");
    person.setAge(30);
    kieSession.insert(person);
    kieSession.fireAllRules();
    kieSession.dispose();
}

规则模板文件以template header开头,以end template结尾。

然后其中:age,className代表的是xls中的列映射名称。如第一列映射的名称为age。

template “cheesefans””为模板名称,是唯一的,关键字template表示一个规则模板的开始,一个规则模板中可以有多个模板。

@{row.rowNumber}”是模板中的一个函数,用来让规则名唯一。

“@{age}”““@{className}””是对应age、className的,是最终获取数据源中参数值的。

其中@{className}加了引号,是因为setClassName()方法需要的类型为字符串。

Kmodule.xml文件中,row/col开始的行、列起,每一行都是一条规则。row=2,相当于从第二行开始读取数据。

API方式

@Test
public void testIsDRTAPI() {
    ObjectDataCompiler converter = new ObjectDataCompiler();
    //赋值 给模板属性
    Person person = new Person();
    person.setAge(50);
    person.setClassName("一班");
    Collection<Person> cfl = new ArrayList<Person>();
    cfl.add(person);//每add一次,就代码一条规则
    InputStream dis = null;
    try {
        dis = ResourceFactory.newClassPathResource("rules/isDrt/Cheese.drt", this.getClass()).getInputStream();
    } catch (IOException e) {
        e.printStackTrace();
    }
    String drl = converter.compile(cfl, dis);
    System.out.println(drl);
    KieHelper helper = new KieHelper();
    helper.addContent(drl, ResourceType.DRL);
    KieSession ksession = helper.build().newKieSession();
    Person ps = new Person();
    ps.setAge(50);
    person.setName("张三");
    ksession.insert(ps);
    int i = ksession.fireAllRules();
    System.out.println(ps.getClassName() + "   " + i + "次");
    ksession.dispose();
}

运行结果

package rules.isDrt
import com.domain.Person

rule "cheese fans_0"
no-loop true
when
    $p:Person(age==50)
then
    $p.setClassName("一班");
    update($p);
    System.out.println($p);
end

2022-43-27 03:43:26 [INFO ] org.drools.....KieRepositoryImpl - KieModule was added: MemoryKieModule[releaseId=org.default:artifact:1.0.0]
Person{age=50, name='null', className='一班'}
一班	1次

通过这种API的方式,可以对代码进行一个封装。

ObjectDataCompiler:调用规则模板的一个工具类。

Collection cfl:指给规则模板赋值的参数,一个元素就代表一个规则。

ResourceFactory:加载规则模板文件。converter.compile(cfl, dis):把规则文件与参数合并,生成drl文件。


Drools入门之规则模板
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/drools-rule-template
作者
卑微幻想家
发布于
2022-07-28
许可协议