本文将分享几种从drools外部访问drools工作内存中数据的方法。
实体类如下:
//客户
public class Customer {
private Integer id;
private String name;
private String level;
private double discount;//折扣率
private boolean freeParking;//是否免费停车
}
//商品
public class Goods {
private Integer id;
private String name;
private Double price;
private String unit;
}
//订单类
public class Order {
private Integer id;
private Integer custId;
private Double total;
private String state;
private List<Goods> goods;
}
//优惠券
public class Coupons {
private Integer id;
private String name;
private Integer custId;
private Integer orderId;
}
一、通过api方法插入的数据(即kieSession.insert(Object))
这种情况下,直接访问Object对应的变量就可以了。
Customer customer = new Customer();
customer.setId(1);
customer.setDiscount(0.0);
customer.setFreeParking(false);
customer.setName("杨杨");
kieSession.insert(customer);//插入数据到工作内存
kieSession.fireAllRules();//匹配执行规则
System.out.println(customer.getDiscount());//直接访问该变量即可获取变化后的数据
kieSession.dispose();//释放 kieSession资源
二、访问规则执行时加入到工作内容的数据
对于rule创建的实例,外部并没有引用变量,要想获取这些数据,就需要借助drools的api了。
案例:给消费金额达到100元的黄金会员发放免费停车券,优惠券下次可用。
对于上述案例,券是由规则创建生成并保存在工作内存中,而且下次可用,这时就需要将工作内存中的停车券取出并保存到数据库。生成免费停车券的规则如下:
rule "create coupons"
lock-on-active true
when
$c:Customer(level == 'gold')
$o:Order(custId == $c.id,total >= 100)//每个订单
then
Coupons coupons = new Coupons();
coupons.setCustId($c.getId());
coupons.setId((int)(Math.random()*1000));
coupons.setName("停车免费券");
coupons.setOrderId($o.getId());
insert(coupons);
System.out.println("发放一张优惠券");
end
1.通过kiesession.getObjects(new ClassObjectFilter(Class clazz))获取
Customer customer = new Customer();
customer.setId(1);
customer.setDiscount(0.0);
customer.setFreeParking(false);
customer.setLevel("gold");
customer.setName("杨杨");
kieSession.insert(customer);//插入客户数据到工作内存
Order order = new Order();
order.setId(10);
order.setCustId(1);
order.setTotal(100.00);
kieSession.insert(order);//插入订单数据到工作内存
Collection<Coupons> coupons = (Collection<Coupons>)kieSession.getObjects(new ClassObjectFilter(Coupons.class));
System.out.println("触发规则前,检索工作内存是否存在coupons:"+(coupons.size()>0));
kieSession.fireAllRules();//匹配执行规则
coupons = (Collection<Coupons>)kieSession.getObjects(new ClassObjectFilter(Coupons.class));
for(Coupons cs: coupons){
System.out.println("触发规则后,释放资源前检索工作内存:"+cs.toString());
}
kieSession.dispose();//释放 kieSession资源
执行结果如下:
触发规则前,检索工作内存是否存在coupons:false
发放一张优惠券
触发规则后,释放资源前检索工作内存:Coupons{id=987, name='停车免费券', custId=1, orderId=10}
2.使用Query查询工作内存
还可以使用query来查询工作内存,query定义在drl文件中,可以提供给rule或java项目调用。
⑴. 上述需求query写法如下:
query coupons //coupons 为query的名称,通过该名称调用query查询drools工作内存
$c:Coupons() //从工作内存中查询所有Coupons实例 注意这里应该绑定一个变量,api通过这个变量名称获取实例
end
java调用如下:
QueryResults queryResults = kieSession.getQueryResults("coupons");//coupons 为query的名称
//遍历查询结果
for(QueryResultsRow r: queryResults){
Coupons c = (Coupons) r.get("$c");//$c 为查询绑定的变量名称
System.out.println("后台query coupons is:"+c.toString());
}
执行结果:
后台query coupons is:Coupons{id=441, name='停车免费券', custId=1, orderId=10}
⑵. query还可以有参数,仍然是上述需求,查询指定人的优惠券,query写法如下:
query coupons(Integer cId)
$c:Coupons(custId == cId)
end
java调用如下:
QueryResults queryResults = kieSession.getQueryResults("coupons",1);//query名称,参数值
for(QueryResultsRow r: queryResults){
Coupons c = (Coupons) r.get("$c");
System.out.println("后台query coupons is:"+c.toString());
}
执行结果如下:
后台query coupons is:Coupons{id=444, name='停车免费券', custId=1, orderId=10}
⑶.有参的query还可以使用org.drools.core.runtime.rule.Variable.v忽略掉参数
java调用如下:
QueryResults queryResults = kieSession.getQueryResults("coupons", Variable.v);//此时查询Coupons时并未做任何条件限制,查询的是所有Coupons实例
for(QueryResultsRow r: queryResults){
Coupons c = (Coupons) r.get("$c");
System.out.println("后台query coupons is:"+c.toString());
}
query在rule中调用与调用function时一样,但是query并不能绑定变量,也不想不明白怎么在rule条件中遍历查询结果,如果不能遍历query结果的话,query到底有什么用,query这么麻烦还得定义,有kieSession.getObjects()方法完全够用了。实际开发中没用过query,体会不到用它的好处是什么,学无止境啊。