Drools 7 规则引擎执行控制之rule units对规则的协调执行

 

 

单独写一下rule units吧,rule units也是执行控制中的一部分,这一块儿的内容比较丰富也挺有意思。

一、简述

rule units 需要实现RuleUnit接口,它由运行时数据(date sources of facts),globals,DRL rules 和function组成。可以将一组rules 划分为更小的 rule units,然后逐个执行rule units。rule units之间可以互相调用,一个ruleUnit的执行可以触发另一个ruleunit 的启动,对协调规则的执行很有效。因此 rule units挺适合有一些严格流程的业务场景。例如:我们去人群聚集的场所时需要先通过安检或防疫检测,达到某种消费金额后可以获得折扣,消费满一定金额后可以获得免费停车券,等等

二、示例:去逛商场,进商场前需要通过防疫检测获得健康认证后方可入内,医护人员可享受8折优惠,实际消费金额满500元可获得免费停车券,停车券仅限当日使用。这需求,很明显各步骤是要严格按照顺序执行的,当然可以根据优先级高低设置salience 属性就可以实现的,但是我在实际开发中觉得salience这东西挺难维护的,比如,中间我需要增加一个环节,我需要控制商场内人数时,如果开始各rule 的salience属性值之间并未设置间隔,这里就得重新调整salience,牵一发而动全身。那如果不用salience,而是借助rule units在规则执行完成的时候指定下一个该谁执行,当中间需要增加一个环节时,我就只需要像在单向链表中插入元素一样加入新规则,再调整前一个规则的调用就可以了。

啰嗦这么多其实我是没想出一个合适的场景去演示了,当然这也不是本文的重点(乱套了),本文重点还是介绍rule units 的使用方法,除了salience还有另一种方法去实现上述场景。

1. 来吧展示

构建实体模型

//职业
public class Profession {
    private Integer id;
    private String name;
    private String rank;
    private String type;//类型 0-医护;1-其他
    ...
}

//健康卡
public class HealthCard {
    private Integer custId;
    private String name;
    private String state;//0-健康;1-抱恙
    ...
    //getter、setter 
}

//优惠券
public class Counpons {
    private Integer id;
    private String type;//券种类,0-停车券;1-消费券
    private Date start;//有效期(开始时间)
    private Date end;//有效期(截止时间)
    private String state;//券状态0-可用;1-核销;2-作废
    private Double discount;//折扣比例,免费就配成1.00 吧
    ...
}

//客户
public class Customer {
    private Integer id;
    private String name;
    private List<Counpons> counpons;
    private Profession profession;//职业,主业就行了,就不考虑你兼职了
    private HealthCard healthCard;//健康卡
    ...
    ...
}


//商品
public class Good {
    private Integer id;
    private String name;
    private String categery;
    private Double price;
    private String unit;//计量单位
    ...
}

//订单明细
public class Item {
    private Integer id;
    private Integer oId;//归属订单
    private Good good;
    private Double count;//数量
    private double discount;
    ....
}

//订单主表
public class Order {
    private Integer id;
    private Integer custId;
    private Date create;
    private List<Item> goods;
    private Double total;//总计
    private Double pay;//应付
    private Double discount;//共计优惠
    //private String state;//0-未结算;1-结算
    private List<Counpons> counpons;//优惠凭证
    ...
}

创建 rule units

//package很重要,拥有的DRL源文件的package 须要与这里保持一致,硬性要求
package com.helloworld.bk.ruleUnits.units; 

import com.helloworld.bk.ruleUnits.entity.Counpons;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

import java.util.List;

public class MarketUnits implements RuleUnit {
    //一般用于存储 facts 
    private DataSource<Object> data;
    //rule unit 内全局变量
    private List<Counpons> counpons;

    public List<Counpons> getCounpons() {
        return counpons;
    }

    public DataSource<Object> getData() {
        return data;
    }
    /**
    *units 开始执行时
    */
    @Override
    public void onStart() {
        System.out.println("购物开始");
    }
    /**
    *units 执行结束时
    */
    @Override
    public void onEnd() {
        System.out.println("购物结束");
    }
    /**
    *调用其他units时
    */
    @Override
    public void onYield(RuleUnit other) {
        System.out.println(this.getUnitIdentity() +",调用了,"+this.getUnitIdentity());
    }
}

 职业调研

