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;}@Overridepublic 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 {@Overridepublic 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 {@Overrideprotected 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<>();// 规则chainRuleChain 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中串行执行,并输出执行结果,业务基于执行结果做下一步操作,可以对一串规则做与(所有规则都满足)、或(只要有一个规则满足)的逻辑。
获取源码请点击