规则引擎有许多种:Drools,Aviator,Mvel,EasyRule,这里主要讲解一下EasyRule。
easyRule集成了Mvel,而Mvel表达式非常强大,我们可以自己写一些表达式,交给mvel进行解析计算,得到这个表达式计算的值。
easyRule可大致分为三部分:规则引擎,事实,规则
它有两种使用方式:一种是注解,一种是api方式,这里主要介绍一下api的方式
- 规则引擎
从版本3.1开始,Easy Rules提供了RulesEngine接口的两种实现:
DefaultRulesEngine:根据规则的自然顺序(默认为优先级)应用规则。
InferenceRulesEngine:持续对已知事实应用规则,直到不再应用规则为止
什么意思呢?来看一段代码
使用DefaultRulesEngine引擎会根据规则设置的priority属性,从小到大顺序执行。
可以看到age先执行,name后执行。
使用InferenceRulesEngine引擎,会通过循环不停的通过事实去匹配规则,直到全部事实都不匹配规则才停止循环。可以看到源码中就是通过do while循环的
规则引擎也有几个参数默认都为false
- skipOnFirstAppliedRule:告诉引擎规则被触发时跳过后面的规则。
- skipOnFirstFailedRule:告诉引擎在规则失败时跳过后面的规则。
- skipOnFirstNonTriggeredRule:告诉引擎一个规则不会被触发跳过后面的规则。
- rulePriorityThreshold:告诉引擎如果优先级超过定义的阈值,则跳过下一个规则。版本3.3已经不支持更改,默认MaxInt。
通过构造函数设置进去就行了
- 事实
事实如何理解呢?规定定义好了,为谁定义的呢?就是Facts ,规则引擎就是判断这些Facts符不符合规则。在内部,Facts实例持有HashSet<Fact<?>>,这意味着:
1.事实需要命名,应该有一个唯一的名称,且不能为空
2. 任何Java对象都可以充当事实
不好理解来看代码
为了解决上面出现的覆盖问题,可以考虑下面这样的实现
- 规则
上面的案例都是一个事实匹配一个规则(一个person只要满足name包含张或者age >10 && age <20其中一个条件就执行对应规则校验成功后的逻辑),那如何做到一个事实匹配多个规则呢?也就是说一个person不仅要满足name包含张且age >10 && age <20才执行成功后的逻辑,就需要使用复合规则。
UnitRuleGroup:单元规则组是作为一个单元的复合规则:要么应用所有规则,要么什么都不应用。
ActivationRuleGroup:激活规则组是一个复合规则,它触发第一个适用规则,并忽略组中的其他规则(XOR逻辑)。规则首先按照组内的自然顺序(默认优先级)进行排序。
ConditionalRuleGroup:条件规则组是一个复合规则,其中优先级最高的规则充当条件:如果优先级最高的规则求值为true,则触发其余规则。
废话不多说,上demo
输出结果:
可以看到 李四没有满足条件 ,其他几个复合规则,大家可自行去尝试。
以上就是easyRule的总结