【问题标题】:mozilla rhino overriding an object method from javascriptmozilla rhino 覆盖来自 javascript 的对象方法
【发布时间】:2013-01-04 11:50:20
【问题描述】:

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

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

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

【问题讨论】:

  • 你在哪里重写方法?我在您的代码中看不到任何继承。
  • @SushilKumar 我想从 javascript 覆盖该方法。查看我的评估字符串代码:CustomClass.doSomething=function(args){};
  • 我无法运行该代码。请发布SSCCE
  • @linski 我已经更新了帖子。查看整个代码
  • 我没有按照你的要求写出来(希望我很快会写出来),但我找到了一个从 JS 覆盖 Java 方法的替代解决方案,请参阅示例 here

标签: java javascript rhino


【解决方案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 属性
jsSet_ 用于 JavaScript 属性的设置器
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
  • 请注意,如果同样的 JS 代码在 Chrome 中运行,它的运行方式会有所不同 - 两次返回 2。
  • 如果使用了外部类(如注释中所述),则会出现与通用相关的编译时错误。此代码是使用 Rhino 1.7r2 编写的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多