当前位置: 代码迷 >> JavaScript >> 纯java 的javascript发动机:rhino
  详细解决方案

纯java 的javascript发动机:rhino

热度:475   发布时间:2012-11-04 10:42:41.0
纯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已经把它收归帐下,成了正规军。

  1. public?class?MathEval ??
  2. { ??
  3. ????public?static?void?main(String[]?args) ??
  4. ????{ ??
  5. ????????Context?cx?=?Context.enter(); ??
  6. ????????try??
  7. ????????{ ??
  8. ????????????Scriptable?scope?=?cx.initStandardObjects(); ??
  9. ????????????String?str?=?"9*(1+2)"; ??
  10. ????????????Object?result?=?cx.evaluateString(scope,?str,?null,?1,?null); ??
  11. ????????????double?res?=?Context.toNumber(result); ??
  12. ????????????System.out.println(res); ??
  13. ????????} ??
  14. ????????finally??
  15. ????????{ ??
  16. ????????????Context.exit(); ??
  17. ????????} ??
  18. ????} ??
  19. }??

下面总结一下前段时间学习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 代码
  1. function?isPrime?(num) ??
  2. { ??
  3. ????if?(num?<=?1)?{ ??
  4. ????????print("Please?enter?a?positive?integer?>=?2.") ??
  5. ????????return?false??
  6. ????} ??
  7. ???? ??
  8. ????var?prime?=?true??
  9. ????var?sqrRoot?=?Math.round(Math.sqrt(num)) ??
  10. ???? ??
  11. ????for?(var?n?=?2;?prime?&?n?<=?sqrRoot;?++n)?{ ??
  12. ????????prime?=?(num?%?n?!=?0) ??
  13. ????} ??
  14. ???? ??
  15. ????return?prime ??
  16. }??


如何运行呢:
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

再给个例子,脚本如下:

  1. person?=?{ ??
  2. ??name:"Mike?Squillace", ??
  3. ??age:37, ??
  4. ??position:"software?engineer", ??
  5. ??getFirstName:function?()?{return?this.name.split("?")[0]} ??
  6. } ??
  7. 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 代码
  1. package?co.test; ??
  2. ??
  3. import?org.mozilla.javascript.Function; ??
  4. ??
  5. public?class?JSFunction??//extends?ScriptableObject ??
  6. { ??
  7. ?private?String?name;? ??
  8. ? ??
  9. ?private?Function?handle; ??
  10. ? ??
  11. ?public?void?setHandler(Function?func) ??
  12. ?{ ??
  13. ??this.handle?=?func; ??
  14. ?} ??
  15. ? ??
  16. ?public?Function?getHandler() ??
  17. ?{ ??
  18. ??return?this.handle; ??
  19. ?} ??
  20. ??
  21. ? ??
  22. ?public?JSFunction(String?s) ??
  23. ?{ ??
  24. ??this.name?=?s; ??
  25. ?}? ??
  26. ? ??
  27. ?public?static?void?print(String?s) ??
  28. ?{ ??
  29. ??System.out.println(s); ??
  30. ?} ??
  31. ??
  32. ?public?String?getName()?{ ??
  33. ??return?name; ??
  34. ?} ??
  35. ?public?void?setName(String?name)?{ ??
  36. ??this.name?=?name; ??
  37. ?} ??
  38. ??
  39. } ??
  40. ??

JSExploration.java:

