package org.jeecg.modules.mdc.util; import org.apache.commons.jexl3.*; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.Map; /** * @Author: Lius * @CreateTime: 2025-08-19 * @Description: 自定义公式计算类 */ @Component public class JexlFormulaCalculator { // 通过JexlBuilder创建JexlEngine实例 private static final JexlEngine jexl = new JexlBuilder().create(); /** * 计算自定义公式,除数为0时返回0 * @param formula 公式字符串,如 "processLong/measureTime*1.0" * @param variables 公式中的变量键值对 * @return 计算结果(BigDecimal类型,除数为0时返回0) */ public BigDecimal calculate(String formula, Map variables) { try { // 解析公式 JexlExpression expression = jexl.createExpression(formula); // 创建上下文并注入变量 MapContext context = new MapContext(); for (Map.Entry entry : variables.entrySet()) { String varName = entry.getKey(); Object value = entry.getValue(); // 确保变量为数字类型 if (value instanceof Number) { context.set(varName, value); } else { throw new IllegalArgumentException("变量" + varName + "必须是数字类型"); } } // 执行计算 Object result = expression.evaluate(context); // 转换为BigDecimal返回 if (result instanceof Number) { return new BigDecimal(result.toString()); } else { throw new RuntimeException("公式计算结果不是数字"); } } catch (JexlException e) { // 关键:不依赖内部类,直接通过异常消息判断除数为0 if (e.getMessage() != null && e.getMessage().contains("division by zero")) { return BigDecimal.ZERO; // 除数为0返回0 } // 其他JEXL异常正常抛出 throw new RuntimeException("公式计算失败: " + formula, e); } catch (Exception e) { throw new RuntimeException("公式计算失败: " + formula, e); } } }