解析器:
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import com.tf.arithmetic.bean.Exterior; /** * 自定义计算表达式解析器和计算器 * 表达式的写法:@{占位变量} * @author yzl * */ public class ExpressionResolver { private ExpressionResolver(){} private static ExpressionResolver resolver = null; public static ExpressionResolver getInstance(){ if(null==resolver){ resolver = new ExpressionResolver(); } return resolver; } /** * 计算表达式的结果 * @param expression 解析包含@{}的表达式 * @param bean * @param precision * @return * @throws ScriptException * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ public double getExecuteResult(String expression, Object bean, int precision) throws ScriptException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { expression = this.parse(expression, bean); ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript"); double result = (Double) se.eval(expression); return MathUtils.multiply(result, 1d, precision); } /** * 解析自定义的@{}表达式 * (@{ys}*0.3+@{csd}*0.25+@{jg}*0.15+@{sf}*0.12+@{yf}*0.1+@{sd}*0.08)*10 * @param expression * @param bean * @return * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ private String parse(String expression, Object bean) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ //保存表达式中的所有变量 List<String> variableList = new ArrayList<String>(); String reg = "@\{"; String reg2 = "\}"; Pattern pattern = Pattern.compile(reg); Pattern pattern2 = Pattern.compile(reg2); String[] arr = pattern.split(expression); for(int i=0; i<arr.length; i++){ if(!"(".equals(arr[i]) && !")".equals(arr[i])){ variableList.add(pattern2.split(arr[i])[0]); } } String fieldName = null; String methodName = null; Object result = null; //用值替换表达式中的变量 if(variableList.size()>0){ Field[] field = bean.getClass().getDeclaredFields(); for(int i=0; i<field.length; i++){ fieldName = field[i].getName(); methodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); result = bean.getClass().getMethod(methodName, null).invoke(bean); expression = expression.replace("@{"+fieldName+"}", result.toString()); } } return expression; } public static void main(String[] args) throws Exception { String input = "(@{ys}*0.3+@{csd}*0.25+@{jg}*0.15+@{sf}*0.12+@{yf}*0.1+@{sd}*0.08)*10"; String reg = "@\{"; String reg2 = "\}"; Pattern pattern = Pattern.compile(reg); Pattern pattern2 = Pattern.compile(reg2); String[] arr = pattern.split(input); for(int i=0; i<arr.length; i++){ if(!"(".equals(arr[i]) && !")".equals(arr[i])){ System.out.println("得到变量:"+pattern2.split(arr[i])[0]); } } Exterior bean = new Exterior(8,8,8,8,8,8); double val = ExpressionResolver.getInstance().getExecuteResult(input, bean, 2); System.out.println(val); } }
需要的实体bean(例子):
/** * 某模型的pojo对象 * @author yzl * */ public class Exterior { private int ys; private int csd; private int jg; private int sf; private int yf; private int sd; public int getYs() { return ys; } public void setYs(int ys) { this.ys = ys; } public int getCsd() { return csd; } public void setCsd(int csd) { this.csd = csd; } public int getJg() { return jg; } public void setJg(int jg) { this.jg = jg; } public int getSf() { return sf; } public void setSf(int sf) { this.sf = sf; } public int getYf() { return yf; } public void setYf(int yf) { this.yf = yf; } public int getSd() { return sd; } public void setSd(int sd) { this.sd = sd; } public Exterior(int ys, int csd, int jg, int sf, int yf, int sd) { super(); this.ys = ys; this.csd = csd; this.jg = jg; this.sf = sf; this.yf = yf; this.sd = sd; } public Exterior() { super(); } }