java轻量级规则引擎easy-rules使用介绍

2,416 阅读3分钟

什么是Easy Rules?

Easy Rules是一个简单而强大的Java规则引擎,提供以下功能:

  • 轻量级框架和易于学习的API
  • 基于POJO的开发与注解的编程模型
  • 定义抽象的业务规则并轻松应用它们
  • 支持从简单规则创建组合规则的能力
  • 支持使用表达式语言(如MVEL和SpEL)定义规则的能力

运行环境

Easy Rules是一个Java库, 需要运行在Java 1.7及以上。

maven依赖

<properties>
    <easy.rules.version>4.1.0</easy.rules.version>
</properties>
<!--easy-rules 执行引擎-->
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-mvel</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-spel</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<!--easy-rules 执行引擎-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>

基于MVEL表达式的编程模型

定义规则

大多数业务规则可以用以下定义表示:

  • Name : 一个命名空间下的唯一的规则名称
  • Description : 规则的简要描述
  • Priority : 相对于其他规则的优先级
  • Facts : 事实,可立即为要处理的数据
  • Conditions : 为了应用规则而必须满足的一组条件
  • Actions : 当条件满足时执行的一组动作

Easy Rules为每个关键点提供了一个抽象来定义业务规则。

实体类user

import lombok.Data;

@Data
public class User {
    private Integer age;
}

运行demo

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.mvel.MVELRule;

import java.util.HashMap;
import java.util.Map;

public class MTest {

    public static void main(String[] args) {
        //规则引擎
        RulesEngine rulesEngine = new DefaultRulesEngine();
        //规则
        MVELRule ageRule = new MVELRule()
                .name("test rule1")
                .description("test demo rule1")
                .priority(1)
                .when("user.age > 18")
                .then("map.put('code',200);map.put('msg','已经成年');");

        Rules rules = new Rules();
        rules.register(ageRule);

        Facts facts = new Facts();

        Map<String,Object> map = new HashMap<>();
        User user = new User();
        user.setAge(19);
        facts.put("user", user);
        facts.put("map", map);

        rulesEngine.fire(rules, facts);
        System.out.println(map);
    }
}

运行结果

14:01:21.699 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
14:01:21.704 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'test rule1', description = 'test demo rule1', priority = '1'}
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='map', value={}}
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='user', value=User(age=19)}
14:01:21.723 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
14:01:21.767 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'test rule1' triggered
14:01:21.817 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'test rule1' performed successfully
{msg=已经成年, code=200}

规则监听器 RuleListener

public class CustomRuleListener implements RuleListener {
    @Override
    public boolean beforeEvaluate(Rule rule, Facts facts) {
        System.out.println("---CustomRuleListener------beforeEvaluate-----");
        return true;
    }

    @Override
    public void afterEvaluate(Rule rule, Facts facts, boolean b) {
        System.out.println("---CustomRuleListener------afterEvaluate-----");
    }

    @Override
    public void beforeExecute(Rule rule, Facts facts) {
        System.out.println("---CustomRuleListener------beforeExecute-----");
    }

    @Override
    public void onSuccess(Rule rule, Facts facts) {

        System.out.println("---CustomRuleListener------onSuccess-----");
    }

    @Override
    public void onFailure(Rule rule, Facts facts, Exception e) {
        System.out.println("---CustomRuleListener------onFailure-----");
    }
}

  • beforeEvaluate 该方法在执行@Condition修饰的方法之前执行。该方法返回false则不执行条件的判断,直接跳过该当前rule。

  • afterEvaluate 该方法在执行@Condition修饰的方法之后执行。

  • beforeExecute 该方法在执行@Action修饰的方法之前执行。

  • onSuccess 该方法在执行@Action修饰的方法之后执行。

  • onFailure 在执行@Action修饰的方法出现异常时,该方法执行。

rulesEngine.fire(rules, facts);之前注册规则监听器

((DefaultRulesEngine) rulesEngine).registerRuleListener(new CustomRuleListener());

RulesEngineListener

public class CustomRulesEngineListener implements RulesEngineListener {
    @Override
    public void beforeEvaluate(Rules rules, Facts facts) {
        System.out.println("---CustomRulesEngineListener------beforeEvaluate-----");
    }

    @Override
    public void afterExecute(Rules rules, Facts facts) {
        System.out.println("---CustomRulesEngineListener------afterExecute-----");
    }
}
  • beforeEvaluate 该方法在执行@Action修饰的方法之后执行。在RuleListener之前执行
  • afterExecute 该方法在执行@Condition修饰的方法之前执行。在RuleListener之后执行

rulesEngine.fire(rules, facts);之前注册规则引擎监听器

((DefaultRulesEngine) rulesEngine).registerRulesEngineListener(new CustomRulesEngineListener());

规则引擎初始化参数

  • skipOnFirstAppliedRuletrue时, 从第一条开始,匹配一条就会跳过后面规则匹配,不匹配则一直往下执行

  • skipOnFirstFailedRuletrue时, 如果执行@Action中发生异常就会跳过后面规则匹配

  • skipOnFirstNonTriggeredRuletrue时,从第一条开始,匹配一条才会往下执行,不匹配则跳过后面

  • rulePriorityThreshold 大于指定的优先级则不进行匹配

 RulesEngineParameters parameters = new RulesEngineParameters()
 parameters.skipOnFirstAppliedRule(true);
 parameters.skipOnFirstFailedRule(true);
 parameters.skipOnFirstNonTriggeredRule(true);
 parameters.priorityThreshold(3);
 
 RulesEngine rulesEngine = new DefaultRulesEngine(parameters);