最近有个需求是通过动态的配置公式 对表数据进行一些逻辑计算
目前采用的是JEP这个开源类库 目前2.4版是免费的 3.0开始收费不过功能更强大更多可配置的东西.
公式实体(Formula) 配置的时候需要记录 表名(tableCode) 条件表达式(conditionExpr) 公式表达式(formulaExpr) 所需要赋的值(evaluate) 顺序号(orderNum)
/**
* Created by Teddy on 2017/10/23.
*/
public class ExpressionUtil {
/**
* 计算List<Bean>配置了公式的值
* @param beanList
* @return
*/
public static List<Map> workOutListBean(List<? extends BaseEntity> beanList){
if(CollectionUtils.isEmpty(beanList)){
return Collections.EMPTY_LIST;
}else {
Class<? extends BaseEntity> beanClass = beanList.get(0).getClass();
Table table = beanClass.getAnnotation(Table.class);//在实体中通过JPA注解获取表名
String tableCode = table.name();
if(StringUtil.isEmpty(tableCode)){
System.out.println("无法计算,该bean没有表名信息");
}
List<Map> mapList = BeanUtil.convertBeansToMaps(beanList);
FormulaService formulaService = SpringContext.getBean(FormulaService.class);
List<Formula> formulas = formulaService.queryByTableCode(tableCode);
for (Map map : mapList) {
JEP jep = getJEP(map);
for (Formula formula : formulas) {
String conditionExpr = formula.getConditionExpr();
String formulaExpr = formula.getFormulaExpr();
String evaluate = formula.getEvaluate();
workOutKey(jep,map,conditionExpr,formulaExpr,evaluate);
}
}
return mapList;
}
}
/**
* 非动态配置公式方式
* @param mapList
* @param conditionExpr
* @param formulaExpr
* @param evaluate
*/
public static void workOutListMap(List<Map> mapList,String conditionExpr,String formulaExpr, String evaluate){
for (Map map : mapList) {
JEP jep = getJEP(map);
workOutKey(jep,map,conditionExpr,formulaExpr,evaluate);
}
}
/**
* 计算出表达式并填充
* @param jep
* @param map
* @param conditionExpr
* @param formulaExpr
* @param evaluate
*/
private static void workOutKey(JEP jep,Map map,String conditionExpr, String formulaExpr, String evaluate){
//如果没有条件
if(StringUtil.isEmpty(conditionExpr)){
map.put(evaluate,workOutSingle(jep,formulaExpr));
//如果有条件 且条件为true
}else if(workOutBool(jep,conditionExpr)){
map.put(evaluate,workOutSingle(jep,formulaExpr));
}
}
/**
* 判断条件表达式
* @param jep
* @param expression
* @return
*/
private static boolean workOutBool(JEP jep,String expression){
return (Double)workOutSingle(jep,expression) > 0;
}
/**
* 计算表达式的值
* @param jep
* @param expression
* @return
*/
private static Object workOutSingle(JEP jep,String expression){
Object result = null;
try { //执行
Node parse = jep.parse(expression);
result = jep.evaluate(parse);
} catch (ParseException e) {
throw new BaseRunTimeException("公式表达式解析失败",e);
}
if(result == null){
throw new BaseRunTimeException("公式表达式解析失败");
}
return result;
}
/**
* 获取填充好变量的JEP对象
* @param param
* @return
*/
private static JEP getJEP(Map param){
JEP jep = new JEP();
Set<Map.Entry> set = param.entrySet();
for (Map.Entry entry : set) {
Object entryValue = entry.getValue();
String entryKey = (String) entry.getKey();
jep.addVariable(entryKey, entryValue);
}
return jep;
}
}
以下是示例Demo: