规则引擎easyRule详解

规则引擎有许多种:Drools,Aviator,Mvel,EasyRule,这里主要讲解一下EasyRule。

easyRule集成了Mvel,而Mvel表达式非常强大,我们可以自己写一些表达式,交给mvel进行解析计算,得到这个表达式计算的值。

easyRule可大致分为三部分:规则引擎,事实,规则

        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-rules-core</artifactId>
            <version>4.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-rules-mvel</artifactId>
            <version>4.1.0</version>
        </dependency>

它有两种使用方式:一种是注解,一种是api方式,这里主要介绍一下api的方式

  • 规则引擎
            RulesEngine rulesEngine = new DefaultRulesEngine();
            rulesEngine.fire(rules, facts);
     

    从版本3.1开始,Easy Rules提供了RulesEngine接口的两种实现:
    DefaultRulesEngine:根据规则的自然顺序(默认为优先级)应用规则。
    InferenceRulesEngine:持续对已知事实应用规则,直到不再应用规则为止

    什么意思呢?来看一段代码
     

        public static void main(String[] args) {
            //规则条件
            String condition = "name contains(\"张\")";
            String condition2 = "age > 10 && age <= 20";
            //规则引擎
            RulesEngine rulesEngine = new DefaultRulesEngine();
            Rules rules = new Rules();
            //具体规则,当满足condition,然后输出对应的success
            Rule rule = new MVELRule().when(condition).then("System.out.println(\"name success\")").priority(2);
            Rule rule2 = new MVELRule().when(condition2).then("System.out.println(\"age success\")").priority(1);
        
            rules.register(rule);
            rules.register(rule2);
            //匹配规则的事实
            Facts facts = new Facts();
            facts.put("name","张");
            facts.put("age","11");
    
            rulesEngine.fire(rules,facts);
    
        }

    使用DefaultRulesEngine引擎会根据规则设置的priority属性,从小到大顺序执行。

  可以看到age先执行,name后执行。

         使用InferenceRulesEngine引擎,会通过循环不停的通过事实去匹配规则,直到全部事实都不匹配规则才停止循环。可以看到源码中就是通过do while循环的

   规则引擎也有几个参数默认都为false

  • skipOnFirstAppliedRule:告诉引擎规则被触发时跳过后面的规则。
  • skipOnFirstFailedRule:告诉引擎在规则失败时跳过后面的规则。
  • skipOnFirstNonTriggeredRule:告诉引擎一个规则不会被触发跳过后面的规则。
  • rulePriorityThreshold:告诉引擎如果优先级超过定义的阈值,则跳过下一个规则。版本3.3已经不支持更改,默认MaxInt。

通过构造函数设置进去就行了 

RulesEngineParameters parameters = new RulesEngineParameters()
    .rulePriorityThreshold(10)
    .skipOnFirstAppliedRule(true)
    .skipOnFirstFailedRule(true)
    .skipOnFirstNonTriggeredRule(true);

RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
  • 事实

    事实如何理解呢?规定定义好了,为谁定义的呢?就是Facts ,规则引擎就是判断这些Facts符不符合规则。在内部,Facts实例持有HashSet<Fact<?>>,这意味着:

       1.事实需要命名,应该有一个唯一的名称,且不能为空

       2. 任何Java对象都可以充当事实

不好理解来看代码

//可以这样
  Facts facts = new Facts();
        facts.put("name","张");
        facts.put("age","11"); 

//也可以这样存放对象
  Facts facts = new Facts();
        Result p1 = new Result();
        p1.setAge(11); p1.setName("张三");

        Result p2 = new Result();
        p2.setAge(12); p2.setName("张四");
        //facts的key相同,后put会覆盖前一个person,因为Facts是通过HastSet来存储,并以key区分
        facts.put("person",p1);
        facts.put("person",p2);
          
//如果是这样那么规则就必须person.xxx这样写
 String condition = "person.name contains(\"张\")";
 String condition2 = "person.age > 10 && person.age <= 20";

    @Data
    class Result {
        private String name;
        private Integer age;
    }