java 代码
  1. package?co.test; ??
  2. ??
  3. import?java.io.FileReader; ??
  4. import?java.io.LineNumberReader; ??
  5. ??
  6. import?org.mozilla.javascript.Context; ??
  7. import?org.mozilla.javascript.Function; ??
  8. import?org.mozilla.javascript.Scriptable; ??
  9. ??
  10. public?class?JSExploration ??
  11. { ??
  12. ????private?Context?cx; ??
  13. ??
  14. ????private?Scriptable?scope; ??
  15. ??
  16. ????public?JSExploration() ??
  17. ????{ ??
  18. ????????this.cx?=?Context.enter(); ??
  19. ????????this.scope?=?cx.initStandardObjects(); ??
  20. ????} ??
  21. ??
  22. ????public?Object?runJavaScript(String?filename) ??
  23. ????{ ??
  24. ????????String?jsContent?=?this.getJsContent(filename); ??
  25. ????????Object?result?=?cx.evaluateString(scope,?jsContent,?filename,?1,?null); ??
  26. ????????return?result; ??
  27. ????} ??
  28. ??
  29. ????private?String?getJsContent(String?filename) ??
  30. ????{ ??
  31. ????????LineNumberReader?reader; ??
  32. ????????try??
  33. ????????{ ??
  34. ????????????reader?=?new?LineNumberReader(new?FileReader(filename)); ??
  35. ????????????String?s?=?null; ??
  36. ????????????StringBuffer?sb?=?new?StringBuffer(); ??
  37. ????????????while?((s?=?reader.readLine())?!=?null) ??
  38. ????????????{ ??
  39. ????????????????sb.append(s).append("\n"); ??
  40. ????????????} ??
  41. ????????????return?sb.toString(); ??
  42. ????????} ??
  43. ????????catch?(Exception?e) ??
  44. ????????{ ??
  45. ????????????//?TODO?Auto-generated?catch?block ??
  46. ????????????e.printStackTrace(); ??
  47. ????????????return?null; ??
  48. ????????} ??
  49. ????} ??
  50. ??
  51. ??
  52. ????public?Scriptable?getScope() ??
  53. ????{ ??
  54. ????????return?scope; ??
  55. ????} ??
  56. ??
  57. ????public?static?void?main(String[]?args) ??
  58. ????{ ??
  59. ????????String?filename?=?System.getProperty("user.dir")?+?"/jsmap.js"; ??
  60. ????????JSExploration?jsExploration?=?new?JSExploration(); ??
  61. ????????Object?result?=?jsExploration.runJavaScript(filename); ??
  62. ????????Scriptable?scope?=?jsExploration.getScope(); ??
  63. ????????Scriptable?obj?=?(Scriptable)?scope.get("obj",?scope); ??
  64. ????????System.out.println("obj.a?==?"?+?obj.get("a",?obj)); ??
  65. ????????Scriptable?b?=?(Scriptable)?obj.get("b",?obj); ??
  66. ????????System.out.println("b[0]?==?"?+?b.get(0,?b)); ??
  67. ????????Boolean?flag?=?(Boolean)?scope.get("flag",?scope); ??
  68. ????????System.out.println(flag); ??
  69. ??
  70. ????????Scriptable?myobj?=?(Scriptable)?scope.get("obj",?scope); ??
  71. ????????Boolean?myflag?=?(Boolean)?scope.get("flag",?scope); ??
  72. ????????System.out.println(myflag); ??
  73. ??
  74. ????????Scriptable?jsFunction?=?(Scriptable)?scope.get("jsFunction",?scope); ??
  75. ????????Function?fc?=?(Function)?jsFunction.get("handler",?jsFunction); ??
  76. ????????Object?isPrime?=?fc.call(Context.getCurrentContext(),?jsFunction,?fc,?new?Object[]?{?"this?is?my?test"?}); ??
  77. ????} ??
  78. } ??
  79. ??

js脚本:jsmap.js

js 代码
  1. var?swingNames?=?JavaImporter(); ??
  2. ??
  3. swingNames.importPackage(Packages.java.lang); ??
  4. swingNames.importPackage(Packages.co.test); ??
  5. ??
  6. obj?=?{a:1,?b:['x','y']} ??
  7. next?=?isPrime ??
  8. flag?=?isPrime(5) ??
  9. with?(swingNames)?{ ??
  10. ?System.out.println("in?javascript"); ??
  11. ?JSFunction.print("in?JSFunction"); ??
  12. ??jsFunction?=?new?JSFunction("lichunlei"); ??
  13. ?var?name?=?jsFunction.getName(); ??
  14. ?System.out.println("get?name?from?java?source:?"?+?name); ??
  15. ?jsFunction.setHandler(log);? ??
  16. }? ??
  17. ??
  18. java.lang.System.out.println("not?use?swingNames"); ??
  19. function?isPrime?(num) ??
  20. { ??
  21. ?java.lang.System.out.println("in?isPrime(num)"); ??
  22. ????if?(num?<=?1)?{ ??
  23. ????????java.lang.System.out.println("Please?enter?a?positive?integer?>=?2.") ??
  24. ????????return?false??
  25. ????} ??
  26. ???? ??
  27. ????var?prime?=?true??
  28. ????var?sqrRoot?=?Math.round(Math.sqrt(num)) ??
  29. ???? ??
  30. ????for?(var?n?=?2;?prime?&?n?<=?sqrRoot;?++n)?{ ??
  31. ????????prime?=?(num?%?n?!=?0) ??
  32. ????} ??
  33. ???? ??
  34. ????return?prime ??
  35. } ??
  36. ??
  37. function?log(msg) ??
  38. { ??
  39. ?java.lang.System.out.println("in?function?log:?"?+?msg); ??
  40. } ??
  41. ??
  42. ? ??

js 代码

java 代码
1 楼 dwangel 2007-06-07  
ognl
2 楼 sp42 2007-06-07  
nice work!有用的资料
3 楼 gfh21cn 2007-06-07  
技术是好的,但是不实用,我想最实用的还是C++中嵌入 PYTHON
4 楼 lcllcl987 2007-06-07  
此言差矣!
比如:如果你的应用有脚本功能,你可以在你的应用中加入客户自定义流程,而无须改写现有代码。
这只是随便想到的应用。
5 楼 manyinjin 2008-03-25  
lcllcl987 写道
此言差矣!
比如:如果你的应用有脚本功能,你可以在你的应用中加入客户自定义流程,而无须改写现有代码。
这只是随便想到的应用。

是啊,比如,可以用它来做一个web页面分析和执行的工具。。。
6 楼 monya_h 2012-03-02  
太帅了。谢谢
  相关解决方案