Rhino——一个可以在Java中操作和执行JS的框架

前段时间,在浏览javaeye论坛,看见有人征集如何在java中运行数学表达式。

结果方案五花八门:

1.jakartacommonsJEXL.

2.Beanshell

3.JavaMathExpressionParserjep

4.parsecombinatorjparsec

5.jdk6.0的script

6.利用SQL

7.自己写语法分析

如果自己写语法分析,没有个2000行估计搞不定。有人用sql来运行数学表达式,比较另类。

不过由于前段时间较深入的学习了一些java的javascript引擎,我给出的方案就是用javascript来计算了。

java中比较著名的js引擎当属mozilla开源的rhino,不过jdk6已经把它收归帐下,成了正规军。

public class MathEval   
{   

    public static void main(String[] args)    
    {   
        Context cx = Context.enter();   

        try   
        {   
            Scriptable scope = cx.initStandardObjects();   

            String str = "9*(1+2)";    

            Object result = cx.evaluateString(scope, str, null, 1, null);    

            double res = Context.toNumber(result);    
            System.out.println(res);   
        }   

        finally   
        {   
            Context.exit();   
        }   
    }   
}  

下面总结一下前段时间学习rhino的心得(给自己的程序添加脚本功能,其实是很酷的):

一:环境配置及运行js脚本:

在http://www.mozilla.org/rhino/下载rhino:

把js.jar加入系统CLASSPATH中

可以以交互模式调用js解释器:

javaorg.mozilla.javascript.tools.shell.Main

然后您应该会看到解释器的版本号,后面跟着提示符js>

用法如下:

比如:有一个js文件:

D:\eclipse-workshop\rhinoExample\src\isPrime.js

内容如下:

package co.test;   
  
import org.mozilla.javascript.Function;   
  
public class JSFunction  //extends ScriptableObject   
{   

 private String name;     
    

 private Function handle;    
    

 public void setHandler(Function func)    
 {   

  this.handle = func;    
 }   
    

 public Function getHandler()    
 {   

  return this.handle;    
 }   
  
    

 public JSFunction(String s)    
 {   

  this.name = s;    
 }    
    

 public static void print(String s)    
 {   
  System.out.println(s);   
 }   
  

 public String getName() {    

  return name;    
 }   

 public void setName(String name) {    

  this.name = name;    
 }   
  
}   
  

JSExploration.java:

package co.test;   
  
import java.io.FileReader;   
import java.io.LineNumberReader;   
  
import org.mozilla.javascript.Context;   
import org.mozilla.javascript.Function;   
import org.mozilla.javascript.Scriptable;   
  
public class JSExploration   
{   

    private Context cx;    
  

    private Scriptable scope;    
  

    public JSExploration()    
    {   

        this.cx = Context.enter();    

        this.scope = cx.initStandardObjects();    
    }   
  

    public Object runJavaScript(String filename)    
    {   

        String jsContent = this.getJsContent(filename);    

        Object result = cx.evaluateString(scope, jsContent, filename, 1, null);    

        return result;    
    }   
  

    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)    
        {   

            // TODO Auto-generated catch block    
            e.printStackTrace();   

            return null;    
        }   
    }   
  
  

    public Scriptable getScope()    
    {   

        return scope;    
    }   
  

    public static void main(String[] args)    
    {   

        String filename = System.getProperty("user.dir") + "/jsmap.js";    

        JSExploration jsExploration = new JSExploration();    
        Object result = jsExploration.runJavaScript(filename);   
        Scriptable scope = jsExploration.getScope();   

        Scriptable obj = (Scriptable) scope.get("obj", scope);    

        System.out.println("obj.a == " + obj.get("a", obj));    

        Scriptable b = (Scriptable) obj.get("b", obj);    

        System.out.println("b[0] == " + b.get(0, b));    

        Boolean flag = (Boolean) scope.get("flag", scope);    
        System.out.println(flag);   
  

        Scriptable myobj = (Scriptable) scope.get("obj", scope);    

        Boolean myflag = (Boolean) scope.get("flag", scope);    
        System.out.println(myflag);   
  

        Scriptable jsFunction = (Scriptable) scope.get("jsFunction", scope);    

        Function fc = (Function) jsFunction.get("handler", jsFunction);    

        Object isPrime = fc.call(Context.getCurrentContext(), jsFunction, fc, new Object[] { "this is my test" });    
    }   
}   
  

js脚本:jsmap.js

  1. var swingNames = JavaImporter();   
  2.   
  3. swingNames.importPackage(Packages.java.lang);   
  4. swingNames.importPackage(Packages.co.test);   
  5.   
  6. obj = {a:1, b:['x','y']}   
  7. next = isPrime   
  8. flag = isPrime(5)   
  9. with (swingNames) {   
  10.  System.out.println("in javascript");   
  11.  JSFunction.print("in JSFunction");   
  12.   jsFunction = new JSFunction("lichunlei");   
  13.  var name = jsFunction.getName();   
  14.  System.out.println("get name from java source: " + name);   
  15.  jsFunction.setHandler(log);    
  16. }    
  17.   
  18. java.lang.System.out.println("not use swingNames");   
  19. function isPrime (num)   
  20. {   
  21.  java.lang.System.out.println("in isPrime(num)");   
  22.     if (num <= 1) {   
  23.         java.lang.System.out.println("Please enter a positive integer >= 2.")   
  24.         return false  
  25.     }   
  26.        
  27.     var prime = true  
  28.     var sqrRoot = Math.round(Math.sqrt(num))   
  29.        
  30.     for (var n = 2; prime & n <= sqrRoot; ++n) {   
  31.         prime = (num % n != 0)   
  32.     }   
  33.        
  34.     return prime   
  35. }   
  36.   
  37. function log(msg)   
  38. {   
  39.  java.lang.System.out.println("in function log: " + msg);   
  40. }   
  41.   
  42.    

相关推荐