美文网首页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)

    一、背景 在我们编写drl规则的时候,有些时候需要自己声明一些类,用于辅助之后的规则运行,如果需要用到的类还需要在...

  • Haskell Algebraic datatypes

    Data declarations review 关键字 data 声明数据类型 Bool 类型构造器,但是没有参...

  • <二> C sharp 变量和表达式

    一: 变量声明 1> 声明变量需要指定类型和变量名: type 表示使用什么类型来储存...

  • TypeScript入门

    先编译,后运行 1.简单的例子 test1.ts 2.类型和声明(Types and declarations) ...

  • Foreach语句

    显式类型迭代声明 foreach(Type Identifier in ArrayName) 隐式类型迭代声明 f...

  • RabbitMQ 消息模式总结

    1、声明队列 2、声明exchange exchange_type 类型: direct, topic, head...

  • 类型注解和类型推断

    类型注解(type annotation) 类型注解就是在声明变量的时候 先告诉TS 当前声明的变量是什么类型 例...

  • Typescript(三)类型注解和类型推断

    1:type annotation 类型注解 就是在声明变量的时候,显式的声明他的类型 这段代码就是类型注解,意思...

  • Swift常量

    常量声明 常量使用let关键字声明: 类型标注 当你声明常量或者变量的时候可以加上类型标注(type annota...

  • 了解DOCTYPE和浏览器渲染模式

    DOCTYPE DOCTYPE,或者称为 Document Type Declaration(文档类型声明,缩写 ...

网友评论

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

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