s语言pringboot:can drools 规则引擎文件(.drl)可以通过前端根据用户输入进行更新

rmbxnbpk  于 2021-06-26  发布在  Java
关注(0)|答案(1)|浏览(461)

我遵循了一个关于drools的教程,并实现了同样的方法。我试图理解通过前端修改.drl文件中的值的方法。下面是我使用的名为order.drl的drools文件。

package KieRule;
import com.example.demo.Order;

rule "HDFC"

when
orderObject : Order(cardType=="HDFC" && price>10000);
then
orderObject.setDiscount(10);
end;

rule "ICICI"

when
orderObject : Order(cardType=="ICICI" && price>15000);
then
orderObject.setDiscount(8);
end;

rule "DBS"

when
orderObject : Order(cardType=="DBS" && price>15000);
then
orderObject.setDiscount(15);
end;

基本上,逻辑是建立规则的折扣百分比,以计算每一种卡类型的商品购买。
因此,一个职位要求如下http://localhost:8080/订单

{
"name":"Mobile",
"cardType":"HDFC",
"price" : 11000
}

在已确定折扣的情况下给出如下输出

{
"name": "Mobile",
"cardType": "HDFC",
"discount": 10,
"price": 11000
}

我创建了springstarter项目,下面是我的文件夹结构

对我来说,将当前硬编码在.drl文件中的值(例如“hdfc”和“price>10000”)从jsp或reactjs前端捕获并更新是否可行?我更希望应用程序的管理员用户在需要时修改规则。我看到过一些例子,其中在.drl中使用了$符号,但无法完全理解它们。我们能用java实现吗?
谢谢山猫

bihw5rsg

bihw5rsg1#

假设您要做的是保持基本结构不变,并简单地改变约束,那么最简单的两种解决方案是使用规则模板或将约束本身传递给规则以及您的输入。

传递约束

这是最简单的解决办法。基本上,您的约束的值是一等公民,与您的规则输入一起。
看看你提出的规则,构成你的约束的两个数据是卡片类型和最低价格。这些都有一个单一的后果。我们可以简单地建模:

class OrderConstraints {
  private String cardType;
  private Integer minimumPrice;
  private Integer discount;
  // Getters 
}

您可以将这些信息传递到如下对象中的规则中:

{
    "cardType": "HDFC",
    "minimumPrice": 10000,
    "discount": 10
},
{
    "cardType": "ICICI",
    "minimumPrice": 15000,
    "discount": 8
},
{
    "cardType": "DBS",
    "minimumPrice": 15000,
    "discount": 15
}

现在,您的所有用例都可以在一个规则中处理:

rule "Apply order discount"
when
  OrderConstraints( $cardType: cardType, $minimumPrice: minimumPrice, $discount: discount)
  $order: Order( cardType == $cardType, price > $minimumPrice )
then
  $order.setDiscount($discount);
end

(旁注:我清理了你的语法。原来的规则中有很多不必要的分号和奇怪的空白。)
工作流程基本如下:
用户在ui/前端中创建约束,指定所需信息(卡类型、最低价格、折扣)。
用户的约束被发送到服务器并保存到持久层(数据库等)
当进行一个新的查询时,约束将从持久层中读出,并与规则输入一起传递到规则中。

规则模板

第二种解决方案是使用规则模板(链接到drools文档)。基本思想是提供一个数据表和drl模板,drools框架将把数据生成模板并为您生成drl。当您有非常重复的规则(比如您的规则)时,这是非常有用的—其他规则基本上是用不同的约束应用相同的规则。
与其他场景类似,您的工作流如下所示:
用户在ui/前端中创建约束,指定所需信息(卡类型、最低价格、折扣)
将用户的约束发送到服务器。
服务器将请求重新格式化为表格格式(而不是json或任何原始格式)。
服务器使用数据表(步骤3)和模板来生成规则。
您的模板可能如下所示,假设列标签为“cardtype”、“minprice”和“discount”):

template header
cardType
minPrice
discount

package com.example.template;
import com.example.Order;

template "orderdiscounts"

rule "Apply order discount for @{cardType}"
when
  $order: Order( cardType == "@{cardType}",
                 price > @{minPrice} )
then
  $order.setDiscount(@{discount});
end

end template

格式很直接。首先是标题,在这里我们按顺序定义列。第一个空行表示标题的结尾。接下来是包声明和导入,因为它们对于文件来说是静态的。然后是模板。列值使用 @{ column name } 图案;请注意,您需要为字符串使用引号将其括起来。
drools文档非常好,所以我不打算过于详细,但您应该能够理解其中的要点。

设计注意事项

既然您谈论的是react前端,我就假设您正在构建一个现代web应用程序。在实现解决方案时,请记住持久性和数据完整性问题。
如果您将后端应用程序扩展到多个示例中,这些示例前面有一个负载平衡的示例,那么您需要确保将用户应用的约束传播到所有示例。此外,如果应用更改,它们需要实时可见/传播——不能让一个节点或集群使用过时的约束或值。
虽然从表面上看,规则模板似乎是解决这个问题的最佳内置解决方案,但事实并非如此。规则模板是围绕存储在平面文件中的数据表设计的——根据定义,这不是一种非常现代或分布式的方法。如果用户更新了节点a上的约束,并且更新了节点a上的数据表,则需要确保相同的数据表文件传播到所有其他节点。此外,如果启动一个新节点,则需要设计一种机制,使其能够获取“当前”数据表。如果发生了灾难性的事情,你失去了所有的节点怎么办?
“将约束传递到内存”解决方案是老派的,但它的好处是有一个传统的持久层作为后盾。如果您使用某种分布式数据源,这可能是您的真相来源。只要您的所有应用程序示例在归档规则(或使用某些逻辑缓存层)时都从数据库中查询出您的约束,您就不必担心示例不同步。如果您丢失了所有节点,那么当您的新应用程序示例启动并需要使用它时,您的约束将出现在数据源中。当然,缺点是您确实需要执行这些数据库查询或缓存读取,这可能会增加延迟。然后,您需要将这些数据传递到规则中,这将增加内存使用量和潜在的cpu(具体多少取决于您传递的数据量)。
我已经把你和drools文档联系起来了,我强烈建议你读一下。很长,但很值得。这可能是我访问量最大的书签,尽管我已经不再每天流口水了。还有其他可用的解决方案,例如,用户请求可以生成规则,将它们打包到kjar中,并将它们发布到maven存储库中,然后您的所有示例都可以下载并使用该存储库——但是适合您的用例的正确解决方案是您需要根据自己的需求自行决定的。

相关问题