本文将简介package、import组件,会较多的介绍function组件。
一、package和import
这么大的标题,其实没什么可介绍的。本来也没想写这两部分,但是为了完整,还是凑了两句。
package 实际就是一个符合java命名规范的域名,多个drl文件可重复使用,namespace跟drl文件的保存路径并没有关系,可任意定义,但是位置必须是声明在文件的顶部。在被其他drl文件引用时、规则单元分组时有很大的用处。
import用于引用java项目或其他依赖包中的类库、引用其他drl文件中的function等资源。
二、function
function虽然作为本文的介绍重心,但是用法却是极其的简单易懂,与java中的方法一样,可以有入参和返回值,根据方法签名调用function。when和then中都可以调用function,其作用就是提高代码重复利用率。但我在实际使用过程中却发现,往往在较复杂的条件逻辑判断时function特别有用。
首先,还是简单的示例:
package rules;
import com.helloworld.bean.Student
function String printFun(String name){
return "hello,"+name;
}
rule "rule"
when
Student($n:name)
then
System.out.println(printFun($n));
end
简单的示例仅适合入门了解,以前的文章写过一个用function校验日期时间段的例子,这里简化一下拿来做个说明吧。
示例:某商场为了吸引客户消费,决定在4月1日到4月30日给予到店客户9折优惠。
定义实体类如下:
public class Customer {
private Integer id;
private String name;
private double discount;//折扣率
private boolean freeParking;//是否免费停车
}
数据如下:
//规则文件,生成知识库并创建会话
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession();
//创建并插入源数据
Customer customer = new Customer();
customer.setId(1);
customer.setDiscount(0.0);
customer.setFreeParking(false);
customer.setName("杨杨");
kieSession.insert(customer);
//规则校验
kieSession.fireAllRules();
//释放资源,关闭会话
kieSession.dispose();
规则定义如下:
package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
//校验时间
function boolean dateFunc(){
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = sdf.parse("2020-04-01");
Date date2 = sdf.parse("2020-04-30");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
}
rule "rule"
//date-effective "2020-04-01"
//date-expires "2020-04-30"
when
eval(dateFunc())
$c:Customer()
then
$c.setDiscount(0.90);
System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");
end
执行结果如下:
尊敬的杨杨,您将享受9.0折优惠!
当然上述示例使用 date-effective 和 date-expires 两个属性更方便,但是这两个属性只能控制日期区间,如果更细化判断就有点力不从心了。下面将对上述需求做出修改如下:
示例:
优惠一:4月1日至4月30日给予客户9折优惠;
优惠二:同时为了避免早晚高峰期,过多的客户到店消费造成拥堵,商场提出提出另一项优惠,每天14:00至16:00免费停车
除了校验日期,还需要对时间段做出判断。规则如下:
package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
import java.util.Calendar
function boolean dateFunc(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(sdf.format(new Date()));
Date date1 = sdf.parse("2020-04-01");
Date date2 = sdf.parse("2020-04-30");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
}
function boolean timeFunc(){
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
// Date date = sdf.parse(sdf.format(new Date()));
//写案例的时候已经18点了,这里就伪造个时间点吧
Date date = sdf.parse("15:30:10");
Date date1 = sdf.parse("14:00");
Date date2 = sdf.parse("16:00");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
}
rule "rule"
when
eval(dateFunc())
$c:Customer()
do[discount]
eval(timeFunc())
then
$c.setFreeParking(true);
System.out.println("尊敬的"+$c.getName()+",您本次停车免费");
then[discount]
$c.setDiscount(0.90);
System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");
end
运行结果如下:
尊敬的杨杨,您将享受9.0折优惠!
尊敬的杨杨,您本次停车免费
还可以通过 import function 引入静态java方法,与global相似,但是它只能引用静态方法,下面用import function写出上述示例:
静态方法如下:
package com.helloworld.service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateService {
public static boolean dateFunc(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(sdf.format(new Date()));
Date date1 = sdf.parse("2020-04-01");
Date date2 = sdf.parse("2020-04-30");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
} catch (ParseException e) {
e.printStackTrace();
return false;
}
}
}
规则文件如下:
package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
//引入java静态类
import function com.helloworld.service.DateService.dateFunc
/*function boolean dateFunc(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(sdf.format(new Date()));
Date date1 = sdf.parse("2020-04-01");
Date date2 = sdf.parse("2020-04-30");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
}*/
function boolean timeFunc(){
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
// Date date = sdf.parse(sdf.format(new Date()));
Date date = sdf.parse("15:30:10");
Date date1 = sdf.parse("14:00");
Date date2 = sdf.parse("16:00");
if(date.after(date1) && date.before(date2)){
return true;
}
return false;
}
rule "rule"
when
eval(dateFunc())
$c:Customer()
do[discount]
eval(timeFunc())
then
$c.setFreeParking(true);
System.out.println("尊敬的"+$c.getName()+",您本次停车免费");
then[discount]
$c.setDiscount(0.90);
System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");
end
运行结果如下:
尊敬的杨杨,您将享受9.0折优惠!
尊敬的杨杨,您本次停车免费
function的作用还是挺大的,还可以用它来做集合遍历、数据预处理等等,更多的应用场景等着各位去发现。