java规则引擎Aviator

4 篇文章 1 订阅
1 篇文章 0 订阅

在灰度系列中《基于springcloud的灰度实现方案(二)》,之前规则适配使用数据库+策略模式实现,单个规则还好,多个规则,各种场景使用,还是稍微有点欠缺。就想着用java规则引擎来解决这个问题。

之前在项目中使用过drools,比较重,初始加载复杂,首次执行效率较低,最好预热一下,其次分布式规则处理时的一致性也得自己把控;

之前就了解过aviator,这次就直接用了。

相关资料

# 官网地址
https://github.com/killme2008/aviator
# 开发文档
https://www.yuque.com/boyan-avfmj/aviatorscript/cpow90

简介:

在5.0之前aviator只是一个表达式引擎主要用于各
种表达式的动态求值。
到5.0以后,aviator 变成了一门通用的脚本语言aviatorScript.
- 直接翻译成对应的java字节码;
- 高性能(最多扫两套)
- 轻量级,只依赖commons-beanutils这个库的反射,整个jar到5.0页就430k;
相对有特色的点:
- 支持运算重载;
- 原生支持大整数和BigDecimal类型及运算;
- 原生支持正则表达式类型及匹配运算符 =~;
- 类clojure的seq库及lambda支持可以灵活地处理各种集合
- 开放能力:包括自定义函数接入以及各种定制选项


ps: 如果用不到5.0以后的功能,使用之前的版本即可,之前的包只有几十kb;

特性:

  • 词法作用域 {…} ,和 let 定义作用域内的变量

  • return 语句,用于从函数或者 script 中返回(值)。

  • if/elsif/else 条件语句

  • for/while 循环语句,以及 break / continue 支持

  • fn 语法用于定义命名函数, 4.0 已经引入了 lambda -> … end语法专门用于匿名函数定义

  • 单行注释 支持

  • 和 Java Scripting API 更好的集成

  • 字符串插值

  • 异常处理 try…catch…finally 语句等等。

项目中使用

        <dependency>
            <groupId>com.googlecode.aviator</groupId>
            <artifactId>aviator</artifactId>
            <version>5.2.5</version>
        </dependency>

示例:比如,在灰度规则里 手机尾号为9和0,用户id>901,注册时间大于‘2021-06-25’ 的用户进入灰度环境 硬编码好说,策略也还好,但是如果加上或运算,策略也不好处理, 表达式最好了

    @Test
    public void grayRule(){
        Map<String,Object> map = new HashMap<>();
        final Date date = new Date();
        String dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS").format(date);
        map.put("mobileTail","9");
        map.put("userId",901);
        map.put("registerTime",dateStr);
        map.put("mobile","15600000269");
        map.put("sex",1);
        map.put("age",28);
        // 手机尾号
        String expression = "(string.startsWith('9,0',mobileTail) && userId>=901 && registerTime>'2021-06-25 00:00:00')";
        Boolean flag = (Boolean) AviatorEvaluator.execute(expression, map);
        Assert.assertTrue("规则验证通过",flag);
    }

用了以后,操作真简单。

执行方式一:直接表达式+参数

AviatorEvaluator.execute() 
或
AviatorEvaluator.getInstance().execute()

最终底层:
AviatorEvaluatorInstance.execute()

script脚本+ 参数


执行方式二:script脚本+参数

script脚本

str = "";
if (age <=1 ){
  str = "婴儿";
} elsif (age>1 && age<=6) {
   str = "儿童";
} elsif (age>6 && age<=17) {
  str = "青少年";
} elsif (age>18 && age<=40){
  str = "青年";
} elsif (age>40 && age<=48){
  str = "壮年";
} elsif (age>48 && age<=65){
  str = "中年";
} elsif (age>65){
  str = "老年";
}
return str="#{name}处在#{str}期";

@Test
public void script2() throws IOException {
    //编译脚本
    //路径是文件系统的绝对路径或相对路径,
    //相对路径的时候,必须项目的根目录开始的相对路径
    //classpath下的绝对或相对路径
    Expression compiledExp = AviatorEvaluator.getInstance().compileScript("src/test/resources/script.av");
    //执行脚本,参数可以map,也可以通过newEnv kv对的方式塞入,最终还是map
    final Object o = compiledExp.execute(compiledExp.newEnv("age", 12, "name", "yxk"));
    System.out.println(o);
}

输出结果

> yxk处在青少年期

#### 内置函数

aviator内置了很多函数,具体可以看官网 https://www.yuque.com/boyan-avfmj/aviatorscript/ashevw

比如:上面我们用的string.startsWith(‘9,0’,mobileTail)

@Test
public void function_in(){
    long num =(Long) AviatorEvaluator.getInstance().execute("math.round(4.3)");
    Assert.assertEquals("4.3四舍五入后", 4L ,num);
    Map<String,Object> map = new HashMap<>();
    map.put("str","yxkong");
    map.put("head","yxk");
    Boolean flag = (Boolean) AviatorEvaluator.getInstance().execute("string.contains(str,head)",map);
    Assert.assertTrue("yxkong包含yxk",flag);
}

#### 自定义函数

//定义函数
class AddFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {

    long num1 = FunctionUtils.getNumberValue(arg1, env).longValue();
    long num2 = FunctionUtils.getNumberValue(arg2, env).longValue();
    return AviatorLong.valueOf(num1+num2);
}

@Override
public String getName() {
    return "add";
}

}

@Test
public void function_my(){
    // 注册自定义函数
    AviatorEvaluator.addFunction(new AddFunction());
    long num =(Long) AviatorEvaluator.getInstance().execute("add(3,4)");
    Assert.assertEquals("3+4", 7L,num);
}

![公众号图片](https://img-blog.csdnimg.cn/20210407102553361.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Y4MDQwNzUxNQ==,size_16,color_FFFFFF,t_70#pic_center)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
aviator规则引擎配置是指在使用aviator规则引擎的过程中,对其进行相关参数的设置和调整,以适应具体业务的需求和实际场景的要求。 配置aviator规则引擎通常包括以下几个方面: 1. 规则文件的加载:在使用aviator规则引擎之前,需要将规则文件加载到引擎中。规则文件可以是文本文件,也可以是数据库中的数据。通过适当的配置,可以指定规则文件的路径或者连接信息,使得引擎能够正确地加载和解析规则文件。 2. 规则变量的设置:规则引擎需要获取和设置一系列的规则变量,以进行规则的计算和推理。在配置引擎时,可以指定规则变量的名称、类型和初值,以及变量的作用域和可见性等。这样,在使用规则引擎时可以直接引用规则变量,进行相应的计算和判断。 3. 规则优先级的设定:规则引擎通常会包含多条规则,而这些规则有时候会有互相之间的冲突。通过设定规则的优先级,可以确定规则执行的先后顺序,从而在执行过程中遵循预期的逻辑。一般来说,可以通过给规则设置权重或者指定执行顺序的方式来设定规则的优先级。 4. 规则引擎选项的调整:aviator规则引擎通常提供了一系列的配置选项,用于控制规则的执行模式和行为。比如,可以通过设置最大执行时间、最大递归深度、启用缓存等选项来控制规则的执行效率和安全性。此外,还可以针对debug模式、编译模式和并发模式等方面进行相应的设置。 通过合理的配置,aviator规则引擎可以在各种复杂的场景下发挥出强大的计算和决策能力,提高系统的效率和灵活性。但是需要注意的是,配置规则引擎要根据具体的需求和条件,避免过度的调整和复杂的配置,以免引起不必要的性能开销或者错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值