纯java 的javascript引擎: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已经把它收归帐下,成了正规军。

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, null1null);
            
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
内容如下:

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:

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, 1null);
        
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(
" ");
            }

            
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

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);
}

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值