使用 Nashorn JavaScript 引擎访问 ScriptContext 变量 (Java 8)
Access variable of ScriptContext using Nashorn JavaScript Engine (Java 8)
我在 Java Rhino
Java脚本引擎中使用了以下代码:
@Test
public void testRhino() throws ScriptException {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("rhino");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
脚本的输出(使用Rhino
)是:
I am the raw value injected
I am a result
I am a returned value
在 Nashorn
Java脚本引擎中,我没有得到 result
:
的值
@Test
public void testNashorn() throws ScriptException {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("nashorn");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
returns
I am the raw value injected
null
I am a returned value
如何使用 nashorn
引擎访问 ScriptContext
的 result
变量的值?
Nashorn 将存储在 ScriptContext
中的 Bindings
视为 "read-only"。
任何设置存储在 Bindings
对象中的变量(或创建新变量)的尝试都将导致在 nashorn.global
中创建一个新变量,该变量以该名称隐藏 Bindings
参数。
您可以使用引擎来 "evaluate" 变量,使用此代码:
System.out.println( engine.eval("result", ctx) );
然而,这非常难看。 "result" 首先编译成脚本,然后对该脚本求值,得到 return 变量的值。适合测试,但对于通用解决方案来说效率可能有点太低了。
一个更好但可能更脆弱的方法是提取 "nashorn.global" 变量,并查询它以获得所需的值。
Bindings nashorn_global = (Bindings) ctx.getAttribute("nashorn.global");
System.out.println( nashorn_global.get("result") );
另请参阅我在 中的 hack/answer,了解在评估脚本后将 nashorn.global
值自动移回 Map<String,Object>
的方法。
如果您使用 ScriptEngine.createEngine API 创建 ENGINE_SCOPE 绑定,它将按预期工作:
import javax.script.*;
public class Main {
public static void main(String[] args) throws Exception {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("nashorn");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
// **This is the inserted line**
ctx.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
}
我在 Java Rhino
Java脚本引擎中使用了以下代码:
@Test
public void testRhino() throws ScriptException {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("rhino");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
脚本的输出(使用Rhino
)是:
I am the raw value injected
I am a result
I am a returned value
在 Nashorn
Java脚本引擎中,我没有得到 result
:
@Test
public void testNashorn() throws ScriptException {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("nashorn");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
returns
I am the raw value injected
null
I am a returned value
如何使用 nashorn
引擎访问 ScriptContext
的 result
变量的值?
Nashorn 将存储在 ScriptContext
中的 Bindings
视为 "read-only"。
任何设置存储在 Bindings
对象中的变量(或创建新变量)的尝试都将导致在 nashorn.global
中创建一个新变量,该变量以该名称隐藏 Bindings
参数。
您可以使用引擎来 "evaluate" 变量,使用此代码:
System.out.println( engine.eval("result", ctx) );
然而,这非常难看。 "result" 首先编译成脚本,然后对该脚本求值,得到 return 变量的值。适合测试,但对于通用解决方案来说效率可能有点太低了。
一个更好但可能更脆弱的方法是提取 "nashorn.global" 变量,并查询它以获得所需的值。
Bindings nashorn_global = (Bindings) ctx.getAttribute("nashorn.global");
System.out.println( nashorn_global.get("result") );
另请参阅我在 nashorn.global
值自动移回 Map<String,Object>
的方法。
如果您使用 ScriptEngine.createEngine API 创建 ENGINE_SCOPE 绑定,它将按预期工作:
import javax.script.*;
public class Main {
public static void main(String[] args) throws Exception {
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("nashorn");
final String raw = "I am the raw value injected";
final ScriptContext ctx = new SimpleScriptContext();
// **This is the inserted line**
ctx.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
String script = "var result = 'I am a result';";
script += "java.lang.System.out.println(raw);";
script += "'I am a returned value';";
final Object res = engine.eval(script, ctx);
System.out.println(ctx.getAttribute("result"));
System.out.println(res);
}
}