因为一些特别的要求,系统要提供一个自定义的文本框,让用户输入自定义的计算,系统要提供对用户输入的内容的解析和结果计算功能。经过一些搜索、查找和分析,选择使用Rhino和BSF+Beanshell。首先是使用Rhino试验了一下,感觉还不错,记录下来。BSF+Beanshell还没有试,后面试了再说。
先从 http://www.mozilla.org/rhino/下载最新版的rhino,当前是1.74版。解压,然后在IDE中添加对解压后的js.jar库文件引用。
先写个简单的表达式计算:
public class MathEval {
public static void main(String[] args){
Context cx = Context.enter();
try{
Scriptable scope = cx.initStandardObjects();
String str = "8*(1+2)";
Object result = cx.evaluateString(scope,str, null,1,null);
double res = Context.toNumber(result);
System.out.println(res);
}
catch (Exception ex){
}
finally {
Context.exit();
}
}
}
在控制台输出24,成功!
再写一个自定义函数的调用:
先定义一个自定义javascript函数isPrime,文件名isPrime.js:
function isPrime (num)
{
if (num <= 1) {
print("Please enter a positive integer >= 2.")
return false
}
var prime = true
var sqrRoot = Math.round(Math.sqrt(num))
for (var n = 2; prime & n <= sqrRoot; ++n) {
prime = (num % n != 0)
}
return prime
}
Java调用:
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可以实现动态的功能解析,给自定的功能扩展保留一定的空间。