Java 7 可运行的 Nashorn,代替 Rhino

简介: 惊现有人把 OpenJDK 上的 Nashorn dump 下来,使得 Java 7 都可以使用!源码在 https://bitbucket.org/ramonza/nashorn-backport/。

惊现有人把 OpenJDK 上的 Nashorn dump 下来,使得 Java 7 都可以使用!源码在 https://bitbucket.org/ramonza/nashorn-backport/

原本 Nashorn 是 Java 8 才有的。现在有人作了向后兼容,好事!

编译源码

只有源码没有 jar,要自己编译。没关系很简单: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

Nashorn 文档:http://cr.openjdk.java.net/~sundar/jdk.nashorn.api/8u20/javadoc/jdk/nashorn/api/scripting/AbstractJSObject.html

目录
相关文章
|
3月前
|
Java
使用IDEA创建项目运行我的第一个JAVA文件输出Helloword
本文介绍了如何使用IDEA(IntelliJ IDEA)创建一个新的Java项目,并运行一个简单的Java程序输出"Hello Word"。文章详细展示了创建项目的步骤,包括选择JDK版本、设置项目名称和路径、创建包和类,以及编写和运行代码。最后,还展示了如何通过IDEA的运行功能来执行程序并查看输出结果。
164 4
使用IDEA创建项目运行我的第一个JAVA文件输出Helloword
|
2月前
|
Java
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
文章详细解释了Java关键字`super`的用途,包括访问父类的成员变量、调用父类的构造方法和方法,并提供了相应的代码实例。
127 5
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
|
2月前
|
Java Apache Maven
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
文章提供了使用Apache POI库在Java中创建和读取Excel文件的详细代码示例,包括写入数据到Excel和从Excel读取数据的方法。
60 6
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
|
3月前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
71 2
|
4月前
|
Java 编译器 C++
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
这篇文章解释了Java能够实现“一次编写,到处运行”的原因,主要归功于Java虚拟机(JVM),它能够在不同平台上将Java源代码编译成的字节码转换成对应平台的机器码,实现跨平台运行。
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
|
2月前
|
分布式计算 大数据 Java
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
28 1
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
|
2月前
|
IDE Java 编译器
Java:如何确定编译和运行时类路径是否一致
类路径(Classpath)是JVM用于查找类文件的路径列表,对编译和运行Java程序至关重要。编译时通过`javac -classpath`指定,运行时通过`java -classpath`指定。IDE如Eclipse和IntelliJ IDEA也提供界面管理类路径。确保编译和运行时类路径一致,特别是外部库和项目内部类的路径设置。
|
2月前
|
Java
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
本文介绍了Java中this和super关键字的用法,包括在构造方法中使用this来区分参数和成员变量、使用super调用父类构造方法和方法,以及它们在同一个方法中同时使用的场景。
131 0
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
|
2月前
|
Java
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
这篇文章详细解释了Java中static和final关键字的用法,包括它们修饰类、方法、变量和代码块时的行为,并通过代码示例展示了它们的具体应用。
213 0
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
|
2月前
|
Java Maven Spring
用Spring导致的无法运行Java文件的问题的解决方案
本文提供了解决在IntelliJ IDEA社区版中使用Spring Initializr插件创建Spring项目后,Java文件无法运行的问题的方法,主要是通过加载Maven项目来解决。
80 0