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

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 {@Testpublic 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))));}@Testpublic 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中表达式引擎工具就用它!建议收藏,一定用的到!!相关推荐

  1. 又发现一款牛逼的 API 敏捷开发工具

    来源:xie.infoq.cn/article/b5c3a339267e1351c6151b42a   初衷 跟大家分享一个牛逼的 API 敏捷开发工具,用尽可能简单的方式,完成尽可能多的需求.通过约 ...

  2. 几款超牛逼的终端命令行工具!好用到爆

    点击关注公众号,回复"1024"获取2TB学习资源! 终端是程序员的必备工具之一,本文将介绍许多牛逼且实用的开源工具,本文仅对工具做基本介绍,不提供安装方法,因为这些工具的安装方法 ...

  3. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)

    文章目录 八.Java中的并发工具类 8.1 等待多线程完成的CountDownLatch 8.2 同步屏障CyclicBarrier 8.2.1 CyclicBarrier简介 8.2.2 Cycl ...

  4. 《Java并发编程的艺术》读后笔记-Java中的并发工具类(第八章)

    文章目录 <Java并发编程的艺术>读后笔记-Java中的并发工具类(第八章) 1.等待多线程完成的CountDownLatch 2.同步屏障CyclicBarrier 2.1 Cycli ...

  5. Java中使用ItextPdf工具根据PDF合同模板填充pdf

    Java中使用itextPdf工具根据PDF合同模板填充内容 设置PDF合同模板的文本域 导入itextPdf的pom依赖 编写生成填充pdf代码 1:设置PDF合同模板的文本域 ​ 设置PDF文本域 ...

  6. java ftp ftpclient_详解JAVA中使用FTPClient工具类上传下载

    详解JAVA中使用FTPClient工具类上传下载 在Java程序中,经常需要和FTP打交道,比如向FTP服务器上传文件.下载文件.本文简单介绍如何利用jakarta commons中的FTPClie ...

  7. 呕心沥血集齐史上最全 JavaScript最实用工具函数大全,建议收藏!

    为元素添加on方法 Element.prototype.on = Element.prototype.addEventListener; NodeList.prototype.on = functio ...

  8. 最牛逼 Java 日志框架 — Log4j2,性能无敌,横扫对手.....

    Logback 算是JAVA 里一个老牌的日志框架,从06年开始第一个版本,迭代至今也十几年了.不过logback最近一个稳定版本还停留在 2017 年,好几年都没有更新:logback的兄弟 slf ...

  9. 阿里那些牛逼带闪电的开源工具

    开源展示了人类共同协作,成果分享的魅力,每一次技术发展都是站在巨人的肩膀上,技术诸多创新和发展往往就是基于开源发展起来的,没有任何一家网络公司可以不使用开源技术,仅靠自身技术而发展起来.阿里巴巴各个团 ...

最新文章

  1. Java面向对象知识点精华
  2. 用UltraISO制作支持windows 7的U盘启动盘
  3. java父类调用被子类重写的方法
  4. 1411区间内的真素数2
  5. [How TO]-How to install maven
  6. python中所有保留字首字母都是小写_int是不是python的保留字
  7. 1562: 比较大小(思维)
  8. CodeForces - 1263A Sweet Problem(思维,水题)
  9. 面试必问系列之在浏览器中输入URL后到网页显示 其间发生了什么?
  10. 使用NoSQL实现实体服务–第4部分:Java EE
  11. VS Code配置C/C++
  12. zabbix之监控mysql云服务
  13. 新型智能芯片防伪印章设备_思格特智能印章管理系统成功签约山东问童动力设备公司...
  14. 【LeetCode】剑指 Offer 60. n个骰子的点数
  15. oracle中nvarchar2字符集不匹配
  16. python的http请求和应答_python通过get,post方式发送http请求和接收http响应的方法,pythonget...
  17. 从Android support到Androidx
  18. 推荐系统实战--movieslens数据集实现UserCF算法
  19. 多传感器融合定位 第七章 基于滤波的融合方法
  20. 《大秦帝国》第四部,阵容太强大

热门文章

  1. android led灯框架_LED面板灯的特点:应用领域、产品结构与产品分类
  2. php导出csv带图片,PHP导出CSV文件:刚测试过,这个导出CSV可以
  3. 802.11 n wlan linux驱动下载,802.11n无线网卡驱动
  4. int指针初始化_C++:变量,指针,引用const,extern,using,typedef,decltype关键字
  5. 地址总线是单向还是双向_如何区分晶闸管的单双向问题?
  6. 九度OJ-1088剩下的树
  7. Lackey:一个示例工具
  8. 网络中广播和多播的认识
  9. python中获取目录下所有文件名以及读取一个文件内的每一行
  10. CouchDB未授权访问漏洞记录(端口:5984、6984,CVE-2017-12635,CVE-2017-12636)复现失败