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