我需要在mongoDB中运行以字符串格式保存的JS命令。为什么不以大写形式运行数据?
爪哇
public String read(String chave, String valor){
String processador = atributoDAO.getProcessador(chave);
if(processador != null){
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
try {
engine.eval(processador);
Invocable invocable = (Invocable)engine;
valor = (String)invocable.invokeFunction("process", valor);
} catch (ScriptException e) {
Log.error(AtributoReader.class, "erro no engine js", e);
} catch (NoSuchMethodException e) {
Log.error(AtributoReader.class, "erro no engine js", e);
}
return valor;
}
return valor;
}
数据库
{
"_id" : ObjectId("55390277e230ebff4fe25755"),
"atributo" : "peca_nome",
"processador" : "function(val) { return val.toUpperCase(); }"
}
答案 0 :(得分:2)
执行engine.eval("function(val) { return val.toUpperCase(); }")
时,您将在脚本引擎的范围内创建匿名函数。遗憾的是,以后无法调用它,因为函数未分配给变量。
您的呼叫invocable.invokeFunction("process", valor);
尝试呼叫function process( val )
,但脚本引擎的上下文中不存在具有该名称的功能。所以它会抛出一个NoSuchMethodException
。
有两种可能的解决方案。
重写数据库中的代码片段以将函数分配给变量,以便稍后调用它:
{
"_id" : ObjectId("55390277e230ebff4fe25755"),
"atributo" : "peca_nome",
"processador" : "process = function(val) { return val.toUpperCase(); };"
}
或者,在编译脚本之前,使用Java将变量添加到Javascript源代码中:
engine.eval("process = " + processador);
顺便说一句:在数据库中存储可执行代码通常是安全方面的一个非常危险的想法。如果有任何方法可以将用户提供的数据放入这些代码段中,则可以将应用程序打开到危险的代码执行漏洞。默认情况下,nashorn脚本引擎根本没有沙箱,非常强大。它可以执行JavaVM可以执行的任何操作,包括调用任何方法或从项目和java标准库构造任何对象。你在这里做什么看起来好像你要装满枪支。 如果你知道你在做什么,如果你遵循所有安全预防措施,它可能是安全的,但看起来你正准备开枪你自己(或其他人)。
答案 1 :(得分:0)
您可以评估匿名函数并将结果存储为对象。生成的对象是ScriptObjectMirror(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html)类型,它有一个调用(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html#call-java.lang.Object-java.lang.Object...-)函数的方法。
代码就像
Object thiz = engine.eval("this"); // get you global object
ScriptObjectMirror func = engine.eval("function() { print('hello'); }");
func.call(thiz); // pass global object as "this" for the function