Rhino:如何将Java对象传递给脚本,其中可以引用为“this”
Rhino: How to pass Java object to script, where can be referenced as "this"
我是JSR-223 Java脚本的新手,实际上我是从MVEL切换到标准的Mozilla Rhino JS。我已经阅读了所有的文档,但还是卡住了。我试图引用一些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)");
我知道this
在JavaScript中具有特殊的意义(如在Java中),但在MVEL脚本中,可以通过使用自定义ParserContext
和自定义PropertyHandler
来完成。
在Rhino中可能有这样的东西吗?
我试着从Pointy的回答中实现这个想法(再次感谢),但是这个解决方法对于没有this
前缀的属性不起作用,这似乎是IMHO非常相同。而不是使用来自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
无效?有什么问题被忽视了吗?尖尖的?
嗯,在JavaScript中,真正有意义的是考虑在调用函数的上下文中设置this
。因此,我认为您应该能够在ScriptEngine上使用"invoke"方法(必须转换为"Invocable"):
((Invocable) engine).invokeMethod(objectForThis, "yourFunction", arg, arg ...);
现在"objectForThis"引用(在我的经验中)通常是从先前调用"eval()"返回的东西(或"invokeMethod"我猜);换句话说,它应该是脚本引擎使用适当语言的对象。您是否可以在那里传递Java对象(并使其工作),我不确定。
- jQuery$(this)引用未定义
- Javascript对象文字,如何使用“this”来引用对象中的变量
- 在调用的函数中使用对象引用(this)
- 为什么您可以在不引用“this”的情况下操作对象属性
- 调用插件时如何引用 $(this)
- 当调用“this”的函数位于子对象的对象内时,您将如何引用“this”
- JS在回调时引用“this”
- Javascript:从给定的两个片段中引用“this”的可接受方式
- Tempo js - 呈现字符串或简单对象的数组,在模板中引用“this”
- 将引用$(this)保存到DB
- 关于在提交点击时引用$(this)到多输入的问题
- Javascript模式:引用"this"在私人和公共场合
- 验证的重点是错误,AND引用THIS元素
- JS类中没有常量引用"this"用于成员访问
- JavaScript -引用'this'在内部函数中
- 引用“this"在对象原型方法中的setInterval/setTimeout
- 如何引用“this”?传递给函数的另一个参数
- 如何正确引用“this”
- 在JavaScript对象字面量中,我应该引用'this'或者变量名
- 在回调函数中引用.this出错