easy-rules mvel yaml 格式規則配置&&試用


網上關於easy-rules 介紹的挺多了,以下是一個學習,以及一些學習說明

demo 說明

demo 是一個簡單的用戶實體,同時添加了一些幫助方法,對於規則的定義使用yaml 文件(實際上我們可以基於數據庫,cache,s3文件系統。。。)
包含了,在實際使用中我么如何修改數據以及mvel 的集成使用,以及一些監聽事件的學習

項目准備

  • pom.xml
 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dalong</groupId>
  <artifactId>myruleapps</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <encoding>UTF-8</encoding>
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>8</source>
          <target>8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <packaging>jar</packaging>
  <dependencies>
    <dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-core</artifactId>
      <version>3.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-mvel</artifactId>
      <version>3.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-spel</artifactId>
      <version>3.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.7.25</version>
    </dependency>
  </dependencies>
</project>
 
  • 代碼結構
├── pom.xml
└── src
    └── main
        ├── java
        └── com
        └── dalong
        ├── Launcher.java
        ├── User.java
        └── UserService.java
        └── resources
            ├── rules.yml
            └── simplelogger.properties

代碼說明

  • rules.yml
    主要是配置了規則,主要是為了學習參數的傳遞(class以及map)同時也包含了如何進行參數的修改以及
    關於mvel 的集成使用
    rules.yml
---
name: "1"
description: "1"
condition: "user.getAge()>26"
priority: 1
actions:
  - "user.age=user.age-2;System.out.println(userinfo);"
---
name: "2"
description: "2"
condition: "user.getAge()<26"
priority: 2
actions:
  - "UserService.doAction1(user)"
---
name: "3"
description: "3"
condition: "user.name.length<10"
priority: 3
actions:
  - "UserService.doAction2(user)"
---
name: "4"
description: "4"
condition: "user.name.length<40"
priority: 4
actions:
  - "System.out.println(\"rule4 \"+userinfo)"
---
name: "5"
description: "5"
condition: "user.name.length<30"
priority: 5
actions:
  - "UserService.doAction4(userinfo)"
---
name: "6"
description: "6"
condition: "user.name.length<30"
priority: 6
actions:
  - "System.out.println(\"rule6 \"+userinfo)"
---
name: "7"
description: "7"
condition: "user.name.length<30"
priority: 7
actions:
  - "UserService.doAction4(user)"
---
name: "8"
description: "8"
condition: "user.name.length<30"
priority: 8
actions:
  - "System.out.println(\"rule8 \"+user)"
 

規則簡單說明:
總共8個, 主要是基於不同的user 實體以及一個userinfo map 類型數據的處理,包含了如何數據修改
UserService 是一個靜態幫助類,主要進行數據操作(更新user以及userinfo 的數據)后邊會有代碼的說明

  • Launcher.java
    代碼的核心入口
 
package com.dalong;
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.core.InferenceRulesEngine;
import org.jeasy.rules.core.RuleBuilder;
import org.jeasy.rules.mvel.MVELRuleFactory;
import org.jeasy.rules.support.YamlRuleDefinitionReader;
import org.mvel2.ParserContext;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import static com.dalong.DecreaseTemperatureAction.decreaseTemperature;
import static com.dalong.HighTemperatureCondition.itIsHot;
import static com.dalong.AppendUserName.appendUserName;
import static com.dalong.NameTooShort.nameTooShort;
public class Launcher {
    public static void main(String[] args) throws Exception {
       app3();
    }
    private static void app3() throws Exception {
        MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
        ParserContext context =new ParserContext();
        context.addImport("UserService", UserService.class);
        Rules yamlRules = ruleFactory.createRules(new FileReader(Launcher.class.getClassLoader().getResource("rules.yml").getFile()),context);
        DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
        Facts facts = new Facts();
        Map<String,Object> userinfo = new HashMap<>();
        userinfo.put("name2","dalong");
        userinfo.put("age2",27);
        facts.put("user",new User("dalong",27));
        facts.put("userinfo",userinfo);
        rulesEngine.registerRuleListener(new MyRulesListener());
        rulesEngine.registerRulesEngineListener(new MyRuleEngineListener());
        rulesEngine.fire(yamlRules, facts);
    }
}

