我目前正在尝试使用nashorn在Java中使用lodash模板引擎,而我正面临一个问题。
以下是代码:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine nashorn = mgr.getEngineByName("nashorn");
ScriptContext ctx = nashorn.getContext();
Bindings bindings = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
nashorn.eval(readFileToString("externallibs/lodash.min.js"), bindings);
String tpl = readFileToString("hello.tpl");
bindings.put("tpl", tpl);
nashorn.eval("compiled = _.template(tpl);", bindings);
ScriptObjectMirror compiled = (ScriptObjectMirror)nashorn.get("compiled");
System.out.println("compiled = " + compiled);
Map<String, String> props = new HashMap<String, String(1);
props.put("name", "world");
bindings.put("props", props);
System.out.println(compiled.call(this, bindings.get("props"));
模板很好地由Nashorn编译,如果你看一下你会看到的控制台:
compiled = function(obj){obj||(obj={});var __t,__p='';with(obj){__p+='Hello, '+((__t=( name ))==null?'':__t);}return __p}
但是当我尝试使用map作为参数(props)调用上面编译的模板函数时,就像在JS中一样:
tpl.call(this, {name:'world'})
失败并出现以下错误:
TypeError: Cannot apply "with" to non script object
事实上,我们可以看到该函数的编译版本使用&#39; with&#39;关键字。
有没有人知道如何解决这个问题?我应该如何发送参数来呈现编译的模板?
非常感谢您的帮助。
答案 0 :(得分:3)
您需要将JS脚本对象传递给“with”语句。任意Java对象(不是JS对象 - 比如java.util.Vector或类Foo的对象)不能用作“with”表达式。您可以使用
之类的代码创建一个空脚本Object emptyScriptObj = engine.eval("({})");
并将emptyScriptObj传递给ScriptObjectMirror.call方法调用,例如。
答案 1 :(得分:2)
要将Java映射用作“with”语句的范围表达式,可以使用以下内容:
import javax.script.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws ScriptException {
Map<String, Object> map = new HashMap<>();
map.put("foo", 34);
map.put("bar", "hello");
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// expose 'map' as a variable
e.put("map", map);
// wrap 'map' as a script object
// __noSuchProperty__ hook is called to look for missing property
// missing property is searched in the map
e.eval("obj = { __noSuchProperty__: function(name) map.get(name) }");
// use that wrapper as scope expression for 'with' statement
// prints 34 and hello from the map
e.eval("with (obj) { print(foo); print(bar); }");
}
}