大家好,欢迎来到IT知识分享网。
- 规则读取和修改数据的不同方法
- 规则配置属性和全局变量
- 规则执行控制机制
通过全局变量进行外部交互
为了能够与规则引擎环境之外的系统、数据进行交互,Drools提供了很多方法,其中全局变量便是其中一种。
global EShopConfigService configService;
IT知识分享网
修改工作内存空间中的数据
由于Drl是基于描述的编程语言的,所以它没有办法提供一个drl访问另一个drl的方式,所以为了能够将规则拆分为更小的规则,Drools可以在数据发生变化以后重新评估和执行规则。
insert
IT知识分享网rule "Classify Customer - Gold"
when
$c: Customer( category == Customer.Category.GOLD ) then
insert(new IsGoldCustomer($c));
end
rule "Classify Item - Low price" when
$i: Item(cost < 10.00) then
insert(new IsLowRangeItem($i));
end
rule "Suggest gift"
when
IsGoldCustomer($c: customer)
IsLowRangeItem($i: item)
then
System.out.println("Suggest giving a gift of item "+$i. getName()+" to customer +"$c.getName());
end
对于黄金用户,如果我们有小于10块钱的礼物,则可以赠送一个给他
对于这样一个规则,我们把它拆分为三个小的规则:
- 判断黄金用户
- 判断礼物
- 判断赠送
通过insert关键字修改数据并触发其他规则的执行。
modify和update
对于已存在的数据,通过修改和更新也可以触发规则执行。
rule "Categorize Customer - Gold" when
$c: Customer( category == Customer.Category.NA )
$o: Order(customer == $c, orderLines.size() > 10) then
modify($c){
setCategory(Customer.Category.GOLD);}
end
IT知识分享网$c.setCategory(Customer.Category.GOLD);
update($c);
delete和retract(已过时)
删除工作内存中的数据
rule "Init current date"
when
then insert(new Date());
end
rule "Expire coupons"
when
$now: Date()
$cp: Coupon( validUntil before $now )
then
delete($cp);
end
rule "Execute coupon"
when
$o: Order()
$cp: Coupon(order == $o) then
System.out.println("We have a coupon for this order!"); end
规则属性
Drools是数据驱动的,但是也提供了规则属性进行规则的控制和过滤。
enable“
rule "simple attribute example"
enabled false
when Customer()
then System.out.println("we have a customer"); end
enable设置为false,则对应的规则会被计算但不会被执行。
salience
设置规则的优先级,可以正数或负数,值越大优先级越高
agenda-group
可以对规则进行分组
rule "Promotion: more than 10 pencils get 10% discount"
agenda-group "promotions"
when
OrderLine(item.name == "pencil", quantity > 10)
then
...
end
KieSession ksession = ...;
ksession.getAgenda().getAgendaGroup("promotions").setFocus();
ksession.fireAllRules();
值得注意的是,当规则触发以后,还可以继续通过kcontext定义agenda-group
rule "Done with promotions. Onward with printing invoice"
salience -100 //last rule of group to run
agenda-group "promotions"
when
OrderLine()
then
kcontext.getKnowledgeRuntime().getAgenda(). getAgendaGroup("MAIN").setFocus();
end
控制规则循环
rule "Apply 10% discount on notepads"
when $i: Item(name == "notepad", $sp: salePrice)
then modify($i) {
setSalePrice($sp * 0.9); }
end
modify关键字会触发规则继续执行,陷入死循环。
no-loop
rule "Apply 10% discount on notepads BUT ONLY ONCE"
no-loop true
when $i: Item(name == "notepad", $sp: salePrice)
then modify($i) {
setSalePrice($sp * 0.9); } end
no-loop属性可以防止由于规则自身触发的重新执行,这里要强调的是no-loop只会防止最后一个规则的同一数据引起的重复,如果另外一个规则修改了工作内存中的数据,它还是会第二次执行。
lock-on-active
最快的一种阻止因同一对象被修改的循环触发的方式是添加Lock-on-active属性,它比no-loop有更强的限制循环作用,所有其他规则对数据修改都不会引起循环触发。
标志属性
如果数据很难被修改而无法重新触发规则,我们还可以通过添加标志属性存储检查条件,其他规则可以根据这些属性判断是否要重新执行。
rule "Add 2% discount for orders larger than $100"
when $o:
Order(total > 100.00, has100DollarsDiscount == false) then
modify($o){
increaseDiscount(0.02); setHas100DollarsDiscount(true);
} end
rule "Add 2% discount for orders larger than 15 items"
when $o:
Order(total > 100.00, has15ItemsDiscount == false) then
modify($o){
increaseDiscount(0.02); setHas15ItemsDiscount(true);
} end
声明类型
Drools的数据模型也可以通过类型声明定义在drl文件中
declare SpecialOrder extends Order
whatsSoSpecialAboutIt: String
order: Order
applicableDiscount: Discount
end
通过java的反射API,我们可以通过KieBase获取声明的类型:
KieSession ksession = ...; //previously initialized FactType type = ksession.getKieBase().getFactType(
"chapter04.declaredTypes", "SpecialOrder");
Object instance = type.newInstance();
type.set(instance, "relevance", 2L);
Object attr = type.get(instance, "relevance");
Property-reactive Beans
默认情况下是根据整个对象的属性是否被修改来评估规则是否要重新评估,但有些情况一个对象的某些属性修改不需要引起规则执行,这就需要在数据模型定义上使用property-reactive beans.
declare PropertyReactiveOrder
@propertyReactive
discount: Discount
totalItems: Integer
total: Double
end
rule "Larger than 20 items orders are special orders"
when
$o: PropertyReactiveOrder(
totalItems > 20
) @Watch (!discount)
then
modify ($o) {
setDiscount(new Discount(0.05));
} end
@Watch(discount, total) 只检查diacount和total
@Watch(!discount) 不检查discount
@Watch(!, total)除了total都不检查
@Watch(!, total, totalItems)除了total,totalitems都不检查
正则
matches
rule "validate customer emails"
when $c: Customer(email not matches
"[A-Za-z0-9-.]+@[A-Za-z0-9-.]+$")
then $c.setEmail(null); //invalidate email
end
contains memberOf
rule "print orders with pencils in them"
when
$i: Item(name == "pencil")
$ol: OrderLine(item == $i)
$o: Order($ol memberOf orderLines,
orderLines contains $ol)
then
System.out.println("order with pencils: " + $o); end
from
Drools提供from语句让我们可以在工作空间之外定义特殊的查询空间。
rule "For every notebook order apply points coupon"
when
$o: Order($c: customer, $lines: orderLines)
OrderLine($item: item) from $lines
Item(name == "notebook") from $item
then
insert(new Coupon($c, $o, CouponType.POINTS));
end
以上这种方式有以下优点:
1、拆分条件更易理解
2、可以对集合类型进一步检索
Collect from objects
以下规则每当插入一个Order后都会执行一次,如果插入50个对象,就会执行50次,效率比较低
rule "Simple order condition"
when $o: Order()
then System.out.println("order found: " + $o); end
可以使用collect减少到只执行1次
rule "Grouping orders"
when $list: List() from collect(Order())
then
System.out.println("we've found " + $list.size() + " orders");
end
accumulate
有时需要对匹配条件的数据进行转换,accumulate这个关键字可以
rule "10+ items with sale price over 20 get discount"
when
$o: Order($lines: orderLines)
Number(intValue >= 10) from accumulate(
OrderLine(
item.salePrice > 20.00, $q: quantity
)
from $lines,
init(int count = 0;),
action(count += $q), r
everse(count -= $q),
result(count)
)
then
$o.increaseDiscount(0.05);
end
not
工作内存空间中不存在查询可以使用Not
rule "warn about empty working memory"
when
not(Order() or Item())
then
System.out.println("we don't have elements");
end
exists
exists用来检查工作空间中是否存在满足条件的对象
左边无论有多少Order只执行一次,右边一个Order执行一次。
forall
forall用来设置满足多个条件
rule "make sure all orders have at least one line"
when
exists(Order())
forall(
Order()
Order(orderLines.size() > 0)
)
then
System.out.println("all orders have lines");
end
语法糖
- 嵌套访问
OrderLine( item.cost < 30.0, item.salePrice < 25.0 )
OrderLine( item.( cost < 30.0,salePrice < 25.0) )
- Inline casts
类型转换
Order(customer#SpecialCustomer.specialDiscount > 0.0)
Trait
traits可以被看作一些可以动态添加到对象的属性,要使用trait,需要以下两步:
1、定义trait
declare trait KidFriendly
kidsAppeal: String
end
2、对类添加@Traitable注解
使用don 关键字添加 添加traits
rule "toy items are kid friendly"
no-loop
when
$i: TraitableItem(name contains "toy")
then
KidFriendly kf = don($i, KidFriendly.class);
kf.setKidAppeal("can play with it");
end
使用关键字shed去除traits
Object o = shed( $traitedObject, KidFriendly.class)
逻辑插入
逻辑插入将插入的数据和条件绑定,插入的条件不再满足的时候,数据就会在内存中自动被删除
rule "determine large orders"
when $o: Order(total > 150)
then insertLogical(new IsLargeOrder($o));
end
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/11678.html