如何在 DRL 文件中为规则条件传递参数值?

How to pass parameter value for rule condition in DRL file?

我是 Drools 的新手。我想在 rule.drl 文件中为规则条件传递参数。

目前我有这样的代码:-

rule "PREPAID TOP UP LIMIT" salience 1

when
cardObject : Card(cardType=="prepaid" && loadCash > 25000);
then
cardObject.setTransactionResposne(false);
cardObject.setMessage("Top up limit exceeds ");
end;

正如您在此代码中看到的,cardType 和 loadCash 分别与 "prepaid" 和 25000 静态值进行比较。但我想从 java 类.

启动这个静态值

所以,我该如何传递这个参数。请分享一些解决方案。

要将参数传递给您的 rule.drl 文件,首先您必须清楚如何在您的代码中初始化 Drools 会话。在非常基本的形式中,它可以作为

KieSession kieSession=new DroolsBeanFactory().getKieSession(); .

初始化会话后,我看到您正在评估 cardType & loadCash 的 Card 对象。这两个值基本上是 Card 对象构造函数的一部分,该构造函数接受两个值,即 "cardType" 和 "loadCash"。所以首先要确保您的代码中已经创建了这样的 bean 或 POJO,否则就创建它。之后您需要做的是将这个 "Card" 对象作为一个整体传递给 rule.drl 文件。可以通过以下方式开始:

class Card
{

private String cardType;
private int loadCash;

Card(String cardType,int loadCash)
{
this.cardType = cardType;
this.loadCash = loadCash;
}

public String getCardType()
{
return cardType;
}
public int getLoadCash()
{
return loadCash;
}

// Other methods as per your business-logic
}

public void setCardValue(Card card){    
        kieSession.insert(card);
        kieSession.fireAllRules();  // this will now execute all the rules in your drl file.

    }

您始终可以在此处查看 KieSession 文档并检查是否允许您完成。 https://docs.jboss.org/jbpm/v6.0.Beta2/javadocs/org/kie/api/runtime/KieSession.html 如果对您有帮助,请给答案投上一票。

你基本上有两个选择:

  1. 将条件传递到工作记忆中。
  2. 将条件声明为全局变量。

全局变量通常不被接受,但为了完整起见,我将其包括在内。


对于第一个选项,将条件传递到工作内存中,我建议创建一个简单的对象,其中声明了这些条件以及适当的 getters/setters。

例如:

public class CardLimits {
  private String type;
  private Integer limit;
  // getters and setters here
}

您可以将 CardLimits 实例(或实例,如果您有多种类型)与 Card 实例一起传递到工作内存中。那么您的规则可能如下:

rule "PREPAID TOP UP LIMIT" 
salience 1
when
  CardLimits( $max: limit != null, $type: type == "prepaid" )
  cardObject : Card( cardType == $type && loadCash > $max);
then
  cardObject.setTransactionResposne(false);
  cardObject.setMessage("Top up limit exceeds ");
end

(小吹毛求疵:你在 end 后面的分号不应该在那里。而且你在右侧拼写 'response' 错误。)

CardLimits 实例将与您的 Card 实例一起传递到规则中,如下所示:

KieSession kieSession = ...; 

Card card = ...; // the Card you are passing into the rules
CardLimits limits = ...; // the limits

kieSession.insert( card ); 
kieSession.insert( limits ); 
kieSession.fireAllRules();

请注意,对于此结构,您可以对多种类型的限制使用单一规则。

因此,例如,假设您有两种类型的卡片 "prepaid" 和 "gift",用不同的 CardLimits 实例描述它们的限制。然后你可以用一个规则来处理这两个问题:

rule "ANY TOP UP LIMIT" 
salience 1
when
  CardLimits( $max: limit != null, $type: type ) // no restriction on 'type'
  cardObject : Card( cardType == $type && loadCash > $max); 
then
  cardObject.setTransactionResposne(false);
  cardObject.setMessage("Top up limit exceeds ");
end

我还建议对卡片类型使用枚举而不是字符串。

通过传入对象,您还可以在将来自由添加其他条件。例如,假设您希望在卡在特定天数内过期时拒绝充值——您可以根据需要将其添加到您的条件对象中。


为了完整起见,您的替代方法是使用全局变量。这通常是您想要避免的事情,出于同样的原因,除非别无选择,否则我们在大多数语言中都尽量避免使用全局变量。当我第一次开始使用 Drools(回到 Drools 5)时,这是一种非常普遍的做法,但此后通常不再受欢迎。

global Integer max;
global String type;

rule "PREPAID TOP UP LIMIT" 
salience 1
when
  cardObject : Card( cardType == type && loadCash > max);
then
  cardObject.setTransactionResposne(false);
  cardObject.setMessage("Top up limit exceeds ");
end

这将限制您只能使用一种类型和所有规则的最大值。所以不能同时处理多张卡片。

您在调用规则时设置了全局变量:

KieSession kieSession = ...; 

Card card = ...; // the Card you are passing into the rules

// set the globals
kieSession.setGlobal( "max", (Integer)25000 );
kieSession.setGlobal( "type", "prepaid" );

kieSession.insert( card ); 
kieSession.fireAllRules();

我不建议为此使用全局变量。我只包括这种可能性,因为它是你可以做的事情。