1. Background
When we write the drl
rule, sometimes we need to declare some classes by ourselves to assist in the subsequent rule operation. If the class needs to be used, it needs to be declared in advance in java
, this is inflexible, so is it possible to declare a class in the drl
file? Can use drools Type declaration
to achieve.
2. Preliminary knowledge
1. Type declaration syntax structure
2. Get the type of drl declaration in java code
1. Non-enumeration types
KieBase kieBase = kieContainer.getKieBase("type-kabse");
// 规则文件的包名 声明的类型名
FactType productOrderFactType = kieBase.getFactType("rules", "ProductOrder");
Object instance = productOrderFactType.newInstance();
productOrderFactType.set(instance, "orderId", 20220517121212001L);
2. Get the value of the enumeration type
需要通过反射来获取到。
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");
Notice:
If you don't understand the code above, then look down.
3. Demand
1. Declare an enumeration type in the drl file.
2. Declare a class in the drl file.
3. Declare a class in the drl file and complete the inheritance operation.
4. Write rule
and use our custom type.
5. Assign values to the types declared in the drl file in java, including classes and enumeration types.
4. Realization
1. Declare an enumeration type in the drl file
// 声明一个枚举类型
declare enum OrderStatus
CREATED(0, "新创建"),
PAY(1, "已支付"),
RECEIVED(2, "已接收");
status: Integer;
desc: String;
end
Syntax structure: declare enum 枚举名字 end
2. Declare a class in the drl file
// 声明一个类
declare BaseOrder
orderId: Long // 订单id
createdTime: Date // 时间
item: ProductItem // java中定义的类
orderStatus: OrderStatus // 上方定义的枚举类型
end
每个属性都有一个类型
in this class, the type can be an existing fact, or any valid Java type.
3. Declare a class in the drl file and complete the inheritance operation
// 实现继承操作
declare ProductOrder extends BaseOrder
userId: Long // 下单用户的id
end
Use extends
to complete the inheritance operation.
4. Write rule and use our custom 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
explain:
1. If there is a ProductOrder
object in the rule memory, and userId的值是1001
, orderStatus的值是PAY
, the rule is activated.
2. When the rule is activated, the status of the modified order is RECEIVED
, and the modified value is obtained in the java code.
5. Assign value to the type declared in the drl file in java
@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();
}
}
Notice:
1. To get the type declared in the drl file in java, you need to use kieBase.getFactType
to get it.
2. If you need to get the value of the enumeration type declared in the drl file, you can get it through reflection.
6. Run the above code
用户[1001]在[2022-05-17 11:42:27]购买的[iphone 13]已完成付款
11:42:27.724 [main] INFO com.huan.drools.querys.DroolsTypeDeclareApplication - 获取rule中修改之后的枚举字段的值:[RECEIVED]
You can see that the rule is executed, and the modified value in the working memory is also obtained in java.
5. Complete code
https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-type-declarations
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。