7

在 Java 程序中,我正在调用用户定义的 JavaScript 程序:

File userJSFile=...;
javax.script.ScriptEngineManager mgr=new  ScriptEngineManager();
javax.script.ScriptEngine scripEngine= mgr.getEngineByExtension("js");
Object result=scripEngine.eval(new java.io.FileReader(userJSFile));

现在我想使用“结果”:我怎样才能访问它?我可以将它识别为一个数组(我可以迭代 throw 它的成员)、 a String、 anInteger等...吗?

谢谢

已编辑:我只知道我的用户给了我一个返回最后一个值的脚本。我对这个值一无所知。它是一个String、一个数组等吗?我不知道,但我想使用它。

4

3 回答 3

9

除了简单的值之外,我宁愿让脚本引擎将其值强制转换为 Java 类型。

public class ScriptDemo {

  static class Result {
    private String[] words;

    public void setWords(String[] words) {
      this.words = words;
    }
  }

  static final String SCRIPT = "var foo = 'Hello World!';\n"
      + "result.setWords(foo.split(' '));";

  public static void main(String[] args)
      throws ScriptException {
    Result result = new Result();
    javax.script.ScriptEngineManager mgr = new ScriptEngineManager();
    javax.script.ScriptEngine scripEngine = mgr
        .getEngineByExtension("js");
    scripEngine.getContext().setAttribute("result", result,
        ScriptContext.ENGINE_SCOPE);
    scripEngine.eval(SCRIPT);
    System.out.println(Arrays.toString(result.words));
  }

}

即使您无法编辑脚本,您也可以获取返回值并将其传递给您自己生成的脚本来执行强制转换。这假设您对返回的值有所了解。


编辑:由于对返回值一无所知,我将首先使用 Java(getClass())对其进行测试,看看它是否是 java.lang 类型之一。如果返回的对象来自库私有的某个 API,我会使用脚本语言(在本例中为 JavaScript)对其进行自省,可能会在此过程中将其强制转换为 Java 类型或将其属性推送到某些 Java 数据结构中。

我的 JavaScript 生锈了,但 John Leach 的教程看起来相当不错:JavaScript Introspection

(您也许可以使用 Java 反射,但由于 Java 版本/JRE/JavaScript 引擎之间的引擎实现可能有所不同,因此我不会依赖它。)

于 2009-07-03T10:04:52.730 回答
2

这个问题是很久以前提出的,但答案似乎仍然正确。如果其他尝试在 Java 和 Javascript 之间传递复杂对象的人感兴趣,我想介绍我的解决方案。

我编写了一个脚本,将 NativeObject 转换为(内存中的)JSON 对象(实际上我使用 MongoDB 的基于 BSON 的对象,但您应该能够在下面的示例代码中用 1-1 替换 JSONArray 和 JSONObject)。

例如,假设我有一个(用户)脚本“create_object_script”,它“返回”一些感兴趣的对象或数组,然后我可以将其转换为 JSON(即哈希图列表),如下所示:

Object returnVal = engine.eval(create_object_script);
engine.put("output", returnVal);
BasicDBObject objFactory = new BasicDBObject(); // (or JSON equivalent)
BasicDBList listFactory = new BasicDBList(); // (or JSON equivalent)
BasicDBList outList = new BasicDBList(); // (or JSON equivalent)
engine.put("objFactory", objFactory);
engine.put("listFactory", listFactory);
engine.put("outList", outList);
engine.eval(parsing_script); // (described below)
// "outList" is now populated with (in-memory) JSON representations of "returnVal"

显然,如果您可以控制“create_object_script”脚本,您可以一步完成;我的脚本是用户生成的,因此隐藏这种复杂性是必要的——用户只需编写脚本,其中“返回值”是最后一行。

我在这里给出了“parsing_script”以减少这篇文章的长度。

从功能上讲,这很好用;我没有在 JS 中开发太多,所以可能有更有效的方法来做到这一点。(注意我总是需要我的结果在一个列表中,如果你不这样做,那么你可以传入一个 BasicDBObject“outObj”并在单例情况下写入它)。

希望这对昨晚凌晨 1 点发现自己处于我境地的人有所帮助!

于 2012-01-06T17:16:00.883 回答
0

链接可能会有所帮助。似乎您能做的最好的事情就是依赖于实现特定的类。

于 2009-07-03T09:07:44.987 回答