纯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
... {
publicstaticvoidmain(String[]args)
...{
Contextcx
=Context.enter();
try
...{
Scriptablescope
=cx.initStandardObjects();
Stringstr
="9*(1+2)";
Objectresult
=cx.evaluateString(scope,str,null,1,null);
doubleres=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(
"Pleaseenterapositiveinteger>=2.")
returnfalse
}


varprime=true
varsqrRoot=Math.round(Math.sqrt(num))

for(varn=2;prime&n<=sqrRoot;++n)...{
prime
=(num%n!=0)
}


returnprime
}


如何运行呢:
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:
"MikeSquillace",
age:
37,
position:
"softwareengineer",
getFirstName:
function()...{returnthis.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 // extendsScriptableObject
... {
privateStringname;

privateFunctionhandle;

publicvoidsetHandler(Functionfunc)
...{
this.handle=func;
}


publicFunctiongetHandler()
...{
returnthis.handle;
}



publicJSFunction(Strings)
...{
this.name=s;
}


publicstaticvoidprint(Strings)
...{
System.out.println(s);
}


publicStringgetName()...{
returnname;
}

publicvoidsetName(Stringname)...{
this.name=name;
}


}

JSExploration.java:

packageco.test;

importjava.io.FileReader;
importjava.io.LineNumberReader;

importorg.mozilla.javascript.Context;
importorg.mozilla.javascript.Function;
importorg.mozilla.javascript.Scriptable;

publicclassJSExploration
... {
privateContextcx;

privateScriptablescope;

publicJSExploration()
...{
this.cx=Context.enter();
this.scope=cx.initStandardObjects();
}


publicObjectrunJavaScript(Stringfilename)
...{
StringjsContent
=this.getJsContent(filename);
Objectresult
=cx.evaluateString(scope,jsContent,filename,1,null);
returnresult;
}


privateStringgetJsContent(Stringfilename)
...{
LineNumberReaderreader;
try
...{
reader
=newLineNumberReader(newFileReader(filename));
Strings
=null;
StringBuffersb
=newStringBuffer();
while((s=reader.readLine())!=null)
...{
sb.append(s).append(
" ");
}

returnsb.toString();
}

catch(Exceptione)
...{
//TODOAuto-generatedcatchblock
e.printStackTrace();
returnnull;
}

}



publicScriptablegetScope()
...{
returnscope;
}


publicstatic
voidmain(String[]args)
...{
Stringfilename
=System.getProperty("user.dir")+"/jsmap.js";
JSExplorationjsExploration
=newJSExploration();
Objectresult
=jsExploration.runJavaScript(filename);
Scriptablescope
=jsExploration.getScope();
Scriptableobj
=(Scriptable)scope.get("obj",scope);
System.out.println(
"obj.a=="+obj.get("a",obj));
Scriptableb
=(Scriptable)obj.get("b",obj);
System.out.println(
"b[0]=="+b.get(0,b));
Booleanflag
=(Boolean)scope.get("flag",scope);
System.out.println(flag);

Scriptablemyobj
=(Scriptable)scope.get("obj",scope);
Booleanmyflag
=(Boolean)scope.get("flag",scope);
System.out.println(myflag);

ScriptablejsFunction
=(Scriptable)scope.get("jsFunction",scope);
Functionfc
=(Function)jsFunction.get("handler",jsFunction);
ObjectisPrime
=fc.call(Context.getCurrentContext(),jsFunction,fc,newObject[]...{"thisismytest"});
}

}


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(
"injavascript");
JSFunction.print(
"inJSFunction");
jsFunction
=newJSFunction("lichunlei");
varname=jsFunction.getName();
System.out.println(
"getnamefromjavasource:"+name);
jsFunction.setHandler(log);
}


java.lang.System.out.println(
" notuseswingNames " );
function isPrime(num)
... {
java.lang.System.out.println(
"inisPrime(num)");
if(num<=1)...{
java.lang.System.out.println(
"Pleaseenterapositiveinteger>=2.")
returnfalse
}


varprime=true
varsqrRoot=Math.round(Math.sqrt(num))

for(varn=2;prime&n<=sqrRoot;++n)...{
prime
=(num%n!=0)
}


returnprime
}


function log(msg)
... {
java.lang.System.out.println(
"infunctionlog:"+msg);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值