aviator规则引擎轻量、高性能可以帮我们解决很多配置规则的问题
官方文档参考:Aviator帮助文档
实战一把aviator,举个栗子
对年龄在40岁以内、职级大于等于3的“宋姓”销售人员发放提成,
提成计算公式=“销售量 * 单件提成金额 * 10%”
代码设计:
上述逻辑抽象出两个规则表达式:
"age <= 40 && clazz >= 3 && string.startsWith(name, '宋')"
"salNum * bonus * 10/100"
将两个规则表达式编织成规则chain,顺序执行,上代码
增加pom依赖
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>4.1.2</version>
</dependency>
interface:规则chain
public interface RuleChain {
/***
* 匹配规则表达式chain
* @param context
* @param response:表达式执行结果
*/
void matchRule(AviatorContext context, List<AbstractAviatorRule> response);
}
核心类
class:规则chain接口默认实现类
public class DefaultRuleChain implements RuleChain {
// 规则列表
private List<AbstractAviatorRule> rules;
// 规则列表当前索引
private int position = 0;
public DefaultRuleChain(List<AbstractAviatorRule> rules){
this.rules = rules;
}
@Override
public void matchRule(AviatorContext context, List<AbstractAviatorRule> response) {
while(rules != null && position < rules.size()){
rules.get(position++).execute(context, this, response);
}
}
}
class:抽象规则
@Data
public abstract class AbstractAviatorRule {
// 规则id主键
private Long ruleId;
// 规则表达式
private String expression;
// 表达式执行结果
private AviatorResult result;
/***
* 执行规则表达式
* @param param
* @param ruleChain
* @param response:表达式执行结果对象
*/
public abstract void execute(AviatorContext param, List<AbstractAviatorRule> response);
}
class:抽象规则默认实现,返回值boolean
@Slf4j
public class DefaultAviatorRule extends AbstractAviatorRule {
@Override
public void execute(AviatorContext param, List<AbstractAviatorRule> response) {
super.setResult(executeAndResult(param));
response.add(this);
}
protected AviatorResult executeAndResult(AviatorContext param){
AviatorResult resultInfo = new AviatorResult();
try {
boolean result = AviatorExecutor.execute(param, super.getExpression());
resultInfo.setSuccess(result);
}catch (Exception e){
log.error("DefaultAviatorRule execute error: {}", e);
}
return resultInfo;
}
}
class:默认规则子类计算型规则,返回值Double
@Slf4j
public class CalculatorAviatorRule extends DefaultAviatorRule {
@Override
protected AviatorResult executeAndResult(AviatorContext param){
AviatorResult resultInfo = new AviatorResult();
try {
Double result = AviatorExecutor.execute(param, super.getExpression());
resultInfo.setSuccess(true);
resultInfo.setResult(result);
}catch (Exception e){
log.error("CalculatorAviatorRule execute error: {}", e);
}
return resultInfo;
}
}
class:aviator执行器
public class AviatorExecutor {
public static <T> T execute(AviatorContext context, String expression){
Map<String, Object> param = AviatorContext.buildMap(context);
return (T) AviatorEvaluator.execute(expression, param, true);
}
}
辅助类
@Data
public class AviatorContext {
@AviatorProperty("姓名")
private String name;
@AviatorProperty("年龄")
private Integer age = 0;
@AviatorProperty("职级")
private Integer clazz = 0;
@AviatorProperty("提成")
private Double bonus;
@AviatorProperty("销售数量")
private Integer salNum;
/***
* 将对象转为Map
* @param context
* @return
*/
public static Map<String, Object> buildMap(AviatorContext context){
Map<String, Object> env = new HashMap<>();
if(null == context){
return env;
}
List<Field> fieldList = new ArrayList<>();
Class clz = context.getClass();
int deep = 0;
while(deep < 5 && null != clz){
fieldList.addAll(new ArrayList<>(Arrays.asList(clz.getDeclaredFields())));
clz = clz.getSuperclass();
deep++;
}
for(Field field : fieldList){
try {
PropertyDescriptor property = new PropertyDescriptor(field.getName(), context.getClass());
Method method = property.getReadMethod();
env.put(field.getName(), method.invoke(context));
} catch (Exception e) {
e.printStackTrace();
}
}
return env;
}
}
@Data
public class AviatorResult {
private boolean success;
private Object result;
public AviatorResult(){}
public AviatorResult(boolean success){
this(success, null);
}
public AviatorResult(boolean success, Object result){
this.success = success;
this.result = result;
}
}
测试类
class TestMain{
public static void main(String[] args) {
// aviator上下文
AviatorContext context = buildContext();
// 存储表达式执行结果
List<AbstractAviatorRule> response = new ArrayList<>();
// 规则chain
RuleChain ruleChain = new DefaultRuleChain(rules());
ruleChain.matchRule(context, response);
System.out.println(JSON.toJSONString(response));
}
private static AviatorContext buildContext(){
AviatorContext context = new AviatorContext();
context.setName("宋小宝");
context.setAge(35);
context.setClazz(3);
context.setBonus(10d);
context.setSalNum(20);
return context;
}
private static List<AbstractAviatorRule> rules(){
AbstractAviatorRule rule1 = new DefaultAviatorRule();
rule1.setRuleId(1001l);
rule1.setExpression("age <= 40 && clazz >= 3 && string.startsWith(name, '宋')");
AbstractAviatorRule rule2 = new CalculatorAviatorRule();
rule2.setRuleId(1002l);
rule2.setExpression("salNum * bonus * 10/100");
List<AbstractAviatorRule> rules = new ArrayList<>();
rules.add(rule1);
rules.add(rule2);
return rules;
}
}
执行结果
[{
"expression": "age <= 40 && clazz >= 3 && string.startsWith(name, '宋')",
"result": {
"success": true
},
"ruleId": 1001
}, {
"expression": "salNum * bonus * 10/100",
"result": {
"result": 20.0,
"success": true
},
"ruleId": 1002
}]
结语
核心设计其实就是将多个规则加入RuleChain中串行执行,并输出执行结果,业务基于执行结果做下一步操作,可以对一串规则做与(所有规则都满足)、或(只要有一个规则满足)的逻辑。
获取源码请点击