为了解决上面出现的覆盖问题,可以考虑下面这样的实现

  public static void main(String[] args) {
        List<Result> list = new ArrayList<>();
        Result p1 = new Result();
        p1.setAge(11);
        p1.setName("张三");
        Result p2 = new Result();
        p2.setAge(12);
        p2.setName("张四");
        list.add(p1);
        list.add(p2);
        String condition = "person.name contains(\"张\")";
        String condition2 = "person.age > 10 && person.age <= 20";
        RulesEngine rulesEngine = new DefaultRulesEngine();
        Rules rules = new Rules();
        Rule rule = new MVELRule().when(condition).then("System.out.println(\"name success\")").priority(2);
        Rule rule2 = new MVELRule().when(condition2).then("System.out.println(\"age success\")").priority(1);
        rules.register(rule);
        rules.register(rule2);
        for (int i = 0; i < list.size(); i++) {
            Facts facts = new Facts();
            facts.put("person", list.get(i));
            rulesEngine.fire(rules, facts);
        }


    }
  • 规则
    上面的案例都是一个事实匹配一个规则(一个person只要满足name包含张或者age >10 && age <20其中一个条件就执行对应规则校验成功后的逻辑),那如何做到一个事实匹配多个规则呢?也就是说一个person不仅要满足name包含张且age >10 && age <20才执行成功后的逻辑,就需要使用复合规则。

UnitRuleGroup:单元规则组是作为一个单元的复合规则:要么应用所有规则,要么什么都不应用。
ActivationRuleGroup:激活规则组是一个复合规则,它触发第一个适用规则,并忽略组中的其他规则(XOR逻辑)。规则首先按照组内的自然顺序(默认优先级)进行排序。
ConditionalRuleGroup:条件规则组是一个复合规则,其中优先级最高的规则充当条件:如果优先级最高的规则求值为true,则触发其余规则。

废话不多说,上demo 

    public static void main(String[] args) {
        List<Result> list = new ArrayList<>();
        Result p1 = new Result();
        p1.setAge(11);
        p1.setName("张三");
        Result p2 = new Result();
        p2.setAge(12);
        p2.setName("李四");
        list.add(p1);
        list.add(p2);
        String condition = "person.name contains(\"张\")";
        String condition2 = "person.age > 10 && person.age <= 20";
        RulesEngine rulesEngine = new DefaultRulesEngine();
        Rules rules = new Rules();
        
        Rule rule = new MVELRule().when(condition).then("System.out.println(\"name success\")").priority(2);
        Rule rule2 = new MVELRule().when(condition2).then("System.out.println(\"age success\")").priority(1);

        // 要么应用所有规则,要么什么都不应用。
        UnitRuleGroup unitRuleGroup = new UnitRuleGroup();
        unitRuleGroup.addRule(rule); unitRuleGroup.addRule(rule2);
        rules.register(unitRuleGroup);
        
        for (int i = 0; i < list.size(); i++) {
            Facts facts = new Facts();
            facts.put("person", list.get(i));
            rulesEngine.fire(rules, facts);
        }
    }

输出结果:

可以看到 李四没有满足条件 ,其他几个复合规则,大家可自行去尝试。
以上就是easyRule的总结

参考文章:
https://zhuanlan.zhihu.com/p/91158525
https://www.jianshu.com/p/4eb762b559fd

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
规则引擎在Java项目中的使用可以提高系统的可维护性、可扩展性、可重用性和可测试性。以下是Java规则引擎的使用详解: 1. 规则引擎的基本原理: 规则引擎将业务规则形式化、集中管理,将业务规则与应用程序分离。它通过规则的条件和动作来实现业务逻辑的处理。当满足规则的条件时,规则引擎会执行相应的动作。 2. 规则引擎的优势: - 可维护性:规则引擎将业务规则集中管理,使得修改和维护规则变得更加方便。 - 可扩展性:通过添加新的规则,可以快速响应业务变化,而无需修改应用程序的代码。 - 可重用性:规则引擎将业务规则与应用程序分离,可以在不同的应用程序中重用规则。 - 可测试性:规则引擎可以通过单元测试来验证规则的正确性。 3. Java项目中的规则引擎实现方式: 在Java项目中,可以选择多种规则引擎的实现方式,例如: - Drools:Drools是一个开源的规则引擎,它提供了强大的规则管理和执行功能。 - Easy Rules:Easy Rules是一个轻量级的规则引擎,它提供了简单易用的规则定义和执行接口。 - JRules:JRules是IBM提供的一种规则引擎,它具有高性能和可扩展性。 - RuleBook:RuleBook是一个简单的规则引擎,它提供了基本的规则定义和执行功能。 以上是Java规则引擎的使用详解。通过使用规则引擎,可以将业务规则形式化、集中管理,提高系统的可维护性、可扩展性、可重用性和可测试性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值