用Java進行動態公式處理



最近有個需求是通過動態的配置公式 對表數據進行一些邏輯計算
目前采用的是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:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM