使用Rhino实现自定义函数
因为一些特别的要求,系统要提供一个自定义的文本框,让用户输入自定义的计算,系统要提供对用户输入的内容的解析和结果计算功能。经过一些搜索、查找和分析,选择使用Rhino和BSF+Beanshell。首先是使用Rhino试验了一下,感觉还不错,记录下来。BSF+Beanshell还没有试,后面试了再说。
先从 http://www.mozilla.org/rhino/下载最新版的rhino,当前是1.74版。解压,然后在IDE中添加对解压后的js.jar库文件引用。
先写个简单的表达式计算:
public class RunIsPrime { private Context cx; private Scriptable scope; public static void main(String[] args){ String filename = System.getProperty("user.dir") + "\\src\\isprime.js"; RunIsPrime rip = new RunIsPrime(); String jsContent = rip.getJsContent(filename); Context cx = Context.enter(); // 初始化Scriptable Scriptable scope = cx.initStandardObjects(); // 这一句是必须的,否则 scope.get("isPrime", scope)返回不了Function,而是返回UniqueTag cx.evaluateString(scope,jsContent,filename,1,null); // 得到自定义函数 Function isPrimeFn = (Function) scope.get("isPrime", scope); // 看看得到的对象是个什么类型,这里是Function System.out.println(isPrimeFn.getClassName()); // 调用自定义函数,第三个参数一般应该是传调用对象,但我发现对函数来说,传null也可以得到同样的结果 // 第四个参数是函数的参数,以对象数据的形式传递 Object isPrimeValue = isPrimeFn.call(cx,isPrimeFn,null,new Object[]{31}); System.out.println("31 is prime? " + Context.toBoolean(isPrimeValue)); isPrimeValue = isPrimeFn.call(Context.getCurrentContext(),isPrimeFn,isPrimeFn,new Object[]{33}); System.out.println("33 is prime? " + Context.toBoolean(isPrimeValue)); } private String getJsContent(String filename) { LineNumberReader reader; try { reader = new LineNumberReader(new FileReader(filename)); String s = null; StringBuffer sb = new StringBuffer(); while ((s = reader.readLine()) != null) { sb.append(s).append("\n"); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); return null; } }}Rhino还可以让自定义的javascript和java交换数据,可以网上搜一下,很多的,如http://lcllcl987.iteye.com/blog/87423
Rhino可以实现动态的功能解析,给自定的功能扩展保留一定的空间。