3

我正在寻找从 rhino 中的 javascript 覆盖 java 方法。这是我的代码:

public class CustomClass {
public String s="some string";
public void doSomething(){}
}

进而:

        Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
        ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);
        String s="CustomClass.s='aaa'; \n CustomClass.doSomething=function(args){};";
        Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

因此可以将值更改为 CustomClass.s 但不能更改为方法 doSomething

我收到以下错误:

org.mozilla.javascript.EvaluatorException:无法分配 Java 方法“doSomething”。(#2)

更新 按照评论中的要求,这里是我的完整源代码:

自定义类.java

public class CustomClass {
    public String s="Do something now!";

    public void doSomething(Object ... v){
        System.out.println("do something");
    }
}

脚本.java

import org.mozilla.javascript.*;
public class Scripting {
    public static void main(String args[])
    {

        Context cx = Context.enter();
        try {

            Scriptable scope = cx.initStandardObjects();

            Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
            ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);


            String s="CustomClass.doSomething=function(args){};";

            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

            System.err.println(Context.toString(result));
        }catch(WrappedException e){
            e.printStackTrace();

        } catch(Exception e){
            e.printStackTrace();
        }finally {
            // Exit from the context.
            Context.exit();
        }
    }
}
4

1 回答 1

1

当这段代码运行时,Rhino 不会调用 JavadoSomething方法。相反,它会尝试调用其对应的 javascript(缺少),然后引发 sun.org.mozilla.javascript.internal.EvaluatorException: Java class "CustomClass" has no public instance field or method named "doSomething". (#1)异常。

YourCustomClass是一个纯 Java 类,没有对应的 JavaScript。如果您在源代码中替换此行:

String s="CustomClass.doSomething=function(args){};";

用这条线:

String s = "CustomClass";

并将其评估为 javasript 命令,它将输出为CustomClass@15e0be38. 这通常意味着它是 class 对象的 some("15e0be38") 实例CustomClass

来自方法的 apidoc ScriptableObject.defineClass(Scriptable scope, java.lang.Class clazz)


从实现 Scriptable 的 Java 类定义 JavaScript 对象。
(...)
接下来,扫描所有方法的特殊前缀,这些前缀表明它们对定义 JavaScript 对象具有特殊意义。这些特殊前缀是

jsFunction_ 用于 JavaScript 函数
jsStaticFunction_ 用于作为构造函数属性的JavaScript 函数 jsGet_ 用于 JavaScript 属性
的 getter jsSet_ 用于 JavaScript 属性
的设置器
jsConstructor 用于作为构造函数的 JavaScript 函数

如果方法的名称以“jsFunction_”开头,则会创建一个 JavaScript 函数,其名称由“jsFunction_”后面的 Java 方法名称的其余部分组成。因此名为“jsFunction_foo”的 Java 方法将定义一个 JavaScript 方法“foo”。调用此 JavaScript 函数将导致调用 Java 方法。方法的参数必须是 FunctionObject 类定义的数量和类型。然后将 JavaScript 函数添加为原型的属性。


JavaScriptprint方法((在org.mozilla.javascript.tools.shell.Global类中定义))与 JavaSystem.out.println方法的接口。运行时

public class CustomClass {

public static class _CustomClass extends ScriptableObject {

    @Override
    public String getClassName() {
        return "CustomClass";
    }

    public int jsFunction_method() {
        System.out.println("from java method");
        return 2;
    }
}

public static void main(String[] args) {
    Context context = Context.enter();
    Global global = new Global(context);
    try {            
        //ScriptableObject.defineClass(global, CustomClass.class); 
        ScriptableObject.defineClass(global, _CustomClass.class);            
        String script = "myInstance = new CustomClass();myInstance+' ';";
        System.out.println(context.evaluateString(global, script, "", 1, null));
        script = "myInstance.method+' '+myInstance.method()";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
        script = "CustomClass.prototype.method=function(){print('overriden from javascript method');return 3;}";
        context.evaluateString(global, script, "", 1, null);
        script = "myInstance.method+' '+myInstance.method();";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        Context.exit();
    }
  }
  }

它输出:

[object CustomClass]
from java method
function method() {
[native code, arity=0]
}
 2

overriden from javascript method
function () {
    print("overriden from javascript method");
    return 3;
}
 3
  • 请注意,如果相同的 JS 代码在 Chrome 中运行,它会以不同的方式运行 - 返回 2 两次。
  • 如果使用了外部类(如注释中所述),则会出现与通用相关的编译时错误。此代码是使用Rhino 1.7r2 编写的
于 2013-01-07T23:30:52.083 回答