一、背景
在咱们编写 drl
规定的时候,有些时候须要本人申明一些类,用于辅助之后的规定运行,如果须要用到的类还须要在 java
中事后申明进去,这样就不灵便了,那么是否能够在 drl
文件中申明一个类呢?能够应用 drools 的 Type declaration
来实现。
二、前置常识
1、Type declaration 语法结构
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 的值是 1001
,orderStatus 的值是 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