java調用javascript :js引擎rhino

前段時間,在瀏覽javaeye論壇,看見有人徵集如何在java中運行數學表達式。
結果方案五花八門:
1.jakarta commons JEXL.
2.Beanshell
3.Java Math Expression Parser jep
4.parse combinator jparsec
5.jdk 6.0的 script
6.利用SQL
7.本身寫語法分析
若是本身寫語法分析,沒有個2000行估計搞不定。有人用sql來運行數學表達式,比較另類。
不過因爲前段時間較深刻的學習了一些java的javascript引擎,我給出的方案就是用javascript來計算了。
java中比較著名的js引擎當屬mozilla開源的rhino,不過jdk6已經把它收歸賬下,成了正規軍。javascript


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的心得(給本身的程序添加腳本功能,實際上是很酷的):java

一:環境配置及運行js腳本:
http://www.mozilla.org/rhino/ 下載rhino:
把js.jar加入系統CLASSPATH中
能夠以交互模式調用js解釋器:
java org.mozilla.javascript.tools.shell.Main
而後您應該會看到解釋器的版本號,後面跟着提示符 js>
用法以下:
好比:有一個js文件:
D:\eclipse-workshop\rhinoExample\src\isPrime.js
內容以下:sql


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   
}   shell

如何運行呢:
1:在命令行下鍵入:
java org.mozilla.javascript.tools.shell.Main
2:在js〉下鍵入:
load("D:/eclipse-workshop/rhinoExample/src/isPrime.js");
注意:是「/」而不是「\」
3:鍵入:
isPrime(77);
可看見返回結果爲false。
鍵入:
isPrime(71);返回trueapp

再給個例子,腳本以下: eclipse

person = {   
  name:"Mike Squillace",   
  age:37,   
  position:"software engineer",   
  getFirstName:function () {return this.name.split(" ")[0]}   
}   
person.getFirstName()  
js產生swing的例子:
load("D:/eclipse-workshop/rhinoExample/src/SwingApplication.js");
怎麼樣?看見效果沒?是否是很強悍?其中SwingApplication.js是rhnio自帶的例子。學習


Rhino還有一個js腳本的調試器:
Rhino JavaScript Debugger:
java org.mozilla.javascript.tools.debugger.Main [options] [filename.js] [script-arguments]ui

只須運行java org.mozilla.javascript.tools.debugger.Main,就能夠看到調試器的界面了。this


爲了加快js文件運行的速度,能夠把它編譯爲class文件:
compile:
java org.mozilla.javascript.tools.jsc.Main D:/eclipse-workshop/rhinoExample/src/FirstCompile.js
編譯產生FirstCompile.class文件
在D:/eclipse-workshop/rhinoExample/src/下運行該class文件:
java FirstCompilelua

二:在實際應用中不可避免的須要遇到java代碼如何和javascript腳本相互訪問的問題:
這是一個最簡單的例子:(liveConnect.js是rhnio自帶的例子):
load("D:/eclipse-workshop/rhinoExample/src/liveConnect.js");

在給個複雜點的例子, 沒有什麼邏輯,純技術展現,呵呵:
JSFunction.java:

java 代碼
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:

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

js 代碼var swingNames = JavaImporter();       swingNames.importPackage(Packages.java.lang);    swingNames.importPackage(Packages.co.test);       obj = {a:1, b:['x','y']}    next = isPrime    flag = isPrime(5)    with (swingNames) {     System.out.println("in javascript");     JSFunction.print("in JSFunction");      jsFunction = new JSFunction("lichunlei");     var name = jsFunction.getName();     System.out.println("get name from java source: " + name);     jsFunction.setHandler(log);     }        java.lang.System.out.println("not use swingNames");    function isPrime (num)    {     java.lang.System.out.println("in isPrime(num)");        if (num <= 1) {            java.lang.System.out.println("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    }       function log(msg)    {     java.lang.System.out.println("in function log: " + msg);    }   

相關文章
相關標籤/搜索