因為是使用了mvel 所以使用了MVELRuleFactory,當前因為我們需要依賴一些幫助類操作數據模型,所以導入了UserService
對於數據的傳遞,我們使用了User 實體模型以及一個map 模型(模擬實際業務場景)

  • User.java
    用戶實體模型,當然可以作為一個簡單的pojo處理也行
 
package com.dalong;
public class User {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public User(){
    }
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public void dosomeThing() throws Exception {
        if(this.age<26){
            throw new Exception("age is too small");
        }
        if(this.name.length()<10){
            throw new Exception("some wrong");
        }
    }
    public void setAge(int age) {
        this.age = age;
    }
}
 
  • UserService.java
    主要包含了已給幫助操作類,主要是為了mvel使用,定義了一些action,同時為了學習有一個類型處理的
 
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.HashMap;
import java.util.Map;
public class UserService {
   static Log log = LogFactory.getLog(MyRuleEngineListener.class);
    public static void doAction1(User user){
     log.info("------------do action1------------");
     log.info(user.toString());
    }
    public static void doAction2(User user){
        log.info("------------do action2------------");
        user.setName("sssssssssssssssssss");
        log.info(user.toString());
    }
    public static void doAction3(Map user){
        log.info("------------do action3------------");
        log.info(user.toString());
    }
    public static void doAction4(Object user){
        /**
         * 基於mvel 修改數據,為了復用doAction4,做了數據兼容處理
         */
        if (user instanceof Map ){
            log.info("------------do actionn4------------");
            ((Map)user).put("name2","rule wwwwwwwwwwwwwwwwww");
        }
        if (user instanceof User) {
            ((User)user).setName("dalong demo appapapappapa");
        }
        log.info(user.toString());
    }
}
  • MyRulesListener.java
    rule 運行的監聽,此處我們可以方便進行數據審計記錄(存儲數據庫,同時基於pipline模式,可視化分析任務狀態,以及數據)
 
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.RuleListener;
public class MyRulesListener implements RuleListener {
    Log log = LogFactory.getLog(MyRulesListener.class);
    @Override
    public boolean beforeEvaluate(Rule rule, Facts facts) {
        return true;
    }
    @Override
    public void afterEvaluate(Rule rule, Facts facts, boolean b) {
        log.info("-----------------afterEvaluate-----------------");
       // log.info(rule.getName()+rule.getDescription()+facts.toString());
    }
    @Override
    public void beforeExecute(Rule rule, Facts facts) {
        log.info("-----------------beforeExecute-----------------");
       // log.info(rule.getName()+rule.getDescription()+facts.toString());
    }
    @Override
    public void onSuccess(Rule rule, Facts facts) {
        log.info("-----------------onSuccess-----------------");
       // log.info(rule.getName()+rule.getDescription()+facts.toString());
    }
    @Override
    public void onFailure(Rule rule, Facts facts, Exception e) {
        log.info("-----------------onFailure-----------------");
        log.info(rule.getName()+"----------"+rule.getDescription()+facts.toString()+e.toString());
    }
}
 
  • MyRuleEngineListener.java
    記錄引擎的操作日志
 
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngineListener;
public class MyRuleEngineListener implements RulesEngineListener {
    Log log = LogFactory.getLog(MyRuleEngineListener.class);
    @Override
    public void beforeEvaluate(Rules rules, Facts facts) {
        log.info("-----------------beforeEvaluate-----------------");
        log.info(rules.toString() +" "+facts.toString());
    }
    @Override
    public void afterExecute(Rules rules, Facts facts) {
        log.info("-----------------afterExecute-----------------");
        log.info(rules.toString()+" "+facts.toString());
    }
}

一些說明

easy-rules 對於數據的傳遞是通過map的,所以mvel使用的時候注意key值的處理,同時還有數據類型的處理,一種
比較好的方式是進行類型判斷(類似上邊的doAction4)

參考資料

https://github.com/j-easy/easy-rules
https://www.theserverside.com/feature/Adding-MVEL-to-the-Java-Developers-Toolkit


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM