使用场景: 需要执行一些可配置的公式来计算结果
例如:某些公司工资的计算,分各种计算方案,拿到对应字段替换到公式中进行结果计算
依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.3</version>
</dependency>
代码
package com.hzr;
import org.apache.commons.jexl3.*;
import org.apache.commons.text.StringSubstitutor;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.math.BigDecimal;
import java.util.*;
public class MyTest {
public static void main(String[] args) {
Map<String,Object> varMap = new HashMap<>();
varMap.put("绩效工资",1000);
varMap.put("年平均月工作日",21.75);
varMap.put("请假天数",20);
/**
* 方法一
*/
String ex = "${绩效工资}/${年平均月工作日}*${请假天数}";
System.out.println(jexlEval(ex,varMap));
/**
* 方法二
*/
try {
System.out.println(jsEval(ex,varMap));
} catch (ScriptException e) {
e.printStackTrace();
}
/**
* 方法三
*/
Map<String,Object> varMap2 = new HashMap<>();
varMap2.put("a",1000);
varMap2.put("b",21.75);
varMap2.put("c",20);
String ex2 = "a/b*c";
System.out.println(jexlEval2(ex2,varMap2));
}
/**
* 占位符 + ScriptEngine 方式
* @param formula
* @return
* @throws ScriptException
*/
public static Object jsEval(String formula,Map<String,Object> varMap) throws ScriptException {
formula = new StringSubstitutor(varMap).replace(formula);
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
Object evaluate = jse.eval(formula);
return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 占位符公式 + Jexl 支持中文占位符
* @param formula
* @param varMap
* @return
*/
public static Object jexlEval(String formula, Map<String,Object> varMap){
formula = new StringSubstitutor(varMap).replace(formula);
JexlEngine jexlEngine = new JexlBuilder().create();
JexlExpression jexlExpression = jexlEngine.createExpression(formula);
Object evaluate = jexlExpression.evaluate(null);
return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 变量公式 + JexlContext 不支持中文公式
* @param formula
* @param varMap
* @return
*/
public static Object jexlEval2(String formula, Map<String,Object> varMap){
JexlContext jc = new MapContext();
varMap.forEach((key,value) ->{
jc.set(key,value);
});
JexlEngine jexlEngine = new JexlBuilder().create();
JexlExpression jexlExpression = jexlEngine.createExpression(formula);
Object evaluate = jexlExpression.evaluate(jc);
return new BigDecimal(evaluate.toString()).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
}
}
输出结果
919.54
919.54
919.54