惊现有人把 OpenJDK 上的 Nashorn dump 下来,使得 Java 7 都能够使用。源代码在 https://bitbucket.org/ramonza/nashorn-backport/。
原本 Nashorn 是 Java 8 才有的。如今有人作了向后兼容。好事!
编译源代码
仅仅有源代码没有 jar。要自己编译。没关系非常easy:ant -f make/build.xml。详细步骤先把源代码拖进 Eclipse 项目。然后打开 Ant 视图:
点击 + 图标加入 make/build.xml
然后“运行”就可以编译 jar 包,完毕后保存在 dist 文件夹下。
假设大家不能成功编译,给大家一个直接下载地址:http://download.csdn.net/detail/zhangxin09/9398572
測试
測试是否可用:
import javax.script.*; public class NashornTest { public static void main(String args[]) { ScriptEngineManager manager = new ScriptEngineManager(); for (ScriptEngineFactory f : manager.getEngineFactories()) { printBasicInfo(f); System.out.println(); } ScriptEngine nashorn = manager.getEngineByName("nashorn"); if(nashorn != null) { System.out.println("Nashorn is present."); } else { System.out.println("Nashorn is not present."); } } public static void printBasicInfo(ScriptEngineFactory factory) { System.out.println("engine name=" + factory.getEngineName()); System.out.println("engine version=" + factory.getEngineVersion()); System.out.println("language name=" + factory.getLanguageName()); System.out.println("extensions=" + factory.getExtensions()); System.out.println("language version=" + factory.getLanguageVersion()); System.out.println("names=" + factory.getNames()); System.out.println("mime types=" + factory.getMimeTypes()); } }
检測是否可用的另外一个方法:try{final Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror");} ..
比較 Rhino
创建一个已经封装过的 JS VM
Nashorn n = new Nashorn(); Object s = n.eval("g={a:1};"); Map ss = (Map)s; ss.get("a"); System.out.println(ss.get("a").getClass().getName()); System.out.println(s.getClass().getName());
我封装的 api 自己感觉比較顺手,比如:
Map s = n.eval("g={a:1};", Map.class); // js 对象转换为 java map
Nashorn n = new Nashorn(); Object obj = n.eval("g=[1, 2, 3];"); System.out.println(obj.getClass().getName()); ScriptObjectMirror so = (ScriptObjectMirror)obj; System.out.println(so.get(0).getClass().getName());測试观察发现:
js 的 {} 哈希类型会自己主动转为 jdk.nashorn.api.scripting.ScriptObjectMirror。而不是 Rhino 的 NativeObject。但两者都能够转为 Map
js 的 [] 数组类型会自己主动转为 jdk.nashorn.api.scripting.ScriptObjectMirror,而不是 Rhino 的 NativeArray,但能够用 isArray() : boolean 推断是否数组
js 的 Number 类型会自己主动转为 java.lang.Integer。而不是 Rhino 的 Double,这样在处理数字类型时比較方便。
只是这是早期版本号。缺了正式版才有的功能。比如:
if(so.isArray()) { int[] iarr = (int[])ScriptUtils.convert(so, int[].class); // 转换为 java 数组保存。由于还没有 convert() }
除了将就还能怎么办涅?想想办法呗(其实也就是谷歌一下)。
public static void main(String[] args) throws ScriptException, IOException { Nashorn n = new Nashorn(); n.load("C:/project/spring-test/src/com/ajaxjs/framework/config.js"); Object obj = n.eval("g=[1, 2, 3];"); System.out.println(obj.getClass().getName()); ScriptObjectMirror so = (ScriptObjectMirror) obj; System.out.println(so.get(0).getClass().getName()); if (so.isArray()) { System.out.println(so); // int[] iarr = (int[]) ScriptUtils.convert(so, int[].class); } } /** * js arr2 java arr * @param scriptObjectMirror * @return */ public static Object[] toArray(ScriptObjectMirror scriptObjectMirror) { if (!scriptObjectMirror.isArray()) { throw new IllegalArgumentException("ScriptObjectMirror is no array"); } if (scriptObjectMirror.isEmpty()) { return new Object[0]; } Object[] array = new Object[scriptObjectMirror.size()]; int i = 0; for (Map.Entry<String, Object> entry : scriptObjectMirror.entrySet()) { Object result = entry.getValue(); if (result instanceof ScriptObjectMirror && scriptObjectMirror.isArray()) { array[i] = toArray((ScriptObjectMirror) result); } else { array[i] = result; } i++; } return array; }
其实,假设你不是强迫症。数组 get(0)/get(1)/... 一样可用,无须转换一次。
单測代码(非常重要!
)http://code.taobao.org/p/bigfoot_v2/src/java_v3/test/javascript/TestJS.java