美文网首页Spring.Netjs css html
drools的类型声明(Type declarations)

drools的类型声明(Type declarations)

作者: huan1993 | 来源:发表于2022-05-17 14:16 被阅读0次

    一、背景

    在我们编写drl规则的时候,有些时候需要自己声明一些类,用于辅助之后的规则运行,如果需要用到的类还需要在java中预先声明出来,这样就不灵活了,那么是否可以在drl文件中声明一个类呢?可以使用drools的 Type declaration来实现。

    二、前置知识

    1、Type declaration语法结构

    01-语法结构.png

    2、java代码中获取drl声明的类型

    1、非枚举类型

    KieBase kieBase = kieContainer.getKieBase("type-kabse");
                                                    // 规则文件的包名  声明的类型名
    FactType productOrderFactType = kieBase.getFactType("rules", "ProductOrder");
    Object instance = productOrderFactType.newInstance();
    productOrderFactType.set(instance, "orderId", 20220517121212001L);
    

    2、获取枚举类型的值

    需要通过反射来获取到。

    KieBase kieBase = kieContainer.getKieBase("type-kabse");
    // 此处的FactType的真实类型是EnumClassDefinition,可以获取到枚举中构造方法的参数的值
    FactType orderStatusFactType = kieBase.getFactType("rules", "OrderStatus");
    
    // 获取drools中枚举的值
    Class<?> factClass = orderStatusFactType.getFactClass();
    Method method = factClass.getMethod("valueOf", String.class);
    Object pay = method.invoke(null, "PAY");
    

    注意:
    如果上方的代码看不懂,则接着往下看。

    三、需求

    1、在drl文件中声明一个枚举类型。
    2、在drl文件中声明一个类。
    3、在drl文件中声明一个类并完成继承操作。
    4、编写rule并使用我们自定义的type。
    5、java中给在drl文件中声明的type赋值,包括类和枚举类型。

    四、实现

    1、在drl文件中声明一个枚举类型

    // 声明一个枚举类型
    declare enum OrderStatus
        CREATED(0, "新创建"),
        PAY(1, "已支付"),
        RECEIVED(2, "已接收");
    
        status: Integer;
        desc: String;
    end
    

    语法结构: declare enum 枚举名字 end

    2、在drl文件中声明一个类

    // 声明一个类
    declare BaseOrder
        orderId: Long  // 订单id
        createdTime: Date // 时间
        item: ProductItem // java中定义的类
        orderStatus: OrderStatus // 上方定义的枚举类型
    end
    

    这个类中的每个属性都有一个类型,这个类型可以是已经存在的fact,也可以是任何有效的Java类型。

    3、在drl文件中声明一个类并完成继承操作

    // 实现继承操作
    declare ProductOrder extends BaseOrder
        userId: Long // 下单用户的id
    end
    

    使用extends来完成继承操作。

    4、编写rule并使用我们自定义的type

    // 定义一个规则,规则内存中存在ProductOrder并且 orderStatus是已支付userId==1001
    rule "rule_type"
        no-loop true
        when
            $order: ProductOrder(userId == 1001 && orderStatus == OrderStatus.PAY)
        then
            String createdTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                                    .format($order.getCreatedTime());
            System.out.println("用户["+ $order.getUserId() +"]在["+ createdTime +"]购买的["+ $order.getItem().getItemName() +"]已完成付款");
            modify($order){
                setOrderStatus(OrderStatus.RECEIVED)
            }
    end
    

    解释:
    1、如果规则内存中存在ProductOrder对象,并且userId的值是1001orderStatus的值是PAY则该规则被激活了。
    2、当该规则激活时,修改订单的状态为RECEIVED,在java代码中获取修改后的值。

    5、java中给在drl文件中声明的type赋值

    @Slf4j
    public class DroolsTypeDeclareApplication {
    
        public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            KieServices kieServices = KieServices.get();
            KieContainer kieContainer = kieServices.getKieClasspathContainer();
            KieSession kieSession = kieContainer.newKieSession("type-ksession");
            kieSession.addEventListener(new DebugRuleRuntimeEventListener());
            kieSession.addEventListener(new DebugAgendaEventListener());
            kieSession.addEventListener(new DebugProcessEventListener());
    
            KieBase kieBase = kieContainer.getKieBase("type-kabse");
            FactType productOrderFactType = kieBase.getFactType("rules", "ProductOrder");
            FactType orderStatusFactType = kieBase.getFactType("rules", "OrderStatus");
    
            // 获取drools中枚举的值
            Class<?> factClass = orderStatusFactType.getFactClass();
            Method method = factClass.getMethod("valueOf", String.class);
            Object pay = method.invoke(null, "PAY");
    
            Object instance = productOrderFactType.newInstance();
    
            ProductItem item = new ProductItem();
            item.setItemName("iphone 13");
    
            productOrderFactType.set(instance, "orderId", 20220517121212001L);
            productOrderFactType.set(instance, "createdTime", new Date());
            productOrderFactType.set(instance, "item", item);
            productOrderFactType.set(instance, "orderStatus", pay);
            productOrderFactType.set(instance, "userId", 1001L);
    
            kieSession.insert(instance);
            kieSession.fireAllRules();
    
            Object orderStatus = productOrderFactType.get(instance, "orderStatus");
            log.info("获取rule中修改之后的枚举字段的值:[{}]", orderStatus);
    
            kieSession.dispose();
        }
    }
    

    注意:
    1、在java中获取到drl文件中声明的类型,需要使用 kieBase.getFactType来获取。
    2、如果需要获取到drl文件中申明的枚举类型的值,可以通过反射来获取。

    6、运行上方的代码

    用户[1001]在[2022-05-17 11:42:27]购买的[iphone 13]已完成付款
    11:42:27.724 [main] INFO com.huan.drools.querys.DroolsTypeDeclareApplication - 获取rule中修改之后的枚举字段的值:[RECEIVED]
    

    可以看到规则执行了,并且java中也获取到了工作内存中修改后的值。

    五、完整代码

    https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-type-declarations

    六、参考链接

    1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-declarations-con_drl-rules

    相关文章

      网友评论

        本文标题:drools的类型声明(Type declarations)

        本文链接:https://www.haomeiwen.com/subject/djfnurtx.html