package com.helloworld.bk.ruleUnits.units;

import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

public class ProfessionUnits implements RuleUnit {
    private DataSource<Object> data;

    public ProfessionUnits() { }

    public ProfessionUnits(DataSource<Object> data) {
        this.data = data;
    }

    public DataSource<Object> getData() {
        return data;
    }

    @Override
    public void onStart() {
        System.out.println("职业调研规则开始");
    }

    @Override
    public void onEnd() {
        System.out.println("职业调研规则结束");
    }

    @Override
    public void onYield(RuleUnit other) {
        System.out.println(this.getUnitIdentity()+",调用,"+other.getUnitIdentity());
    }
}

防疫检测

package com.helloworld.bk.ruleUnits.units;

import com.helloworld.bk.ruleUnits.entity.Customer;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

public class HealthUnits implements RuleUnit {
    private DataSource<Object> data;//用于存储所有运行时数据(facts),可以定义多个,这里就不考虑那么多了
    private Integer num;//商场内人数
    private Integer maxNum;//商场内最多容纳人数

    public HealthUnits(){}

    public HealthUnits(DataSource<Object> data, Integer num, Integer maxNum) {
        this.data = data;
        this.num = num;
        this.maxNum = maxNum;
    }

    public DataSource<Object> getData() {
        return data;
    }

    public Integer getNum() {
        return num;
    }

    public Integer getMaxNum() {
        return maxNum;
    }


    @Override
    public void onStart() {
        //开始执行 rule units 时
        System.out.println(" 防疫检测执行开始");
    }

    @Override
    public void onEnd() {
        //执行完成 rule units 时
        System.out.println(" 防疫检测执行结束");
    }

    @Override
    public void onYield(RuleUnit other) {
        //调用其rule units 时
        System.out.println(this.getUnitIdentity()+",调用,"+other.getUnitIdentity());
    }
}

 计算优惠

package com.helloworld.bk.ruleUnits.units;

import com.helloworld.bk.ruleUnits.entity.Counpons;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

import java.util.List;

public class DiscountUnits implements RuleUnit {
    private DataSource<Object> data;//用于存储所有运行时数据(facts),可以定义多个,这里就不考虑那么多了
    private List<Counpons> counpons;
    public DiscountUnits(){}

    public DiscountUnits(DataSource<Object> data,List<Counpons> counpons) {
        this.data = data;
        this.counpons = counpons;
    }
    public DataSource<Object> getData() {
        return data;
    }

    public List<Counpons> getCounpons() {
        return counpons;
    }

    @Override
    public void onStart() {
        //开始执行 rule units
        System.out.println(" 优惠规则执行开始");
    }

    @Override
    public void onEnd() {
        //执行完成 rule units
        System.out.println(" 优惠规则执行结束");
    }
    @Override
    public void onYield(RuleUnit other) {
        System.out.println(this.getUnitIdentity()+",调用,"+other.getUnitIdentity());
    }
}

 核销优惠券

package com.helloworld.bk.ruleUnits.units;

import com.helloworld.bk.ruleUnits.entity.Counpons;
import org.kie.api.runtime.rule.RuleUnit;

import java.util.List;

public class ChargeOffUnits implements RuleUnit {
    private List<Counpons> counpons;

    public List<Counpons> getCounpons() {
        return counpons;
    }

    @Override
    public void onStart() {
        System.out.println("核销优惠券开始");
    }

    @Override
    public void onEnd() {
        System.out.println("核销优惠券结束");
    }

    @Override
    public void onYield(RuleUnit other) {
        System.out.println(this.getUnitIdentity()+",调用,"+other.getUnitIdentity());
    }
}

停车

package com.helloworld.bk.ruleUnits.units;

import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

public class ParkUnits implements RuleUnit {
    private DataSource<Object> data;

    public DataSource<Object> getData() {
        return data;
    }

    @Override
    public void onStart() {
        System.out.println(" 停车费规则开始");
    }

    @Override
    public void onEnd() {
        System.out.println(" 停车费规则结束");
    }
    @Override
    public void onYield(RuleUnit other) {
        System.out.println(this.getUnitIdentity()+",调用,"+other.getUnitIdentity());
    }
}

