mozilla rhino从javascript覆盖对象方法

时间:2013-01-04 11:50:21

标签: java javascript rhino

我正在寻找从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();
        }
    }
}

1 个答案:

答案 0 :(得分: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对象具有特殊意义。这些特殊的前缀是

     

用于JavaScript函数的jsFunction_   jsStaticFunction_用于JavaScript函数,它是构造函数的属性
  jsGet_用于JavaScript属性的getter   jsSet_用于JavaScript属性的setter
  jsConstructor是一个JavaScript函数,它是构造函数

     

如果方法的名称以“jsFunction_”开头,则会创建一个JavaScript函数,其名称由“jsFunction_”之后的其余Java方法名称组成。 因此,名为“jsFunction_foo”的Java方法将定义JavaScript方法“foo”。调用此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
  • 请注意,如果在Chrome中运行相同的JS代码,则运行方式会有所不同 - 返回2次。
  • 如果使用了外部类(如在注释中),则会出现一般的相关编译时错误。此代码是使用Rhino 1.7r2
  • 编写的