一个有点人为的例子来说明我的问题。想象一下,我们有一些javascript函数库已经由前端开发团队每天维护和更新。具体来说,假设一个这样的函数看起来像这样:
function employeesForStore(store) {
var dictionary = {
"downtown": ["Joe", "Mary", "Steve"],
"uptown": ["Jules", "Vincent", "Matt"],
// and so on for hundreds of locations
};
return dictionary[store];
}
注意:请忽略此功能实施的详细信息。实际函数可能比简单的JSON字典查找复杂得多,并假设我们不知道有关js函数的任何实现细节。我们所知道的是它需要一个String参数并返回和字符串数组。
现在我们想在Java代码中利用这个功能。也就是说,在我们的Java代码中,我们想要“加载”这个函数,然后能够多次调用它,传递String
args并接收String[]
或ArrayList<String>
结果
从搜索SO和谷歌到目前为止,我知道这将涉及使用:
javax.script.ScriptEngineManager
javax.script.ScriptEngine
scriptEngine.getContext()
将值传递给函数并接收结果。 我对上面的细节有点模糊,特别是因为我发现的大多数例子都涉及一次运行javascript代码,而不是让javascript函数可用于Java。
employeesForStore("downtown")
并将其结果存储在名为String[]
的变量中的原生java List<String>
或downtownResults
中。employeesForStore("uptown")
并存储在变量uptownResults
答案 0 :(得分:2)
答案 1 :(得分:2)
创建一个界面,充当JavaScript代码的facade。
以下是使用Oracle Java 1.7实现中嵌入的Rhino实现的示例:
package demo;
import java.io.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import javax.script.*;
public class StoreData {
public static interface Stores {
public String[] employees(String store);
}
public static Stores stores() throws IOException, ScriptException {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("JavaScript");
AtomicReference<Stores> ref = new AtomicReference<>();
engine.put("ref", ref);
String adapt = "ref.set("
+ "new Packages.demo.StoreData.Stores({employees:employeesForStore})"
+ ");";
try (Reader myFns = new FileReader("my_functions.js")) { // TODO encoding
engine.eval(myFns);
engine.eval(adapt);
return ref.get();
}
}
public static void main(String[] args) throws IOException, ScriptException {
List<String> employees = Arrays.asList(stores().employees("uptown"));
System.out.println(employees);
}
}
通过指定接口,我们让Rhino将JavaScript类型强制转换为Java类型(String,String []等)。
JRE规范使no guarantees关于应该提供什么脚本引擎,因此依赖外部引擎可能是明智之举。我不知道Nashorn是否会改变这种情况。