DRL文件

package com.helloworld.bk.ruleUnits.units;
unit MarketUnits
import com.helloworld.bk.ruleUnits.entity.*
rule come_in
    salience 10
    when
        $c:Customer() from data
    then
        System.out.println( "欢迎 "+$c.getName() + " 光临!");
        drools.run(HealthUnits.class);//强制中断执行当前rule unit,并启动HealthUnits
end

rule leave

    when
        $c:Customer() from data
        $o:Order(custId == $c.id,pay >= 500.00) from data
    then
        //System.out.println("消费已满500元");
        drools.run(ParkUnits.class);

end

防疫检测 

package com.helloworld.bk.ruleUnits.units //package 必须要与drl归属rule units的包名一致
unit HealthUnits //声明本drl文件归属 rule units
import com.helloworld.bk.ruleUnits.entity.*

rule health_0
    salience 10
    when
        //data为HealthUnits的data属性,意思是,查询当前客户是否持有健康卡,且身体健康
        $c:Customer(healthCard.custId == id, healthCard.state == '0') from data
    then
        System.out.println($c.getName() + "身体健康,允许入内,购物愉快");
        drools.run(ProfessionUnits.class);
        drools.run(DiscountUnits.class);
end

 职业调研

package com.helloworld.bk.ruleUnits.units;
unit ProfessionUnits
import com.helloworld.bk.ruleUnits.*
import java.util.Date
function boolean test(Customer c){
    System.out.println("function 运行:"+c.getProfession().getType());
    return true;
}
rule "profession"
    when
        $c:Customer(healthCard.custId == id, healthCard.state == '0',profession.type == '0') from data

    then
            Counpons c = new Counpons();
            c.setId(1);
            c.setType("1");
            c.setStart(new Date());
            c.setEnd(new Date());
            c.setState("0");
            c.setDiscount(0.80);
            $c.getCounpons().add(c);
            System.out.println("医护工作者获得8折优惠券一张");
end

优惠计算 

package com.helloworld.bk.ruleUnits.units
unit DiscountUnits
import com.helloworld.bk.ruleUnits.entity.*
import java.util.Date
import java.math.BigDecimal

rule discount_0
    salience 10
    when
        $c:Customer() from data
        $coup:Counpons(type == '1',state == '0',end >= new Date()) from $c.counpons
        $o:Order(custId == $c.id) from data
        $i:Item(oId == $o.id,$g:good) from $o.goods
        do[discount] //这里利用的是drools 的 extends
        //挺别扭的其实,应该是计算完成以后再核销券的,但实际规则在计算第一件商品优惠后就核销了,知道什么意思就行了,流程上我就不细抠了
        not (Counpons(id == $coup.id) from counpons)
    then
       counpons.add($coup);
       drools.run(ChargeOffUnits.class);
    then[discount]
        BigDecimal gp = BigDecimal.valueOf($g.getPrice());
        BigDecimal ic = BigDecimal.valueOf($i.getCount());
        BigDecimal cd = BigDecimal.valueOf(1-$coup.getDiscount());

        //double discount = $g.getPrice() * $i.getCount() * (1-$coup.getDiscount());
        double discount = gp.multiply(ic).multiply(cd).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        $i.setDiscount(discount);
        $o.setPay($o.getPay() - discount);
        $o.setDiscount($o.getDiscount() + discount);
        System.out.println($g.getName() +",优惠了"+discount+" 元");
end

 优惠券核销

package com.helloworld.bk.ruleUnits.units;
unit ChargeOffUnits

rule "chargeOff"
    when
       $c:Counpons(state == '0') from counpons
    then
        $c.setState("1");
        System.out.println("核销优惠券");
end

停车费用

package com.helloworld.bk.ruleUnits.units;
unit ParkUnits


rule parking
    when
        eval(true)
    then
        System.out.println("免费停车");
end

 

数据准备

public class Service {
    public Order createOrder(Integer custId){
        List<Item> items = new ArrayList<Item>(){{
            add(new Item(1,1,new Good(1,"猪肉","肉类",40.00,"kg"),1.00,0.00));
            add(new Item(2,1,new Good(2,"大葱","肉类",6.00,"kg"),1.00,0.00));
            add(new Item(3,1,new Good(3,"老陈醋","调料",6.90,"壶"),1.00,0.00));
        }};
        Order order = new Order();
        order.setCustId(custId);
        order.setCreate(new Date());
        order.setId(1);
        order.setDiscount(0.00);
        order.setPay(52.90);
        order.setGoods(items);
        order.setTotal(52.90);
        return order;
    }
}

