Mozilla Rhino:覆盖JavaScript对象方法

3
我希望你能够在Rhino中使用JavaScript覆盖Java方法。以下是我的代码:

我正在寻找一种在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)

更新 根据评论的要求,这是我的完整源代码:

CustomClass.java

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

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

Scripting.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();
        }
    }
}

你在哪里重写这个方法?我在你的代码中没有看到任何继承。 - kaysush
@SushilKumar 我想要在 JavaScript 中重写该方法。请看我的评估字符串代码:CustomClass.doSomething=function(args){}; - Doua Beri
我无法运行那段代码。请发布一个SSCCE - linski
@linski 我已经更新了帖子,请查看完整的代码。 - Doua Beri
我没有按照你的要求完全写出来(希望很快能够做到),但我找到了一个覆盖Java方法的JS替代解决方案,可以在这里看到一个例子:http://my.opera.com/sutabi/blog/putting-the-java-into-javascript-with-rhino。 - linski
1个回答

1
当这段代码运行时,Rhino不会调用Java的doSomething方法。相反,它尝试调用其JavaScript对应项(该项缺失),然后抛出一个sun.org.mozilla.javascript.internal.EvaluatorException: Java class "CustomClass" has no public instance field or method named "doSomething". (#1)异常。
您的CustomClass是一个纯Java类,没有JavaScript对应项。如果您在源代码中替换此行:
String s="CustomClass.doSomething=function(args){};";

使用这行代码:

String s = "CustomClass";

将其作为javasript命令进行评估,输出结果为CustomClass@15e0be38。这通常意味着它是类CustomClass的对象的某个("15e0be38")实例。

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


定义了一个从实现Scriptable的Java类中定义JavaScript对象的过程。接下来,扫描所有方法以查找特殊前缀,这些前缀指示它们对于定义JavaScript对象具有特殊含义。这些特殊前缀包括:
- jsFunction_ 用于JavaScript函数 - jsStaticFunction_ 用于作为构造函数属性的JavaScript函数 - jsGet_ 用于JavaScript属性的getter - jsSet_ 用于JavaScript属性的setter - jsConstructor 用于构造函数的JavaScript函数
如果方法名称以"jsFunction_"开头,则将创建一个JavaScript函数,其名称由Java方法名称中"jsFunction_"后面的其余部分组成。因此,名为"jsFunction_foo"的Java方法将定义一个名为"foo"的JavaScript方法。调用此JavaScript函数将导致调用Java方法。该方法的参数必须是由FunctionObject类定义的数字和类型。然后将JavaScript函数添加为原型的属性。
JavaScript print方法(在org.mozilla.javascript.tools.shell.Global类中定义)与Java System.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编写的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接