简单表达式运算

常见场景:

  • 计费公式
  • 规则决策

需求

1. 计费公式

  • 精确度要求高
  • 支持数值运算

2. 规则决策

  • 支持逻辑运算
  • 支持数值运算

实现

1. evalEx

成熟的表达式计算器,通过解析操作符、数值、变量 计算

1
2
3
4
5
6
7
</dependencies>
<dependency>
<groupId>com.udojava</groupId>
<artifactId>EvalEx</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
1
2
3
4
5
6
// 创建表达式
Expression expression = new Expression("amount * 0.1");
// 置入变量
expression.setVariable("amount", request.getAmount());
// 计算
BigDecimal res = expression.eval();

2. groovy

groovy可编译成class文件,与java平滑整合

jsr-223脚本接口调用简单

1
2
3
4
5
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<scope>test</scope>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
// 创建脚本引擎
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("groovy");

// 简单数值运算
Integer sum = (Integer) engine.eval("(1..10).sum()");
assertEquals(new Integer(55), sum);

// 带变量的运算(脚本只需编译一次)
engine.eval("def func01(amount){ 0.01 * amount + 1}");
Invocable inv = (Invocable) engine;
Object res = ((Invocable) engine).invokeFunction("func01", new BigDecimal(5.0));

ps:

不足

  • groovy脚本中默认的小数为bigdecimal;相反,非小数时,精度问题突出
  • 虽然可以人为将表达式,写成小数的。但略复杂
  • 编译执行,缓存脚本费点神

优势

  • 编译执行,效率比工具一高
  • 支持函数更丰富(前提,熟悉groovy)