规则调用

KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
//将DRL文件等资产构建知识库
KieBase kb = kc.getKieBase();
//RuleUnitExecutor 绑定知识库
RuleUnitExecutor executor = RuleUnitExecutor.create().bind(kb);

List<Object> data = new ArrayList<>();
Profession p = new Profession(1,"医护","","0");
Customer c = new Customer(1,"y先生",null,p,new HealthCard(1,"健康卡","0"));
data.add(c);
Service service = new Service();
Order o = service.createOrder(c.getId());
//由于多个rule units 之间共享同一个DataSource,所以运行时数据采用以下方式加入到drools
//多个(组)数据绑定到同一个DataSource上,当units中有DataSource 类型 且名称为“data”时,都可以访问该值,也就是具有以上提到的属性的units之间共享该数据,其他units对数据的修改也是可见的。
executor.newDataSource("data",o,c);
//绑定非DataSource变量
executor.bindVariable("counpons",new ArrayList());
executor.run(MarketUnits.class);
//打印结果
System.out.println("java application print customer:"+c.toString());
System.out.println("java application print order:"+o.toString());

执行结果

购物开始
欢迎 y先生 光临!
org.kie.api.runtime.rule.RuleUnit$Identity@6a5c4021,调用了,org.kie.api.runtime.rule.RuleUnit$Identity@6a5c4021
 防疫检测执行开始
y先生身体健康,允许入内,购物愉快
org.kie.api.runtime.rule.RuleUnit$Identity@c03c0f4f,调用,org.kie.api.runtime.rule.RuleUnit$Identity@a39fd0d4
职业调研规则开始
医护工作者获得8折优惠券一张
职业调研规则结束
 优惠规则执行开始
老陈醋,优惠了1.38 元
大葱,优惠了1.2 元
猪肉,优惠了8.0 元
org.kie.api.runtime.rule.RuleUnit$Identity@ad01d824,调用,org.kie.api.runtime.rule.RuleUnit$Identity@d37fb0f0
核销优惠券开始
核销优惠券
核销优惠券结束
 优惠规则执行开始
 优惠规则执行结束
 防疫检测执行开始
 防疫检测执行结束
购物开始
购物结束
java application print customer:Customer{id=1,name=y先生,counpons=[Counpons{id=1, type='1', start=Sat Nov 28 16:03:53 GMT+08:00 2020, end=Sat Nov 28 16:03:53 GMT+08:00 2020, state='1', discount=0.8}],profession=Profession{id=1, name='医护', rank='', type='0'},healthCard=HealthCard{custId=1, name='健康卡', state='0'}}
java application print order:Order{id=1, custId=1, create=Sat Nov 28 16:03:53 GMT+08:00 2020, goods=[Item{id=1, oId=1, good=Good{id=1, name='猪肉', categery='肉类', price=40.0, unit='kg'}, count=1.0, discount=8.0}, Item{id=2, oId=1, good=Good{id=2, name='大葱', categery='肉类', price=6.0, unit='kg'}, count=1.0, discount=1.2}, Item{id=3, oId=1, good=Good{id=3, name='老陈醋', categery='调料', price=6.9, unit='壶'}, count=1.0, discount=1.38}], total=52.9, pay=42.32, discount=10.58}

从执行结果上看,当通过drools.run()调用其他unit的时候当前unit的执行是被暂停的,等被调用的unit执行完成后,还会继续执行当前unit。这一点应该注意一下的。

2.data source

DateSource是rule unit 要处理的数据源,它是rule unit 计算的入口点。每个rule unit 可以声明多个data source,每个data source 表示rule unit executor 的一个入口点。多个rule unit也可以共享同一个data source,但是需要各rule unit各自声明自身的data source入口点。如上例中 DataSource<Object>。

rule unit是由RuleUnitExecutor绑定KieBase调用的,在不同的场景data source 或者全局变量有不同的绑定方式:

