1.背景我们在写drl规则的时候,有时候需要自己声明一些类,辅助后面规则的运行。如果声明的话,不灵活,那么是否可以在drl文件中声明一个类呢?这可以使用drools类型声明来实现。二、前置知识1、类型声明语法结构2、获取java代码中drl声明的类型1、非枚举类型KieBasekieBase=kieContainer.getKieBase("type-kabse");//规则文件的包名声明TypenameFactTypeproductOrderFactType=kieBase.getFactType("rules","ProductOrder");Objectinstance=productOrderFactType.newInstance();productOrderFactType.set(instance,"orderId",20220517121212001L);反思得到它。KieBasekieBase=kieContainer.getKieBase("type-kabse");//这里FactType的真实类型是EnumClassDefinition,可以得到枚举中构造方法的参数值。FactTypeorderStatusFactType=kieBase.getFactType("rules","OrderStatus");//获取drools中的枚举值Class>factClass=orderStatusFactType.getFactClass();Methodmethod=factClass.getMethod("valueOf",String.class);Objectpay=method.invoke(null,"PAY");注意:如果上面的代码看不懂,请继续往下看。三、要求1、在drl文件中声明一个枚举类型。2.在drl文件中声明一个类。3、在drl文件中声明一个类,完成继承操作。4.编写规则并使用我们的自定义类型。5.给java中drl文件声明的类型赋值,包括类和枚举类型。4.实现1.在drl文件中声明一个枚举类型//声明一个枚举类型declareenumOrderStatusCREATED(0,"NewlyCreated"),PAY(1,"Paid"),RECEIVED(2,"CreatedReceive");状态:整数;描述:字符串;end语法结构:declareenum枚举名end2,在drl文件中声明一个类//声明一个类declareBaseOrderorderId:Long//orderidcreatedTime:Date//timeitem:ProductItem//java中定义的类orderStatus:OrderStatus//enumerationtypedefinedaboveend这个类中的每个属性都有一个类型,这个类型可以是一个已经存在的事实,也可以是任何有效的Java类型。3.在drl文件中声明一个类并完成继承操作//实现继承操作declareProductOrderextendsBaseOrderuserId:Long//下单用户的idend使用extends完成继承操作。4.编写规则并使用我们的自定义类型//来定义规则。ProductOrder存在于规则内存中并且orderStatus已支付-ddHH:mm:ss").format($order.getCreatedTime());System.out.println("User["+$order.getUserId()+"]在["+createdTime+"]购买了["+$order.getItem().getItemName()+"]");modify($order){setOrderStatus(OrderStatus.RECEIVED)}end解释:1.如果规则内存中有一个ProductOrder对象,userId的值为1001,orderStatus的值为PAY,则激活规则.2.规则激活时,修改订单状态为RECEIVED,在java代码中获取修改值。5、java中给在drl文件中声明的类型赋值@Slf4jpublicclassDroolsTypeDeclareApplication{publicstaticvoidmain(String[]args)throwsInstantiationException,IllegalAccessException,NoSuchMethodException,InvocationTargetException{KieServiceskieServices=KieServices.get();KieContainerkieContainer=kieServices.getKieClasspathContainer();KieSessionkieSession=kieContainer.newKieSession("type-ksession");kieSession.addEventListener(newDebugRuleRuntimeEventListener());kieSession.addEventListener(newDebugAgendaEventListener());kieSession.addEventListener(newDebugProcessEventListener());KieBasekieBase=kieContainer.getKieBase("type-kabse");FactTypeproductOrderFactType=kieBase.getFactType("rules","ProductOrder");FactTypeorderStatusFactType=kieBase.getFactType("rules","OrderStatus");//获取drools中张举的价值Class>factClass=orderStatusFactType.getFactClass();方法method=factClass.getMethod("valueOf",String.class);Objectpay=method.invoke(null,"PAY");对象实例=productOrderFactType.newInstance();ProductItemitem=newProductItem();item.setItemName("iphone13");productOrderFactType.set(实例,"orderId",20220517121212001L);productOrderFactType.set(instance,"createdTime",newDate());productOrderFactType.set(实例,“项目”,项目);productOrderFactType.set(实例,“orderStatus”,支付);productOrderFactType.set(实例,"userId",1001L);kieSession.insert(实例);kieSession.fireAllRules();ObjectorderStatus=productOrderFactType.get(instance,"orderStatus");log.info("获取规则中修改后的张举字符串的值:[{}]",orderStatus);kieSession.dispose();}}注意:1.在java中获取drl文件中声明的类型,需要使用kieBase.getFactType来获取。2.如果需要获取drl文件中声明的枚举类型的值,可以使用反射获取。6.运行上面的代码[iphone13]purchasebyuser[1001]at[2022-05-1711:42:27]paymentcompleted11:42:27.724[main]INFOcom.huan.drools.querys.DroolsTypeDeclareApplication-获取规则中修改后的枚举字段的值:[RECEIVED]可以看到规则被执行了,java中也获取了工作内存中修改后的值。5.完整代码https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-type-declarations6.参考链接1.https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-declarations-con_drl-rules
