java - Rhino:如何将 Java 对象传递给脚本,其中可以引用为 "this"

标签 java javascript rhino

我是 JSR-223 Java 脚本的新手,实际上我是从 MVEL 切换过来的符合标准 Mozilla Rhino JS .我已阅读所有文档,但卡住了。我试过像在教程中那样通过绑定(bind)从脚本中引用一些 Java 对象:

    // my object
    public class MyBean {
       public String getStringValue() { return "abc" };
    }

    // initialization
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");

    // add bindings
    engine.put("bean", new MyBean());

    // evaluate script, output is "abc"
    engine.eval("print(bean.stringValue)");

Java 对象作为属性 bean 从脚本中引用。到目前为止,一切都很好。

但我想在脚本中将我的对象引用为this,我想使用它的属性和方法而不带任何前缀或明确地带有前缀this。就像这样:

    // add bindings
    engine.put(....., new MyBean()); // or whatever ???

    // evaluate scripts, all have the same output "abc"
    engine.eval("print(stringValue)");
    engine.eval("print(this.stringValue)");

我知道 JavaScript 中的 this 具有特殊含义(如在 Java 中),但在 MVEL 脚本中可以通过使用自定义 ParserContext 来完成和定制PropertyHandler .

在 Rhino 中可以实现这样的功能吗?

非常感谢。

最佳答案

我尝试执行 this idea来自 Pointy 的回答(再次感谢),但此解决方法不适用于没有 this 前缀的属性,恕我直言,这似乎是一样的。没有使用来自 Java API 的 Rhino 1.5,而是来自 Mozilla 的原始 Rhino 1.7。测试用例在这里:

import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Wrapper;

public class RhinoTest2 {

  private Obj obj = new Obj();

  public class Obj {
    public String getStringValue() {
      return "abc";
    }
  }

  private Object eval(String expression) {
    Context cx = Context.enter();
    try {
      ScriptableObject scope = cx.initStandardObjects();

      // convert my "this" instance to JavaScript object  
      Object jsObj = Context.javaToJS(obj, scope);

      // prepare envelope function run()    
      cx.evaluateString(scope, 
        String.format("function run() { %s }", expression), 
        "<func>", 1, null);

      // call method run()
      Object fObj = scope.get("run", scope);
      Function f = (Function) fObj;
      Object result = f.call(cx, scope, (Scriptable) jsObj, null);
      if (result instanceof Wrapper)
        return ((Wrapper) result).unwrap();
      return result;

    } finally {
      Context.exit();
    }
  }

  @Test
  public void test() {

    // works
    eval("return this.getStringValue()");
    eval("return this.stringValue");

    // doesn't work, throws EcmaError: ReferenceError: "getStringValue" is not defined.
    eval("return getStringValue()");
    eval("return stringValue");
  }
}

为什么 this.getStringValue()/this.stringValue 有效而 getStringValue()/stringValue 无效?有什么地方被忽视了吗?尖尖的?

关于java - Rhino:如何将 Java 对象传递给脚本,其中可以引用为 "this",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6709542/

相关文章:

java - JAVA中优先级队列的比较

java - 什么是NullPointerException,我该如何解决?

java - 在新变量赋值之前返回变量的优雅方法?

javascript - 如何取消选择告诉您哪个选项已更改的参数?如何获得正确的 JQuery 和 Javascript 总价?

Java 脚本引擎(nashorn 和犀牛): how to stack scopes/bindings?

Java - 如何使用此程序更有效地 "scan"我的文件系统的一部分?

javascript - 为什么这个JS代码打印undefined?

使用国际键盘输入印地语的 JavaScript 库

java - 将参数传递给 JavaScript 函数

java - 如何将 Rhino-JavaScript 数组转换为 Java 数组