牛逼,Java中表达式引擎工具就用它!建议收藏,一定用的到!!

Posted Hollis Chuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛逼,Java中表达式引擎工具就用它!建议收藏,一定用的到!!相关的知识,希望对你有一定的参考价值。

最近在负责一个和定价有关的系统,要做分层的价格决策。在决策过程中有两个诉求:

1、需要根据一定的表达式公式,进行分层决策。如订单金额大于1000元时,给10块钱红包,介于100和1000之间的给5元红包。
2、具体价格的产出,需要根据一定的公式。比如根据用户订单金额,乘一个固定的系数。

这时候,就需要一个表达式引擎。需要能够做表达式匹配和数学公式计算。

调研了业内很多的表达式引擎工具,如Ognl、MVEL、IKExpression、Aviator等,根据易用性、性能、可维护性、功能多少等,最终选择了Aviator这款工具。

Aviator

根据Aviator文档的介绍,Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,除了依赖 commons-beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K。

同时, Aviator 内置的函数库非常“节制”,除了必须的字符串处理、数学函数和集合处理之外,类似文件 IO、网络等等你都是没法使用的,这样能保证运行期的安全,如果你需要这些高阶能力,可以通过开放的自定义函数来接入。因此总结它的特点是:
• 高性能
• 轻量级
• 一些比较有特色的特点:
• 支持运算符重载
• 原生支持大整数和 BigDecimal 类型及运算,并且通过运算符重载和一般数字类型保持一致的运算方式。
• 原生支持正则表达式类型及匹配运算符 =~
• 类 clojure 的 seq 库及 lambda 支持,可以灵活地处理各种集合
• 开放能力:包括自定义函数接入以及各种定制选项

用法

Aviator 用法很简简单,首先引入jar包:

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

获取一个Aviator实例:

AviatorEvaluatorInstance aviatorEvaluator = AviatorEvaluator.getInstance()

接着,对表达式进行编译:

Expression expression =  aviatorEvaluator.compile("a > 100 && b< 100");
Expression expression = aviatorEvaluator.compile("a + 150");

在执行表达式验证和计算。


expression..execute(params);

这里面对params是一个Map,Map中的Key就是表达式中的变量,如a、b等。

如:

AviatorEvaluator.getInstance().compile("a > 300 && a<500").execute(ImmutableMap.of("a", new BigDecimal(400));
AviatorEvaluator.getInstance().compile("a + 123.2").execute(ImmutableMap.of("a", 400)).compareTo(new BigDecimal("523.2"));

为了方便使用,我们还可以定一个util工具类:

/**
 * 表达式处理工具类
 *
 * @author Hollis
 */
public class ExpressionUtil 

    public static AviatorEvaluatorInstance aviatorEvaluator = AviatorEvaluator.getInstance();

    static 
        aviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
    
    
	/**
	*表达式验证
	**/
    public static boolean verify(String expression, Map<String, Object> params) 
        return (Boolean)aviatorEvaluator.compile(expression).execute(params);
    

    /**
     * 表达式计算
     * @param expression 表达式
     * @param params 需要替换的表达式参数
     * @return calculate result
     */
    public static BigDecimal calculate(String expression, Map<String, Object> params) 
        return (BigDecimal)aviatorEvaluator.compile(expression).execute(params);
    


使用单元测试对以上方法进行验证:

public class ExpressionUtilTest 

    @Test
    public void test() 

        Assert.assertTrue(ExpressionUtil.verify("a > 300 && a<500", ImmutableMap.of("a", new BigDecimal(400))));

        Assert.assertFalse(ExpressionUtil.verify("a > 300 && a<500", ImmutableMap.of("a", new BigDecimal(600))));

        Assert.assertTrue(
            ExpressionUtil.verify("a > 300 && b<500 && c < 600",
                ImmutableMap.of("a", new BigDecimal(400), "b", new BigDecimal(400), "c", new BigDecimal(500))));

        Assert.assertFalse(
            ExpressionUtil.verify("a > 300 && b<500 && c < 600",
                ImmutableMap.of("a", new BigDecimal(400), "b", new BigDecimal(400), "c", new BigDecimal(700))));

    

    @Test
    public void test1() 
        Assert.assertEquals(0,
            ExpressionUtil.calculate("a + 123.2", ImmutableMap.of("a", 400)).compareTo(new BigDecimal("523.2")));

        Assert.assertEquals(0,
            ExpressionUtil.calculate("a + b", ImmutableMap.of("a", new BigDecimal("0.1"), "b", new BigDecimal("0.2")))
                .compareTo(new BigDecimal("0.3")), 0);
    


以上,就是简单的Aviator的使用方法,快快在你的代码中实践起来吧,如果有收获,请一键三连哦!!!

以上是关于牛逼,Java中表达式引擎工具就用它!建议收藏,一定用的到!!的主要内容,如果未能解决你的问题,请参考以下文章

牛逼!超级黑客用10部分讲明白Git (建议收藏)

建议收藏15755字,讲透MySQL性能优化(包含MySQL架构存储引擎调优工具SQL索引建议等等)

建议收藏!大厂Java高级多套面试专题整理集合

-波波烤鸭博客文章汇总篇Java核心,经典开源框架应用及源码分析,企业级解决方案等强烈建议收藏!!!

程序员常用资源工具集合(建议收藏)

置顶文章-波波烤鸭博客文章汇总篇Java核心,经典开源框架应用及源码分析,企业级解决方案等强烈建议收藏!!!