Java Springboot:Drools规则引擎文件(.drl)可以通过前端根据用户输入进行更新吗

Java Springboot:Drools规则引擎文件(.drl)可以通过前端根据用户输入进行更新吗,java,spring,spring-boot,drools,drools-guvnor,Java,Spring,Spring Boot,Drools,Drools Guvnor,我遵循了一个关于Drools的教程,并实现了同样的功能。我试图理解通过前端修改.drl文件中的值的方法。下面是我使用的名为order.drl的Drools文件 package KieRule; import com.example.demo.Order; rule "HDFC" when orderObject : Order(cardType=="HDFC" && price>10000); then orderObject.s

我遵循了一个关于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/orders

{
"name":"Mobile",
"cardType":"HDFC",
"price" : 11000
}
在已确定折扣的情况下,给出如下输出

{
"name": "Mobile",
"cardType": "HDFC",
"discount": 10,
"price": 11000
}
我创建了SpringStarter项目,下面是我的文件夹结构

对于我来说,将当前硬编码在.drl文件中的值(例如“HDFC”和“price>10000”)从JSP或Reactjs前端捕获并更新是否可行?我希望应用程序的管理员用户在需要时修改规则。我见过一些例子,其中在.drl中使用了$notation,但无法完全掌握它们。我们能用Java实现这一点吗

谢谢
SM

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


传递约束 这是最简单的解决办法。基本上,我们的想法是,约束的值与规则输入一起是一等公民

看一下您提出的规则,构成约束的两条数据是卡类型和最低价格。这些都有一个单一的后果。我们可以简单地建模:

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。当您有非常重复的规则(如您的规则)时,这非常有用,因为其他人基本上使用相同的规则和各种不同的约束

    与其他场景类似,您的工作流如下所示:

    {
        "cardType": "HDFC",
        "minimumPrice": 10000,
        "discount": 10
    },
    {
        "cardType": "ICICI",
        "minimumPrice": 15000,
        "discount": 8
    },
    {
        "cardType": "DBS",
        "minimumPrice": 15000,
        "discount": 15
    }
    
  • 用户在UI/前端中创建约束,指定所需信息(卡类型、最低价格、折扣。)
  • 用户的约束将发送到服务器
  • 服务器将请求重新格式化为表格格式(而不是JSON或任何原始格式)
  • 服务器使用数据表(步骤3)和模板生成规则
  • 您的模板可能如下所示,假设列标记为“cardType”、“minPrice”和“折扣”):

    格式非常简单。首先是标题,在这里我们按顺序定义列。第一个空行表示标题的结尾。接下来是包声明和导入,因为它们对于文件是静态的。然后是模板。使用
    @{column name}
    模式对列值进行插值;请注意,您需要将其用引号括起来作为字符串

    Drools文档非常好,所以我不打算过于详细,但您应该能够理解其中的要点


    设计考虑 既然您谈论的是React前端,我将假设您正在构建一个现代web应用程序。在实现解决方案时,请记住持久性和数据完整性问题

    如果您将后端应用程序扩展到多个实例中,这些实例前面有一个负载平衡的应用程序,那么您需要确保将用户应用的约束传播到所有实例。此外,如果应用更改,它们需要实时可见/传播——不能让一个节点或集群使用过时的约束或值

    虽然从表面上看,规则模板似乎是解决此问题的完美内置解决方案,但事实并非如此。规则模板是围绕存储在平面文件中的数据表设计的——根据定义,这不是一种非常现代或分布式的方法。如果用户更新了节点A上的约束,并且更新了节点A上的数据表,则需要确保相同的数据表文件传播到所有其他节点。此外,如果启动一个新节点,则需要设计一种机制,使其能够获取“当前”数据表。如果发生了灾难性的事情,你失去了所有的节点怎么办

    “将约束传递到内存”解决方案是老派的,但它有一个传统的持久层作为后盾的好处。如果您使用某种分布式数据源,这可能是您的真相来源。只要您的所有应用程序实例在提交规则(或使用某些逻辑缓存层)时都从数据库中查询出您的约束,您就不必担心实例不同步。如果您丢失了所有节点,那么当您的新应用程序实例启动并需要使用它时,您的约束将出现在数据源中。当然,缺点是您确实需要执行这些数据库查询或缓存读取,这可能会增加延迟。然后您需要将这些数据传递到规则中