关于Drools:
Drools是jboss的一款开源的业务规则引擎,具有速度快、效率高、易学习的特点。
本文内容参考自Drools 官方文档 7.9.0.Final版
https://docs.jboss.org/drools/release/7.9.0.Final/drools-docs/html_single/index.html
让我们从使用驾驶执照申请的一个非常简单的例子开始。
(1)首先我们需要创建一个maven项目,需要添加的依赖为:
<dependency>
<groupId>org.droolsgroupId>
<artifactId>drools-compilerartifactId>
<version>7.5.0.Finalversion>
dependency>
(2)接着我们需要创建一个POJO类
public class Applicant {
private String name;
private int age;
private boolean valid;
// getter and setter methods here
}
现在我们有了数据模型,我们可以开始编写第一条规则。由于这是一个简单的验证用例,我们将添加一条规则来取消任何年龄小于18岁的申请人的资格。
package org.drools.examples.helloworld.entity
rule "Is of valid age"
when
$a : Applicant(age>18)
then
$a.setValid(true);
end
我们需要将上面的内容放到src\mian\resources目录下,并将其命名为 .drl格式的文件。
drl 即Drools Rule Language。在这里我们将其命名为license.drl,同时,在我们的maven项目中还需要创建一个kmodule.xml,这个文件需要放到resources\META-INF文件夹下,由于Drools 已为我们提供有意义的默认值,因此最简单的kmodule.xnl只需要包含一个空的kmodule标签即可,如下所示:
<kmodule xmlns="http://www.drools.org/xsd/kmodule"/>
我们接着看上面的drl文件,会发现它和java的语法非常类似。
package : 所用到的pojo类的位置
rule : 规则名称,这里可以是任意值,但需要保持唯一性
when…then…end : 当满足某种条件时,就如何如何,以end做结尾
$a
: $a
是一个绑定变量,它允许我们的引用匹配的对象,美元字符$
是可选的,用于区分变量名和字段名,在这里绑定一个变量用的是 “:”
Applicant( age < 18 ) : Applicant 则是我们的数据模型,age<18则是判断条件
(3)调用规则,使规则生效
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
上面这段代码使我们在类路径下找到所有的DRL文件,并将此编译的结果kiemodule放到 kieContainer中。如果没有错误,我们现在可以从kiecontainer中执行一些数据:
StatelessKieSession kieSession = kieContainer.newStatelessKieSession();
Applicant app = new Applicant();
app.setName("liuyang");
app.setAge(19);
Assert.assertFalse(app.isValid());
System.out.println("执行规则前:"+app.toString());
kieSession.execute(app);
System.out.println("执行规则后:"+app.toString());
Assert.assertTrue(app.isValid());
上述例子只对申请人的年龄做了处理,若此时想对申请日期做判断的话该如何处理呢?Drools实现了对多个实例对象的判断。此时我们将Applicant中的valid移到Application中。
public class Applicant {
private String name;
private int age;
// 省略 get set
}
public class Application {
private String dateApplied;
private boolean valid;
// 省略 get set
}
我们再添加另一条规则来验证其申请日期是否在我们规定的范围。
package org.drools.examples.helloworld.exam2
rule "Is of valid age"
when
Applicant( age > 18 )
$a : Application()
then
$a.setValid(true);
end
rule "Application was made this year"
when
$a : Application(dateApplied > "2018-01-01" )
then
$a.setValid(false);
end
通过Arrays.asList(…)将这两个实例放入集合中,按照放入的顺序执行drl中的规则
public class MyTest {
public static void main(String[] args) {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
StatelessKieSession kieSession = kieContainer.newStatelessKieSession();
Applicant applicant = new Applicant("liuyang", 20);
Application application = new Application();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
application.setDateApplied(df.format(new Date()));
System.out.println("执行规则前:" + application.toString());
kieSession.execute(Arrays.asList(applicant , application ));
System.out.println("执行规则后:" + application.toString());
}
}
由于Arrays.asList中先放入的是applicant,因此会先执行”Is of valid age”这条规则,因为20>18,因此此时的valid为true。接着执行”Application was made this year”这条规则,此时日期为2018-08-11,大于规则中的2018-01-01,因此valid为false.