Java 如何在easy规则中使用变量?

Java 如何在easy规则中使用变量?,java,groovy,rule-engine,easy-rules,Java,Groovy,Rule Engine,Easy Rules,我正在使用JSON描述符加载使用的规则,我想在easy rules操作中使用变量。例如,我有一组规则,其中我定义了规则id、名称和描述,如下所示 [ { "id": 1, "name": "Task using Oracle DB", "description": "Updated comments to update connector", "priority": 1, "condition": "user.getTaskData().getTarg

我正在使用
JSON描述符
加载使用的规则,我想在easy rules
操作中使用变量。例如,我有一组规则,其中我定义了规则id、名称和描述,如下所示

[
  {
    "id": 1,
    "name": "Task using Oracle DB",
    "description": "Updated comments to update connector",
    "priority": 1,
    "condition": "user.getTaskData().getTargetConnectorType().contains(\"Oracle\") || user.getTaskData().getSourceConnectorType().contains(\"Oracle\")",
    "actions": [
      "user.setRuleDetail([\"impacted_feature\":\"Task using Oracle DB\", \"desc\": \"Updated comments to update connector\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
  }
]
以下两件事在这里可能吗

->使用规则
名称
说明
内部操作

...
[
  {
    "id": 1,
    "name": "Task using Oracle DB",
    "description": "Updated comments to update connector",
    "priority": 1,
    "condition": "user.getTaskData().getTargetConnectorType().contains(\"Oracle\") || user.getTaskData().getSourceConnectorType().contains(\"Oracle\")",
    "actions": [
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+description+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
  }
]
...
->在操作下使用变量

...
"actions": [
        "def name = \"Task using Oracle DB\"",
        "def desc = \"Updated comments to update connector\"",
        "def connector = \"Oracle\"",           
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+desc+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
...
更新 这里我正在初始化
MVELRuleFactory

def computeRules(UserData userData) {
    try {
        Facts facts = new Facts()
        facts.put("user", userData)

        MVELRuleFactory ruleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader())
        Rules rules = ruleFactory.createRules(new FileReader("conf/rules.json"))

        //create a default rules engine and fire rules on known facts
        RulesEngine rulesEngine = new DefaultRulesEngine()
        rulesEngine.fire(rules, facts)
    } catch(FileNotFoundException fnfe) {
        _errorLogger.error("Error in #computeRules {}", fnfe)
    } catch(Exception e) {
        _errorLogger.error("Error in #computeRules {}", e)
    }
    return userData.getRuleDetail()
}

//UserData POJO

@CompileStatic
class UserData {
    String orgKey
    TaskData taskData
    List<Map> ruleDetail

    UserData(String orgKey, TaskData taskData) {
        this.orgKey = orgKey
        this.taskData = taskData
    }

    String getOrgKey() {
        return orgKey
    }

    void setOrgKey(String orgKey) {
        this.orgKey = orgKey
    }

    TaskData getTaskData() {
        return taskData
    }

    void setTaskData(TaskData taskData) {
        this.taskData = taskData
    }

    List<Map> getRuleDetail() {
        return ruleDetail
    }

    void setRuleDetail(Map ruleData) {
        if (this.ruleDetail == null)
            this.ruleDetail = []
        this.ruleDetail.add(ruleData)
    }

    @Override
    public String toString() {
        return "UserData{" +
                "orgKey='" + orgKey + '\'' +
                ", taskData=" + taskData +
                ", ruleDetail=" + ruleDetail +
                '}';
    }
}
def computeRules(用户数据用户数据){
试一试{
事实=新事实
facts.put(“用户”,userData)
MVELRuleFactory ruleFactory=新的MVELRuleFactory(新的JsonRuleDefinitionReader())
Rules-Rules=ruleFactory.createRules(新文件读取器(“conf/Rules.json”))
//根据已知事实创建默认规则引擎和消防规则
RulesEngine RulesEngine=新的默认RulesEngine()
规则引擎火灾(规则、事实)
}捕获(FileNotFoundException fnfe){
_errorLogger.error(“计算机规则{}中的错误”,fnfe)
}捕获(例外e){
_errorLogger.error(“计算机规则{}中的错误”,e)
}
返回userData.getRuleDetail()
}
//用户数据POJO
@编译的
类用户数据{
字符串组织键
任务数据任务数据
列表规则详细信息
UserData(字符串orgKey、TaskData TaskData){
this.orgKey=orgKey
this.taskData=taskData
}
字符串getOrgKey(){
返回键
}
void setOrgKey(字符串orgKey){
this.orgKey=orgKey
}
TaskData getTaskData(){
返回任务数据
}
void setTaskData(TaskData TaskData){
this.taskData=taskData
}
列表getRuleDetail(){
返回规则详细信息
}
void setRuleDetail(映射规则数据){
if(this.ruleDetail==null)
this.ruleDetail=[]
this.ruleDetail.add(ruleData)
}
@凌驾
公共字符串toString(){
返回“UserData{”+
“orgKey=”+orgKey+“\”+
“,taskData=“+taskData”+
“,ruleDetail=“+ruleDetail+
'}';
}
}

总结,否和是

要了解如何使用,您必须了解,只要变量作为
事实存在,或者以某种方式存在于
MVEL
上下文中,它就可以被解析

下面是详细的答案-

使用规则
名称
说明
内部操作

...
[
  {
    "id": 1,
    "name": "Task using Oracle DB",
    "description": "Updated comments to update connector",
    "priority": 1,
    "condition": "user.getTaskData().getTargetConnectorType().contains(\"Oracle\") || user.getTaskData().getSourceConnectorType().contains(\"Oracle\")",
    "actions": [
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+description+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
  }
]
...
不可以。您不能在
操作
中使用
规则
名称
说明
。要在规则中使用外部变量,必须将它们添加为事实。如果您想要这种能力,可以使用
drools
,这是一种功能更丰富、更繁重的框架

在操作下使用变量

...
"actions": [
        "def name = \"Task using Oracle DB\"",
        "def desc = \"Updated comments to update connector\"",
        "def connector = \"Oracle\"",           
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+desc+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
...
这是你可以做到的,但不是你现在的方式
def
MVEL
中有特殊含义。因此,要使用变量,您可以执行以下任一操作-

  • 将变量定义为单独的操作项:

    "actions": [
       "name=\"....\"",
       "description=\"....\"",
       "user.setRuleDetail([\"impacted_feature\": name, \"desc\": description, \"impact\": \"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
    
  • 添加内联变量:

    "actions": [
       "name=\"....\";description=\"....\";user.setRuleDetail([\"impacted_feature\": name, \"desc\": description, \"impact\": \"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
    
    请注意,在操作中使用引号时,您不需要额外的引号


  • 希望这有帮助

    您基本上是试图访问条件/操作中的规则信息,或者换句话说,让条件/操作知道规则。您可以使用一个规则侦听器来实现这一点,该侦听器将规则作为事实放在规则执行之前,然后将其删除。下面是一个简单的例子:

    public class MyListener implements RuleListener {
        @Override
        public void beforeExecute(Rule rule, Facts facts) {
            facts.put("rule", rule);
        }
    
        @Override
        public void onSuccess(Rule rule, Facts facts) {
            facts.remove("rule");
        }
    
        @Override
        public void onFailure(Rule rule, Facts facts, Exception exception) {
            facts.remove("rule");
        }
    
        // implement other methods if needed
    }
    
    下面是如何使用它:给定以下规则描述文件
    rule aware action.json

    [
      {
        "name": "rule aware action",
        "description": "a rule where the action is aware of the rule",
        "condition": "true",
        "actions": [
          "System.out.println(rule.name);"
        ]
      }
    ]
    
    import java.io.FileReader;
    
    import org.jeasy.rules.api.Facts;
    import org.jeasy.rules.api.Rule;
    import org.jeasy.rules.api.RuleListener;
    import org.jeasy.rules.api.Rules;
    import org.jeasy.rules.core.DefaultRulesEngine;
    import org.jeasy.rules.mvel.MVELRuleFactory;
    import org.jeasy.rules.support.reader.JsonRuleDefinitionReader;
    
    public class RuleAwareActionExample {
    
        public static void main(String[] args) throws Exception {
            MVELRuleFactory mvelRuleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader());
            Rules rules = mvelRuleFactory.createRules(new FileReader("rule-aware-action.json"));
            DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
            rulesEngine.registerRuleListener(new MyListener());
            Facts facts = new Facts();
            rulesEngine.fire(rules, facts);
        }
    }
    
    下面的示例打印规则感知操作

    [
      {
        "name": "rule aware action",
        "description": "a rule where the action is aware of the rule",
        "condition": "true",
        "actions": [
          "System.out.println(rule.name);"
        ]
      }
    ]
    
    import java.io.FileReader;
    
    import org.jeasy.rules.api.Facts;
    import org.jeasy.rules.api.Rule;
    import org.jeasy.rules.api.RuleListener;
    import org.jeasy.rules.api.Rules;
    import org.jeasy.rules.core.DefaultRulesEngine;
    import org.jeasy.rules.mvel.MVELRuleFactory;
    import org.jeasy.rules.support.reader.JsonRuleDefinitionReader;
    
    public class RuleAwareActionExample {
    
        public static void main(String[] args) throws Exception {
            MVELRuleFactory mvelRuleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader());
            Rules rules = mvelRuleFactory.createRules(new FileReader("rule-aware-action.json"));
            DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
            rulesEngine.registerRuleListener(new MyListener());
            Facts facts = new Facts();
            rulesEngine.fire(rules, facts);
        }
    }
    

    这意味着该操作能够访问它所属的规则的名称。该示例显示了如何使操作了解其规则,但它也应该适用于条件。

    java和groovy标记在这里做什么?@daggett easy rules是一个java规则引擎,操作中的代码是用groovy编写的,因为我知道它不包含操作的groovy实现。@daggett抱歉,我的错,操作使用java代码,我的项目是在groovy中进行的,它同时使用java和groovy。请编辑您的问题,并至少提供部分代码-您是如何初始化SpELRuleFactory的