问题
I am working on an API in Java that allows users to write scripts and access a specific set of methods that are passed in (in the form of an API object) by the Nashorn script engine.
I want to, in the JavaScript, call a function getDate(), which will return some arbitrary date (as a native JavaScript date) that's provided from the Java side.
I have tried simply putting an org.java.util.Date on the API object, but that won't behave like a JS date. The goal is to make this as simple as possible for end-users who are experienced with JS.
Java Example:
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());
}
JavaScript example
function entryPoint(myApi){
var date = myApi.getDate();
myApi.log(date.getMinutes());
}
回答1:
The Nashorn engine has objects it uses internally which represent the Javascript objects. As you have guessed the java.util.Date != new Date()
(in javascript). The engine uses a class called jdk.nashorn.internal.objects.NativeDate
to represent its JS date.
If I were building this out I would not have the NativeDate
constructed in the Java but instead have a wrapper in Javascript for the MyApi
object which would contain a few other native JS methods, such as getDate()
.
var MYAPI_JAVASCRIPT = {
log: function() {
print(arguments);
},
getDate: function() {
return new Date();
}
}
You could then pass that object as the method parameter.
However if your really set on using the NativeDate
in your Java code then you can construct one like so:
public NativeDate getDate() {
return (NativeDate) NativeDate.construct(true, null);
}
回答2:
jdk.nashorn.internal.* packages are nashorn internal implementation classes. There is no guarantee that these won't be changed or be removed between JDK versions. Besides with a security manager around, accessing these packages from java code directly would result in SecurityException being thrown! With jdk9 modular jdk, these packages are not exported packages from nashorn module and so javac won't even compile your code in jdk9!
I'd recommend using JS wrapper (solution 1) in the answer by user "ug_". If you do have to call from Java, you can use API exported from jdk.nashorn.api.scripting package.
If "engine" is your javax.script.ScriptEngine of nashorn, then you can do something like the following:
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();
}
With that, your JS script can call "getDate()" on your API object and get a JS Date object. Note that you can also pass constructor arguments to newObject method call (it is a Java variadic method).
来源:https://stackoverflow.com/questions/33110942/supply-javascript-date-to-nashorn-script