rule=“int getvar(double para){ int fvda=0;
if(para>=1000 && para<1000000) fvda=0;
else if(para<1002) fvda=2;
else if(para>=999999 && para<9999999999)
fvda=2;return fvda;}"
这个方法是从数据库查出来的字符串怎么把这个字符串还原成方法,并且我可以调用它

解决方案 »

  1.   

    先创建一个java文件,里面定义只定义类:
    public class Tool{}然后利用IO读写文件,将rule写到这个Tool类中去,最好是写成static方法,这样你就可以调用Tool.getvar()方法了。
      

  2.   

    这个问题之前看到过,类似于动态语言,也就是javascript的eval功能。 没用过见人使用过生成一个java类然后用jdk编译一下,然后在用反射调用。楼主在搜一下吧,.net有eval功能,没准java也早已有人实现了该功能·
      

  3.   


    好方法,要调用java方法,需要实例
      

  4.   

    在程序里把类定义和方法已字符串的形式写出到一个.java文件
    动态编译,加载,反射调用
      

  5.   


    恩差不多就是这个意思,把你读出来的东西写到一个.java文件中,然后自己写个小工具类,用类加载器来加载这个写好的java文件,然后newInstance一个实例出来,就可以正常的对其调用了
      

  6.   

    谢谢各位找到解决的方法了
    使用BeanShell组建
    public static void main(String[] args) {
    Interpreter ip=new Interpreter();
    String rule="int getvar(double para){ int fvda=4;return fvda;}";
    try {
    ip.eval(rule);
    ip.set("para",12);
    ip.eval("fvd=getvar(para)");
    Object  b=ip.get("fvd");
    System.out.println(b);
    } catch (EvalError e) {
    e.printStackTrace();
    }

    }
      

  7.   

    呵呵,还真用了eval功能··楼主结贴哈!
      

  8.   

    我曾经做过一个会计软件计算税收的问题,基于不同情况有不同的计算公式,不同的变量,然后使用公式进行计算得出税务情况。为了达到灵活的目的,这些公式都以字符串的形式存储在数据库里,在具体运算过程中被程序调用。我的方法是把从数据库得到的公式动态的写到一个String方式的class里,然后即时的编译和执行得到答案,想必就是楼主想要的东西。下面把进行编译和计算的类原封不动的贴出来,给楼主进行参考
    package au.com.taxsurvey.calculation;import java.io.File;
    import java.io.FileWriter;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;import com.sun.tools.javac.Main;
    /**
     * <p>Title: <b>Calculation Handler</b></p>
     *
     * <p>Description: This class generates another class to do the calculations based on 
     * the formula and the values of those variables used in the formula. 
     * There are only 2 steps to be applied to use this Calculation Class
     * <ol>
     * <li><b>Instantiate this class. e.g. NewCalculationHandler nch = new NewCalculationHandler();</b></li>
     * <li><b>Call 'calculate(String formula, Map<String, String> values)</b></li><ul>
     *    <li>The formula is the formula used to calculate, e.g. ^ABC + ^BCD</li>
     *    <li>The values map is a map contains the variables and corresponding values, e.g.<br/>
     *    values("ABC", "28.58");<br/>
     *    values("BCD", "312.30");</li>
     *    </ul>
     * </li>
     * <li><b>value type for different types of operations:</b>
     * <table border=1>
     * <tr bgcolor="black">
     *  <td><b><font color=white>Keyword</font></b></td>
     *  <td><b><font color=white>Sample Formula</font></b></td>
     *  <td><b><font color=white>Map Patterns</font></b></td>
     * </tr>
     * <tr>
     *  <td><b>max</b></td>
     *  <td>max(^ABC, ^BCD)</td>
     *  <td>values("ABC", "382.32"), values("BCD", "291.17");</td>
     * </tr>
     * <tr>
     *  <td><b>min</b></td>
     *  <td>same as 'max'</td>
     *  <td>same as 'max'</td>
     * </tr>
     * <tr>
     *  <td><b>sum</b></td>
     *  <td>sum(^ABC)</td>
     *  <td>values("ABC", "382.32"), values("BCD", "291.17");</td>
     * </tr>
     * <tr>
     *  <td><b>if</b></td>
     *  <td>if(^ABC>^BCD) return ^BBC;</td>
     *  <td>values("ABC", "2"), values("BCD", "29"), values("BBC", "3")</td>
     * </tr>
     * <tr>
     *  <td><b>normal calculation</b></td>
     *  <td>(^ABC+^BCD)*^CDE/^BCD</td>
     *  <td>values("ABC", "2"), values("BCD", "29"), values("CDE", "3")</td>
     * </tr>
     * <tr>
     *  <td><b>year</b></td>
     *  <td>if(year(^BCD)>1)return ^DEF; return ^AFO</td>
     *  <td>values("BCD", "\"28092007\""); others are normal variables</td>
     * </tr>
     * <tr>
     *  <td><b>month</b></td>
     *  <td>if(month(^BCD)>11)return ^DEF; return ^AFO</td>
     *  <td>values("BCD", "\"28092007\""); </td>
     * </tr>
     * <tr>
     *  <td><b>day</b></td>
     *  <td>if(day(^BCD)>28)return ^DEF; return ^AFO</td>
     *  <td>values("BCD", "\"28092007\"");</td>
     * </tr>
     * <tr>
     *  <td><b>static string</b></td>
     *  <td>"New South Wales</td>
     *  <td>values(null, null)</td>
     * </tr>
     * </table>
     * </li>
     * </ol>
     * </p>
     *
     * <p>Created on: 21/09/2007</p>
     * 
     *
     */
    public class NewCalculationHandler {    public final static int FIND_MAX = 1;
        public final static int FIND_MIN = -1;
        
    public final static char SIGN = '^';    public final static String MAN_AND1 = " AND ";
        public final static String MAN_AND2 = " and ";    public final static String JAVA_AND = " && ";    public final static String MAN_OR1 = " OR ";
        public final static String MAN_OR2 = " or ";    public final static String JAVA_OR = " || ";
        
        public final static String MAN_SUM1 = "SUM";
        public final static String MAN_SUM2 = "Sum";
        
        public final static String JAVA_SUM = "sum";
        
        public final static String MAN_MAX1 = "MAX";
        public final static String MAN_MAX2 = "Max";
        
        public final static String JAVA_MAX = "max";
        
        public final static String MAN_MIN1 = "MIN";
        public final static String MAN_MIN2 = "Min";
        
        public final static String JAVA_MIN = "min";    public final static String MAN_NOT_EQUAL_TO = "NOT_EQUAL_TO";    public final static String JAVA_NOT_EQUAL_TO = "!=";    public final static String MAN_EQUAL_TO = "==";    public final static String JAVA_EQUAL_TO = "==";    public final static String MAN_GREATER_THAN = ">";    public final static String JAVA_GREATER_THAN = ">";    public final static String MAN_LESS_THAN = "<";    public final static String JAVA_LESS_THAN = "<";
        
        public final static String MAN_IF = "If";
        
        public final static String JAVA_IF = "if";
        
        public final static String MAN_STRING = "\"";
        
        public final static String JAVA_STRING = "\\\"";
        
        public final static String MAN_NOT = "#";
        
        public final static String JAVA_NOT = "!=";
        
        public final static String MAN_NULL = "NULL";
        
        public final static String JAVA_NULL = "null";
        
        public final static String MAN_SUM_INDICATOR = "%";
        
        public final static String JAVA_SUM_INDICATOR = "";
        
        private Map<String, String> rules = new HashMap<String, String>();
        
        private String formula;
        
        // this map has the values for each variable as Map<tag, value>
        // e.g. values<"^ABC", "3.23">
        private Map<String, Object> values = new HashMap<String, Object>();
        
    public String getFormula() {
    return formula;
    } public void setFormula(String formula) {
    this.formula = formula;
    } /**
     * default constructor
     * loads all rules for formula validating.
     */
    public NewCalculationHandler() {
            rules.put(MAN_AND1, JAVA_AND);
            rules.put(MAN_AND2, JAVA_AND);
            rules.put(MAN_OR1, JAVA_OR);
            rules.put(MAN_OR2, JAVA_OR);
            rules.put(MAN_SUM1, JAVA_SUM);
            rules.put(MAN_SUM2, JAVA_SUM);
            rules.put(MAN_MAX1, JAVA_MAX);
            rules.put(MAN_MAX2, JAVA_MAX);
            rules.put(MAN_MIN1, JAVA_MIN);
            rules.put(MAN_MIN2, JAVA_MIN);
            rules.put(MAN_NOT_EQUAL_TO, JAVA_NOT_EQUAL_TO);
            rules.put(MAN_EQUAL_TO, JAVA_EQUAL_TO);
            rules.put(MAN_GREATER_THAN, JAVA_GREATER_THAN);
            rules.put(MAN_LESS_THAN, JAVA_LESS_THAN);
            rules.put(MAN_IF, JAVA_IF);
            rules.put(MAN_STRING, JAVA_STRING);
            rules.put(MAN_NOT, JAVA_NOT);
            rules.put(MAN_NULL, JAVA_NULL);
            rules.put(MAN_SUM_INDICATOR, JAVA_SUM_INDICATOR);
    }

    /**
     * it calls the method that does the actual calculation.
     * @param formula formula string
     * @param values map that contains the variable name as its key, and the corresponding value
     * @return Object the result
     * @throws Exception
     */
    public Object calculate(String formula, Map<String, Object> values) throws Exception{
    // if (!isValidCalculation(formula, values)) {
    // throw new Exception("Value missing for the calculation. " +
    // "Please check if all the variables in the formula has a value.");
    // }
    this.setValues(values);
    this.setFormula(formula);

    // this.substituteFormulaWithValues();

    try {
    return this.doCompile("CalculationTemp");
    } catch (Exception ex) {
    ex.printStackTrace();
    System.out.println("Failed to calculate!");
    }

    return null;
    }

    /**
     * it calls the method that does the a test calculation.
     * @param formula formula string
     * @param values map that contains the variable name as its key, and the corresponding value
     * @return Object the result
     * @throws Exception
     */
    public String testCalculate(String formula, Map<String, Object> values) throws Exception{
    // if (!isValidCalculation(formula, values)) {
    // throw new Exception("Value missing for the calculation. " +
    // "Please check if all the variables in the formula has a value.");
    // }
    this.setValues(values);
    this.setFormula(formula);

    String errMsg = "";
    // try {
    // this.doCompile("CalculationTemp");
    // }
    // catch (Exception ex) {
    // errMsg = "Error due to: " + ex.getMessage();
    // }

    return shouldReturn(formula) + " " + substituteFormulaWithValues() + "\n" + errMsg;

    }

    private boolean isValidCalculation(String formula, Map<String, Object> values) {
    String temp [] = spliter(formula);
    if (temp.length <= values.values().size()) return true;
    return false;
    }

    /**
     * replace syntaxically illegal words in the formula to JAVA readable workds to make 
     * the formula Java syntax
     * 
     * @param formula
     * @return JAVA format formula
     */
        private String convertToJavaCode(String formula) {
            String output = formula.replace(SIGN, ' ');
            Iterator<String> it = rules.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                output = output.replaceAll(key, rules.get(key));
            }
            
    //        if (spliter(output).length == 0) return output;
            
            for (int i = output.length() - 1; i >= 0; i --) {
             char c = output.charAt(i);
             if (c == ';')
             break;
             else {
             if (c == ' ') {
             continue;
             }
             else {
             output += ";";
             break;
             }
             }
            }
            
            return output;
        }由于回复内容不能太长,程序分几次贴出来,LZ粘贴拷贝一下就可以了幸亏这个方法比较复杂,我作了挺完整的Java文档,楼主可以转化出来看一下,应该挺清楚的。这里面doCompile这个方法是关键的地方,楼主想要的东西应该就在这里。
      

  9.   

    /**
     * This method splits the formula and extracts the varialbes.
     * e.g. ^ABC + ^BCD will return {"ABC", "BCD"}
     * 
     * @param formula
     * @return String[] variables
     */
        public static String[] spliter(String formula) {
            int index = 0;
            String temp = "";
            formula += " ";  // to avoid array indexOutOfBound exception
            Set<String> check = new HashSet<String>();
            List<String> output = new ArrayList<String>();
            for (int i = 0; i < formula.length(); i++) {
                index = formula.indexOf(SIGN, i);
                if (index < 0)
                    break;
                for (int n = index; n < formula.length(); n++) {
                    char c = formula.charAt(n + 1);
                    if (Character.isLetterOrDigit(c) || c == '_') {
                        temp += formula.charAt(n + 1);
                    } else {
                        System.out.println("Spliting: " + temp);
                        i = n;
                        break;
                    }
                }
                if (!check.contains(temp)) {
                    output.add(temp);
                }
                check.add(temp);
                temp = "";
            }
            String out[] = new String[output.size()];
            return output.toArray(out);
        }
        
        /**
         * Match the tags and values
         * @param values<String, String> this is the value passed from the client side
         * the Servlet which receives the call will constructed this map.
         */
        private void setValues(Map<String, Object> values) {
         this.values = values;
        
         Iterator keys = values.keySet().iterator();
         while (keys.hasNext()) {
         Object key = keys.next();
         System.out.println("ValuesMap containing: Key = " + key + ", Value = " + values.get(key));
         }
        }
        
        /**
         * if there are missing values for the variables extracted from the formula,
         * set the default value '0' for them.
         */
        public void setDefaultValues() {
         String variables [] = spliter(formula);
        
         for (int i = 0; i < variables.length; i ++) {
         String key = variables[i];
        
         if (!values.containsKey(key)) {
         values.put(key, "0");
         }
         }
        }
        
        /**
         * Substitute the variables in the formula with values from the value map
         *
         */
        public String substituteFormulaWithValues() {
         setDefaultValues();
         Iterator<String> keys = values.keySet().iterator();
         String output = convertToJavaCode(formula);
        
         //if the formula is a plain string
         if (spliter(formula).length == 0)
         output = "\"" + output + "\"";
        
         System.out.println("Formula that is to be substuted: " + output);
         while (keys.hasNext()) {
         String key = keys.next();
         String theValue = values.get(key).toString();
         String value = theValue;
         try {
         value = "" + Double.parseDouble(theValue);
         }
         catch (Exception ex) {
         if (!isANumberArray(value)) {
         value = "\"" + theValue + "\"";
         }
         }
         output = output.replaceAll(key, value);
         System.out.println("Substituting " + key + " with Value " + value);
         }
        
         System.out.println("formula = " + output);
         return output;
        }
        
        public boolean isANumberArray(String input) {
         String [] nums = input.split(",");
         for (int i = 0; i < nums.length; i ++) {
         String num = nums[i].replaceAll(" ", "");
         try {
         double x = Double.parseDouble(num);
         }
         catch (Exception ex) {
         return false;
         }
         }
        
         return true;
        }
        
        public String semiColon() {
         if (spliter(formula).length == 0) {
         return ";";
         }
         return "";
        }
        
        /**
         * determines whether the method should return a value. This is because in formulas like
         * 'if(^ABC) return ^BCD; else return ^DIW;', there's alreay 'return' kayword in it, but in
         * formulas like 'max(^ABC, ^BCD)' it doesn't.
         * @param formula
         * @return String 'return' or ''
         */
        public String shouldReturn(String formula) {
         if (formula.indexOf("return") >= 0) return "";
        
         return "return ";
        }
        
      

  10.   

        public Object doCompile(String className) throws Exception {
         int seed = (int)(100000 * Math.random());
         String path =  System.getProperty("java.io.tmpdir") + "/";
         className += "_" + seed;     path = "";
         ClassLoader loader = ClassLoader.getSystemClassLoader();
        
            String sourceFile = path + className + ".java";
            
            FileWriter fw = new FileWriter(sourceFile);        String code =
             "import java.util.Date;\n" +
             "import java.util.Calendar;\n" +
             "import java.text.DateFormat;\n" +
             "import java.text.SimpleDateFormat;\n\n" +
                "public class " + className + "{\n" + "    public " + className + "() {}\n";
            
            code +=
             " public Object calculate(String input[]) {\n" +
             " " + shouldReturn(formula) + " " + substituteFormulaWithValues() + semiColon() + "\n" +
             " }\n";
            
            code +=
             " public double max(double ... args) {\n" +
             " double max = args[0];\n" +
             " for (int i = 1; i < args.length; i ++) {\n" +
             " if (args[i] > max) max = args[i];\n" +
             " }\n" +
             " return max;\n" +
             " }\n";
            
            code +=
             " public double min(double ... args) {\n" +
             " double min = args[0];\n" +
             " for (int i = 1; i < args.length; i ++) {\n" +
             " if (args[i] < min) min = args[i];\n" +
             " }\n" +
             " return min;\n" +
             " }\n";
            
            code +=
             " public double sum(double ... args){\n" +
             " try {\n" +
             " double output = 0;\n" +
             " for (int i = 0; i < args.length; i ++) {\n" +
             " output += args[i];\n" +
             " }\n" +
             " return output;\n" +
             " }\n" +
             " catch (Exception ex) {\n" +
             " return 0;\n" +
             " }\n" +
             " }\n";
            
            code += 
             " public int minusYear(String dateString, int years){\n" +
             " dateString = dateString.replaceAll(\"-\", \"\");\n" +
             " return year(dateString) - years;\n" +
             " }\n";
            
            code += 
             " public int minusMonth(String dateString, int months){\n" +
             " dateString = dateString.replaceAll(\"-\", \"\");\n" +
             " return month(dateString) - months;\n" +
             " }\n";
            
            code +=
             " private Calendar getCalendar(String dateString) {\n" +
             " DateFormat formatter = new SimpleDateFormat(\"ddMMyyyy\");\n" +
             " try {\n" +
             " Date date = formatter.parse(dateString);\n" +
             " Calendar cal = Calendar.getInstance();\n" +
             " cal.setTime(date);\n" +
             " return cal;\n" +
             " } catch (Exception ex){\n" +
             " ex.printStackTrace();\n" +
             " }\n" +
             " return null;\n" +
             " }\n";
            
            code +=
             " public int year(String dateString) {\n" +
             " return getCalendar(dateString).get(Calendar.YEAR);\n" +
             " }\n";
            
            code +=
             " public int month(String dateString) {\n" +
             " return getCalendar(dateString).get(Calendar.MONTH) + 1;\n" +
             " }\n";
            
            code +=
             " public int day(String dateString) {\n" +
             " return getCalendar(dateString).get(Calendar.DAY_OF_MONTH);\n" +
             " }\n";
            
            code +=
             " public int week(String dateString) {\n" +
             " return getCalendar(dateString).get(Calendar.WEEK_OF_YEAR);\n" +
             " }\n";
            
            code += "}\n";        System.out.println(className + ".java\n\n" + code);
            fw.write(code);
            fw.close();
            File f = new File(sourceFile);
            System.out.println("file path:"+f.getAbsolutePath());
                 int compileReturnCode = Main.compile(new String[] { sourceFile });
            if (compileReturnCode == 0) {
                Object objectParameters[] = { new String[] {} };
                Class classParameters[] = { objectParameters[0].getClass() };
                String packageAndClass = "au.com.taxsurvey.calculation." + className;
    //            Class aClass = Class.forName(packageAndClass);
                Class aClass = Class.forName(path + className);
                Object instance = aClass.newInstance();            Method theMethod = null;
                
                theMethod = aClass.getDeclaredMethod("calculate", classParameters);
                Object obj = theMethod.invoke(instance, objectParameters);
                
                System.out.println("Result: " + obj);
                
                // clean up the created files
             try {
              File file = new File(className + ".class");
              File file2 = new File(className + ".java");
              f.delete();
              file.delete();
              file2.delete();
             } catch (Exception ex) {
             ex.printStackTrace();
             }
            
             return obj;
            }
        
         return null;
        }
        
        /*************Debug********************/
        
        /************** Test ******************/
        public static void main (String args[]){
    //     System.out.println(DateUtility.year("28092007"));
         NewCalculationHandler nch = new NewCalculationHandler();
         String formula = "min(^ABC,^BCD, ^DEC, ^DLA)";
    //     formula = "if (^ABC > ^BCD) return ^DEC; else return ^DLA";
    //     formula = "(^ABC+^BCD)*^DEC-min(^DLA, ^ABC)";
    //     formula = "new south wales";
    //     formula = "if (^ABC>0) return \"greater\"; else return \"less\"";
    //     formula = "sum(^ABC, ^BCD, ^DEC, max(^DLA, ^DEC))";
    //     formula = "If(^ABC>7) return ^BCD; else return \"\";";
    //     formula = "month(^BCD)";
    //     formula = "minusYear(\"20-06-2009\", year(^BCD));";
    //     formula = "Sum(^FFF) + Sum(^BBB)";
         formula = "^ABC + ^BCD";
         Map<String, Object> values = new HashMap<String, Object>();
         values.put("ABC", "8");
         values.put("BCD", "9");
         values.put("DEC", "\"greater\"");
         values.put("DLA", "\"less\"");
         values.put("FFF", "3, 4");
         try {
    nch.calculate(formula, values);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    System.exit(0);
        }
    }============ DONE ============
      

  11.   

    膜拜12楼,要是能给import com.sun.tools.javac.Main;这个工具类就完美了。