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

posted on 2020-04-12 18:11  荣锋亮  阅读(4689)  评论(0编辑  收藏  举报

导航