drools的類型聲明(Type declarations)
一、背景
在我們編寫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中也獲取到了工作內存中修改後的值。
五、完整代碼
//gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-type-declarations
六、參考鏈接
1、//docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-declarations-con_drl-rules