第一种方式:

//第一种,没什么特别之处,一般用这种就可以

DataSource<Object> data = DataSource.create(o,c);
MarketUnits unit = new MarketUnits();
unit.setData(data);
executor.run(unit);

第二种方式:

//第二种,直接将数据绑定到了executor上,这种是可以使facts在所有具有"data"和"ounpons"两个属性名或其中之一的rule unit 之间传递,且修改均可见;
//但是也有局限性,如上例中"data"属性是包含了多个(组)数据的,这种方式却只能给属性赋值一个实例对象。

executor.bindVariable("data",o).bindVariable("counpons",new ArrayList());

 第三种方式:

//第三种,这种与第二种类似,也可以使 facts在具有相同属性名称的 rule unit 之间传递,并且可以将多个(组)赋值给DataSource;
//但是,它只能给DataSource赋值,其他变量仍需要使用bingdVariable方法赋值。

executor.newDataSource("data",o,c);

写到这里简单提一下drools 中的OOPath表达式(点击这里查看OOPath表达式),对于简化对象和对象嵌套的访问。使用OOPath表达式可以替代繁琐的 from 写法,例如上例中对订单明细的遍历访问可以写成

rule testUnit

    when
        //仅访问data中Customer实例
        $c:/data#Customer
        //仅访问data中Order实例
        $o:/data#Order[custId == $c.id]
        //"../id"表示获得上一层(Order实例的id属性值)
        $i:/data#Order[custId == $c.id]/goods[oId == ../id]
    then
        System.out.println("OOPath print 成功了"+$i.getClass());
end

等价于

rule testUnit

    when
       $c:Customer() from data
       $o:Order(custId == $c.id) from data
       $i:Item(oId == $o.id) from $o.goods
    then
        System.out.println("OOPath print 成功了"+$i.getClass());
end

RuleUnit 中也可以使用@UnitVar注解给 属性名称设置别名,别名与RuleUnitExecutor 中绑定的参数名称保持一致同样可以获得数据,例如:

public class HealthUnits implements RuleUnit {
    @UnitVar("data")
    private DataSource<Object> data_1;//DataSource data_1设置别名data
    @UnitVar("num")
    private Integer num_1;//全局变量num_1设置别名num
    private Integer maxNum;
}

3.rule units 间调用

rule unit通过 drools.run()或者drools.guard()方法调用其他rule unit。

drools.run():触发指定规则单元类的执行。此方法强制中断当前rule unit的执行,并激活另一个指定的rule unit。每个匹配数据都会强制中断,然后激活指定rule unit,这也就意味着被指定的rule unit 会多次启动。

drools.guard():触发指定规则单元类的执行。但是不会发生中断,当前rule unit的所有匹配数据处理完成,且当前rule unit 执行结束之后才会启动指定的rule unit ,且仅启动一次,这也是与drools.run()的不同之处。一个rule unit可以通过drools.guard()方法启动多个rule unit。

示例:

//售票窗口
public class BoxOffice {
    private Boolean open;
}

//购票人
public class Person {
    private Integer id;
    private String name;
    private Integer age;
}

//门票
public class Ticket {
    private Integer id;
    private Person person;
}

 售票窗口 rule unit

package com.helloworld.bk.ruleUnits.units;

import com.helloworld.bk.ruleUnits.entity.BoxOffice;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

public class BoxOfficeUnit implements RuleUnit {
    private DataSource<BoxOffice> boxOffices;

    public DataSource<BoxOffice> getBoxOffices() {
        return boxOffices;
    }

    @Override
    public void onStart() {
        System.out.println("----------------BoxOfficeUnit 开始了");
    }

    @Override
    public void onEnd() {
        System.out.println("----------------BoxOfficeUnit 结束了");
    }

    @Override
    public void onYield(RuleUnit other) {
        System.out.println("----------------BoxOfficeUnit 跳转到了其他地方");
    }
}

 购票 rule unit

package com.helloworld.bk.ruleUnits.units;

import com.helloworld.bk.ruleUnits.entity.Person;
import com.helloworld.bk.ruleUnits.entity.Ticket;
import org.kie.api.runtime.rule.DataSource;
import org.kie.api.runtime.rule.RuleUnit;

import java.util.List;

