前段时间,在浏览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
内容如下:
- 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,?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
- 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); ??
- } ??
- ??
- ? ??
比如:如果你的应用有脚本功能,你可以在你的应用中加入客户自定义流程,而无须改写现有代码。
这只是随便想到的应用。
比如:如果你的应用有脚本功能,你可以在你的应用中加入客户自定义流程,而无须改写现有代码。
这只是随便想到的应用。
是啊,比如,可以用它来做一个web页面分析和执行的工具。。。