如何将javaScript函数传递给Java方法作为回调函数(Rhino)

如何将javaScript函数传递给Java方法作为回调函数(Rhino),java,javascript,rhino,Java,Javascript,Rhino,基本上,我试图将javaScript函数传递给Java方法,作为对脚本的回调 我可以这样做——有点——但我收到的对象是sun.org.mozilla.javascript.internal.expressedfunction,我看不到调用它的方法 有什么想法吗 以下是我目前掌握的情况: var someNumber = 0; function start() { // log is just an log4j instance added to the Bindings log.i

基本上,我试图将javaScript函数传递给Java方法,作为对脚本的回调

我可以这样做——有点——但我收到的对象是sun.org.mozilla.javascript.internal.expressedfunction,我看不到调用它的方法

有什么想法吗

以下是我目前掌握的情况:

var someNumber = 0;

function start() {
   // log is just an log4j instance added to the Bindings
   log.info("started....");
   someNumber = 20;

    // Test is a unit test object with this method on it (taking Object as a param).
    test.callFromRhino(junk);
}

function junk() {
    log.info("called back " + someNumber);
}

sun.org.mozilla.javascript.internal.解释器函数
实现接口
sun.org.mozilla.javascript.Function
。该接口上有一个名为
call
的方法,该方法采用:

  • a
    Context
  • 用作作用域的
    可编写脚本的
  • 一个
    可编写脚本的
    ,用作函数中此
    的值
  • 作为函数参数的
    对象的数组

因此,我建议在java中,您将传递的对象转换为
sun.org.mozilla.javascript.Function
和call
call
。前两个参数可以是从java开始脚本时使用的任何参数。按照您在那里使用它的方式,最后两个参数可以是
null
newobject[0]

实现一个接口:

import javax.script.*;

public class CallBack {
  public void invoke(Runnable runnable) {
    runnable.run();
  }

  public static void main(String[] args) throws ScriptException {
    ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
    js.getContext().setAttribute("callBack", new CallBack(),
        ScriptContext.ENGINE_SCOPE);
    js.eval("var impl = { run: function () { print('Hello, World!'); } };\n"
        + "var runnable = new java.lang.Runnable(impl);\n"
        + "callBack.invoke(runnable);\n");
  }
}

解决方案实际上是在另一个脚本中调用它。这类作品:

import javax.script.*;

public class CallFunction {

    /**
     * @param args
     * @throws Exception oops!
     */
    public static void main(String[] args) throws Exception {
        ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
        js.getContext().setAttribute("out", System.out, ScriptContext.ENGINE_SCOPE);
        Object a = js.eval(
                "out.println('Defining function a...');" +
                "function a() {out.println('hello from JavaScript!'); }" +
                "function foobar() {out.println('in foobar() definition');}" +    
                "out.println('Done!.');"
        );

        System.out.println(js.get("a")); // InterpretedFunction
        SimpleBindings bindings = new SimpleBindings();
        bindings.put("foobar",js.get("a"));
        js.eval("foobar();", bindings); // hello from JavaScript
        js.eval("foobar();"); // in foobar() definition
    }
}

当您返回对函数的引用时,您需要请求引擎为您执行该函数。虽然不是很漂亮,但让js使用一组特定的绑定为您计算()实际上可以帮您完成这项工作。您需要注意,您正在操作的变量属于正确的范围;我想这里很容易出错。

这个例子介绍了用javascript实现java接口。这也可以用于从java调用javascript回调



package com.hal.research;

import javax.script.*;

public class CallFunction {
    /**
     * define contract for the callback 
     */
    static interface WhatEverYouWant {
        public String testMe(String a, String b);
    }
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        final ScriptEngineManager scriptManager = new ScriptEngineManager();
        final ScriptEngine js = scriptManager.getEngineByExtension("js");
        js.put("producer", new Object() {
            /**
             * @param call is a callback to be invoked
             */
            public void doSomethingWithIt(WhatEverYouWant call) {
                System.out.println("invoke callback javascript...");
                String result = call.testMe("a", "b");
                // do something with the result ...
                System.out.println("invoke callback...done, result: "+result);
            }
        });
        js.eval(  "var handler = {\"testMe\": function (a,b){return a + \" is concatenated to \"+ b;}};\n"
                + "var callback = new Packages.com.hal.research.CallFunction.WhatEverYouWant(handler);\n"
                + "producer.doSomethingWithIt(callback); ");
    }
}


我认为问题不在于如何从Javascript调用Java方法(您已经给出了一个示例),而在于如何将Javascript函数传递给Java方法并从Java代码调用该函数。@Christian Semrau-接口实现应该调用Javascript函数(我称之为
print
),McDowell是正确的。谢谢方法callFromRhino可以这样定义,并且可以工作!public void callFromRhino(Runnable callback){callback.run();}现在我明白了。JavaScript实现一个接口(
Runnable
),并调用Java方法,该方法反过来调用脚本实现的接口。参数传递如何?这是一个小程序吗?如果不是,那是不可能的,因为JavaScript代码是在客户端执行的,而Java代码是在服务器端执行的。很抱歉,运行时变量在该过程中丢失。您需要通过
POST
GET
请求调用Java,并将数据作为请求参数传递。@FK82-Rhino是用Java编写的JavaScript解释器(它作为脚本API的一部分包含在Java 6 JVM中)@McDowell:OP没有具体说明他试图从哪个运行时调用Rhino/JavaScript函数。Java 6的内置Rhino引擎中没有sun.org.mozilla.JavaScript.function。我将使用可下载的rhino jar来实现它。注意,在可下载的rhino jar中,接口名为
org.mozilla.javascript.Function
——Sun将其JDK中提供的版本中的所有接口重命名。不客气。我也在为同样的问题苦苦挣扎,没有找到一个满意的答案来回答你的问题,所以我觉得有必要找到一个有效的答案。从答案开始,我已经验证了这是非常有效的,而且让回调调用java,调用带有参数的函数似乎并不困难。真的很酷!我想知道是否可以将node.js移植到rhino。英雄联盟