aviator实战

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中串行执行,并输出执行结果,业务基于执行结果做下一步操作,可以对一串规则做与(所有规则都满足)、或(只要有一个规则满足)的逻辑。

获取源码请点击

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值