前言
本来这个主题已经写完了,不过回头看了一下,感觉评估的功能也很有意思,列个单章介绍一下吧。
评估接口
Condition 是一个函数声明接口,就只有一个方法 boolean evaluate(facts),用于评估规则是否满足既定事实。
这两个类似枚举的接口属性比较有意思,在RuleBuilder源码里就有用到。
- FALSE:总是返回false的条件实体。
- TRUE:总是返回true的条件实体。
@FunctionalInterface
public interface Condition {
/**
* 根据已知事实评估规则
*/
boolean evaluate(Facts facts);
/**
* A NoOp {@link Condition} that always returns false.
*/
Condition FALSE = facts -> false;
/**
* A NoOp {@link Condition} that always returns true.
*/
Condition TRUE = facts -> true;
}
常规评估方式
这里用RuleBuilder的例子来说明。
Rule codeRule = new RuleBuilder()
.name("builder-rule")
.description("这是代码规则")
.priority(5)
.when(facts -> (int) facts.get("age") > 18)
.then(facts -> System.out.println("builder rule 被触发1,年龄大于18."))
.build();
RuleBuilder源码
在方法when里限定了规则的触发条件,其实是创建了一个Condition的实体,并在DefaultRule.evaluate()方法里进行规则评估。
condition默认值为Condition.FALSE,如果不设定条件,则规则永远不会被执行。
public class RuleBuilder {
private Condition condition = Condition.FALSE;
/**
* 设置规则触发条件
*/
public RuleBuilder when(Condition condition) {
this.condition = condition;
return this;
}
... 忽略其他代码
public Rule build() {
// 创建默认规则实体
return new DefaultRule(name, description, priority, condition, actions);
}
}
DefaultRule评估
此类构建比较简单,可以看出评估的方式是根据创建规则时写入的条件进行判定。
class DefaultRule extends BasicRule {
...忽略无关代码
@Override
public boolean evaluate(Facts facts) {
return condition.evaluate(facts);
}
}
注解评估
这里带一嘴,注解规则是通过RuleProxy进行代理的,评估方式是解析注解【@Condition】的方法,用java的反射机制来处理【conditionMethod】。
可以参照RuleProxy类的这个方法【invoke】。
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
String methodName = method.getName();
switch (methodName) {
case "getName":
return getRuleName();
...
case "evaluate":
return evaluateMethod(args);
case "execute":
return executeMethod(args);
...
default:
return null;
}
}
表达式评估
可以这么说,easy-rules组件里,评估分类两种,表达式和其他,因为Condition接口的实现类只有【MVELCondition】
注意:evaluate方法里有个注释,不接受已编译的表达式...
public class MVELCondition implements Condition {
private final Serializable compiledExpression;
/**
* 用表达式语法创建一个条件实体
*/
public MVELCondition(String expression) {
compiledExpression = MVEL.compileExpression(expression);
}
@Override
public boolean evaluate(Facts facts) {
// MVEL.evalToBoolean does not accept compiled expressions..
return (boolean) MVEL.executeExpression(compiledExpression, facts.asMap());
}
}
用上一章的例子来说明
Facts factSet = new Facts();
factSet.add(new Fact<>("age", 28));
// 表达式规则
Rule elRule = new MVELRule()
.name("el-rule")
.priority(9)
.description("这是表达式规则")
.when("age > 15")
.then("System.out.println("el rule 被触发,年龄大于15.");");
rules.register(elRule);
最终是做一个数值大小的比较,在MathProcessor中做最终判定。