向 Nashorn 脚本提供 JavaScript 日期
Supply JavaScript date to Nashorn script
我正在 Java 中开发一个 API,它允许用户编写脚本并访问传入的一组特定方法(以 API 对象的形式) 由 Nashorn 脚本引擎提供。
我想在 JavaScript 中调用函数 getDate(),它将 return 一些任意日期(作为本机 JavaScript 日期)提供自Java 侧。
我曾尝试简单地在 API 对象上放置一个 org.java.util.Date,但这不会表现得像 JS 日期。目标是让对 JS 有经验的最终用户尽可能简单。
Java 示例:
public class MyAPI {
public void log(String text){
System.out.println(text);
}
public Date getDate(){
// Return something that converts to a native-JS date
}
public static void main(){
// MyClassFilter implements Nashorn's ClassFilter
ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(new MyClassFilter());
((Invokable) engine).invokeFunction("entryPoint", new MyAPI());
}
Java脚本示例
function entryPoint(myApi){
var date = myApi.getDate();
myApi.log(date.getMinutes());
}
Nashorn 引擎有它在内部使用的对象,这些对象代表 Javascript 对象。正如您猜到的 java.util.Date != new Date()
(在 javascript 中)。该引擎使用一个名为 jdk.nashorn.internal.objects.NativeDate
的 class 来表示其 JS 日期。
如果我正在构建它,我不会在 Java 中构建 NativeDate
,而是在 Java 脚本中为 MyApi
对象创建一个包装器,它将包含一些其他原生 JS 方法,例如 getDate()
.
var MYAPI_JAVASCRIPT = {
log: function() {
print(arguments);
},
getDate: function() {
return new Date();
}
}
然后您可以将该对象作为方法参数传递。
但是,如果您真的打算在 Java 代码中使用 NativeDate
,那么您可以像这样构造一个:
public NativeDate getDate() {
return (NativeDate) NativeDate.construct(true, null);
}
jdk.nashorn.internal.* 软件包是 nashorn 内部实现 类。无法保证这些不会在 JDK 版本之间被更改或删除。除了周围有安全管理器外,直接从 java 代码访问这些包会导致抛出 SecurityException!使用 jdk9 模块化 jdk,这些包不是从 nashorn 模块导出的包,因此 javac 甚至不会在 jdk9![=11= 中编译您的代码]
我建议在用户 "ug_" 的回答中使用 JS 包装器(解决方案 1)。如果您确实必须从 Java 调用,您可以使用从 jdk.nashorn.api.scripting 包导出的 API。
如果 "engine" 是你的 javax.script.ScriptEngine 的 nashorn,那么你可以执行如下操作:
import jdk.nashorn.api.scripting.*;
..
public Object getDate() {
// get JS Date constructor object - you can get once and store
// as well/
JSObject dateConstructor = (JSObject) engine.eval("Date");
// now do "new" on it
return dateConstructor.newObject();
}
有了它,您的 JS 脚本可以在您的 API 对象上调用 "getDate()" 并获得一个 JS
日期对象。请注意,您还可以将构造函数参数传递给 newObject
方法调用(它是一个 Java 可变参数方法)。
我正在 Java 中开发一个 API,它允许用户编写脚本并访问传入的一组特定方法(以 API 对象的形式) 由 Nashorn 脚本引擎提供。
我想在 JavaScript 中调用函数 getDate(),它将 return 一些任意日期(作为本机 JavaScript 日期)提供自Java 侧。
我曾尝试简单地在 API 对象上放置一个 org.java.util.Date,但这不会表现得像 JS 日期。目标是让对 JS 有经验的最终用户尽可能简单。
Java 示例:
public class MyAPI {
public void log(String text){
System.out.println(text);
}
public Date getDate(){
// Return something that converts to a native-JS date
}
public static void main(){
// MyClassFilter implements Nashorn's ClassFilter
ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(new MyClassFilter());
((Invokable) engine).invokeFunction("entryPoint", new MyAPI());
}
Java脚本示例
function entryPoint(myApi){
var date = myApi.getDate();
myApi.log(date.getMinutes());
}
Nashorn 引擎有它在内部使用的对象,这些对象代表 Javascript 对象。正如您猜到的 java.util.Date != new Date()
(在 javascript 中)。该引擎使用一个名为 jdk.nashorn.internal.objects.NativeDate
的 class 来表示其 JS 日期。
如果我正在构建它,我不会在 Java 中构建 NativeDate
,而是在 Java 脚本中为 MyApi
对象创建一个包装器,它将包含一些其他原生 JS 方法,例如 getDate()
.
var MYAPI_JAVASCRIPT = {
log: function() {
print(arguments);
},
getDate: function() {
return new Date();
}
}
然后您可以将该对象作为方法参数传递。
但是,如果您真的打算在 Java 代码中使用 NativeDate
,那么您可以像这样构造一个:
public NativeDate getDate() {
return (NativeDate) NativeDate.construct(true, null);
}
jdk.nashorn.internal.* 软件包是 nashorn 内部实现 类。无法保证这些不会在 JDK 版本之间被更改或删除。除了周围有安全管理器外,直接从 java 代码访问这些包会导致抛出 SecurityException!使用 jdk9 模块化 jdk,这些包不是从 nashorn 模块导出的包,因此 javac 甚至不会在 jdk9![=11= 中编译您的代码]
我建议在用户 "ug_" 的回答中使用 JS 包装器(解决方案 1)。如果您确实必须从 Java 调用,您可以使用从 jdk.nashorn.api.scripting 包导出的 API。
如果 "engine" 是你的 javax.script.ScriptEngine 的 nashorn,那么你可以执行如下操作:
import jdk.nashorn.api.scripting.*;
..
public Object getDate() {
// get JS Date constructor object - you can get once and store
// as well/
JSObject dateConstructor = (JSObject) engine.eval("Date");
// now do "new" on it
return dateConstructor.newObject();
}
有了它,您的 JS 脚本可以在您的 API 对象上调用 "getDate()" 并获得一个 JS 日期对象。请注意,您还可以将构造函数参数传递给 newObject 方法调用(它是一个 Java 可变参数方法)。