java调用javascript :js引擎rhino

老子叫甜甜 提交于 2019-12-09 17:15:24

前段时间,在浏览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已经把它收归帐下,成了正规军。


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解释器:
java org.mozilla.javascript.tools.shell.Main
然后您应该会看到解释器的版本号,后面跟着提示符 js> 
用法如下:
比如:有一个js文件:
D:\eclipse-workshop\rhinoExample\src\isPrime.js
内容如下:


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    
}  

如何运行呢:
1:在命令行下键入:
java org.mozilla.javascript.tools.shell.Main
2:在js〉下键入:
load("D:/eclipse-workshop/rhinoExample/src/isPrime.js");
注意:是“/”而不是“\”
3:键入:
isPrime(77);
可看见返回结果为false。
键入:
isPrime(71);返回true

再给个例子,脚本如下:

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]

只须运行java org.mozilla.javascript.tools.debugger.Main,就可以看到调试器的界面了。


为了加快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 FirstCompile

二:在实际应用中不可避免的需要遇到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);    
}   


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!