如何编写一个 Java 方法,从服务器端 JavaScript 调用,将 JS 回调函数作为参数?
How do I write a Java method, to be called from server side JavaScript, that takes a JS callback function as an argument?
我正在尝试编写一个 Java API 将在 JDK 7 JS 下从服务器端调用 JavaScript 运行ning引擎。这个想法是让消费者能够编写如下 JS 代码,注册一个回调,稍后由另一个调用 Java 方法执行:
myJavaObj.registerCallback(function (param) {
// do stuff here
});
myJavaObj.methodThatTriggersCallback();
这是我正在使用的一些测试代码:
import javax.script.Invocable;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class JSTestClient {
private String successCallback;
public void handleSuccess(String successCallback) {
this.successCallback = successCallback;
}
public void doStuff() throws ScriptException, NoSuchMethodException {
ScriptEngineManager manager = new ScriptEngineManager();
Invocable engine = (Invocable) manager.getEngineByName("JavaScript");
engine.invokeFunction(successCallback, "TEST SUCCESS");
}
}
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Main {
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
String js =
"var client = new Packages.JSTestClient();\n" +
"client.handleSuccess(function (response) {\n" +
" java.lang.System.out.println(response);\n" +
"});\n" +
"client.doStuff();";
try {
engine.eval(js); // Expecting this to output "TEST SUCCESS"
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
但是当我 运行 这个时,我得到一个 java.lang.NoSuchMethodException 因为它正在解释字符串:
function (response) {
java.lang.System.out.println(response);
}
作为一个函数名。有没有办法创建这样的回调,还是我需要使用其他约定?
您的 handleSuccess
方法采用 String
作为参数,但您使用 JavaScript function
对象调用它。您需要更改它以接受 Function
.
由于您使用的是 Java 7,因此您使用的是修改后的 Mozilla Rhino engine, where the implementation classes were moved from package org.mozilla.javascript
到 sun.org.mozilla.javascript.internal
。
要获取代码 运行,请将 JSTestClient
替换为:
import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Function;
public class JSTestClient {
private Function successCallback;
public void handleSuccess(Function successCallback) {
this.successCallback = successCallback;
}
public void doStuff() {
this.successCallback.call(Context.getCurrentContext(), null, null,
new Object[] { "TEST SUCCESS" });
}
}
注意Java8改成Nashorn引擎,与Nashorn交互的代码完全不同
我正在尝试编写一个 Java API 将在 JDK 7 JS 下从服务器端调用 JavaScript 运行ning引擎。这个想法是让消费者能够编写如下 JS 代码,注册一个回调,稍后由另一个调用 Java 方法执行:
myJavaObj.registerCallback(function (param) {
// do stuff here
});
myJavaObj.methodThatTriggersCallback();
这是我正在使用的一些测试代码:
import javax.script.Invocable;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class JSTestClient {
private String successCallback;
public void handleSuccess(String successCallback) {
this.successCallback = successCallback;
}
public void doStuff() throws ScriptException, NoSuchMethodException {
ScriptEngineManager manager = new ScriptEngineManager();
Invocable engine = (Invocable) manager.getEngineByName("JavaScript");
engine.invokeFunction(successCallback, "TEST SUCCESS");
}
}
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Main {
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
String js =
"var client = new Packages.JSTestClient();\n" +
"client.handleSuccess(function (response) {\n" +
" java.lang.System.out.println(response);\n" +
"});\n" +
"client.doStuff();";
try {
engine.eval(js); // Expecting this to output "TEST SUCCESS"
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
但是当我 运行 这个时,我得到一个 java.lang.NoSuchMethodException 因为它正在解释字符串:
function (response) { java.lang.System.out.println(response); }作为一个函数名。有没有办法创建这样的回调,还是我需要使用其他约定?
您的 handleSuccess
方法采用 String
作为参数,但您使用 JavaScript function
对象调用它。您需要更改它以接受 Function
.
由于您使用的是 Java 7,因此您使用的是修改后的 Mozilla Rhino engine, where the implementation classes were moved from package org.mozilla.javascript
到 sun.org.mozilla.javascript.internal
。
要获取代码 运行,请将 JSTestClient
替换为:
import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Function;
public class JSTestClient {
private Function successCallback;
public void handleSuccess(Function successCallback) {
this.successCallback = successCallback;
}
public void doStuff() {
this.successCallback.call(Context.getCurrentContext(), null, null,
new Object[] { "TEST SUCCESS" });
}
}
注意Java8改成Nashorn引擎,与Nashorn交互的代码完全不同