public class TicketIssuerUnit implements RuleUnit {
    private DataSource<Person> persons;
    private DataSource<Ticket> tickets;

    private List<String> results;

    public TicketIssuerUnit() {
    }

    public TicketIssuerUnit(DataSource<Person> persons, DataSource<Ticket> tickets, List<String> result) {
        this.persons = persons;
        this.tickets = tickets;
        this.results = result;
    }

    public DataSource<Person> getPersons() {
        return persons;
    }

    public DataSource<Ticket> getTickets() {
        return tickets;
    }

    public List<String> getResult() {
        return results;
    }

    @Override
    public void onStart() {
        System.out.println("----------------TicketIssuerUnit 开始了");
    }

    @Override
    public void onEnd() {
        System.out.println("----------------TicketIssuerUnit 结束了");
    }

    @Override
    public void onYield(RuleUnit other) {
        System.out.println("----------------TicketIssuerUnit 跳转了");
    }
}

DRL文件,规定至少有一个窗口开放时,允许年满18岁的客户购买门票

package com.helloworld.bk.ruleUnits.units;
unit BoxOfficeUnit
import com.helloworld.bk.ruleUnits.entity.*
rule "boxOfficeOpen"
    when
        $box:/boxOffices[open]
    then
        System.out.println("第一个执行了");
       // drools.run(TicketIssuerUnit.class);
        drools.guard(TicketIssuerUnit.class);
end
package com.helloworld.bk.ruleUnits.units;
unit TicketIssuerUnit
import com.helloworld.bk.ruleUnits.entity.*

rule issuerTicket
    salience 1
    when
        $p:/persons[age >= 18]
    then
        System.out.println("符合购票要求");
        tickets.insert(new Ticket($p));


end

rule  registerTicket

    when
        $t:/tickets
    then
        System.out.println("购票登记");
        result.add($t.getPerson().getName());
end

 数据准备

KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
KieBase kb = kc.getKieBase();
RuleUnitExecutor executor =RuleUnitExecutor.create().bind(kb);

DataSource<Person> persons = executor.newDataSource( "persons" );
DataSource<BoxOffice> boxOffices = executor.newDataSource( "boxOffices" );
DataSource<Ticket> tickets = executor.newDataSource( "tickets" );

List<String> list = new ArrayList<>();
executor.bindVariable( "results", list );

BoxOffice office1 = new BoxOffice(true);
FactHandle officeFH1 = boxOffices.insert( office1 );
BoxOffice office2 = new BoxOffice(true);
FactHandle officeFH2 = boxOffices.insert( office2 );
persons.insert(new Person(1,"John", 40));

executor.run(BoxOfficeUnit.class);

 使用drools.guard()时,执行结果如下:

----------------BoxOfficeUnit 开始了
第一个执行了
第一个执行了
----------------BoxOfficeUnit 结束了
----------------TicketIssuerUnit 开始了
符合购票要求
购票登记
----------------TicketIssuerUnit 结束了

使用drools.run()时,执行结果如下:

----------------BoxOfficeUnit 开始了
第一个执行了
----------------BoxOfficeUnit 跳转到了其他地方
----------------TicketIssuerUnit 开始了
符合购票要求
购票登记
----------------TicketIssuerUnit 结束了
----------------BoxOfficeUnit 开始了
第一个执行了
----------------BoxOfficeUnit 跳转到了其他地方
----------------TicketIssuerUnit 开始了
----------------TicketIssuerUnit 结束了
----------------BoxOfficeUnit 开始了
----------------BoxOfficeUnit 结束了

 对于调用drools.run()时的打印结果,可以看到 第二次启动TicketIssuerUnit,只有 “开始”和“结束”,这个原因应该是与drools 创建rule unit 实例都是单例有关,同时也涉及到drools 的工作机制(先将所有rule的conditions运行完毕,agenda再依据冲突策略排序再依次运行consequence);我在试验案例的时候怎么也调不出预期效果了,这个问题先留着,后续更新。

4. rule unit identity 冲突

drools 创建rule unit 实例都是单例,一个rule unit 是可以被drools.guard()或drools.run()多次启动的,这时候需要避免冲突(avoid identity conflicts),方法就是RuleUnit的实现类覆盖getUnitIdentity()方法。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值