问题描述
一个有点人为的例子来说明我的问题。想象一下,我们有一些 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 功能的任何实现细节。我们所知道的是它接受一个字符串参数并返回一个字符串数组。
现在我们想在我们的 Java 代码中利用这个功能。也就是说,在我们的 Java 代码中,我们希望“加载”这个函数,然后能够多次调用它,将它传递给 String
。参数和接收 String[]
或 ArrayList<String>
结果。
到目前为止,通过搜索 SO 和谷歌,我了解到这将涉及使用:
-
javax.script.ScriptEngineManager
-
javax.script.ScriptEngine
- 或许还有
scriptEngine.getContext()
用于将值传递给函数并接收结果。
我对上面的细节有点模糊,特别是因为我发现的大多数示例都涉及一次运行 javascript 代码,而不是让 javascript 函数可用于 Java。
我想看的示例代码
- 假设 js 函数在文件“my_functions.js”中,将该文件加载到 Java 中,这样它的所有函数都可供使用。
- 调用
employeesForStore("downtown")
并将其结果存储在 native java 中String[]
或List<String>
在一个名为downtownResults
的变量中. - 与 2 相同,但调用
employeesForStore("uptown")
并存储在变量uptownResults
中
最佳答案
创建一个接口(interface)作为 facade到您的 JavaScript 代码。
这是一个使用嵌入在 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);
}
}
通过指定接口(interface),我们让 Rhino 将 JavaScript 类型强制转换为 Java 类型(String、String[] 等)
JRE 规范使 no guarantees关于应该提供什么脚本引擎,以便依赖外部引擎可能是明智的。我不知道Nashorn将改变这一点。
关于java - 使 Javascript 函数可用于 Java 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16192656/