简体   繁体   English

使Javascript函数可用于Java代码

[英]Making A Javascript Function Available To Java Code

Problem Description 问题描述

A somewhat contrived example to illustrate my question. 一个有点人为的例子来说明我的问题。 Imagine we have some library of javascript functions that is already maintained and updated daily by an army of frontend devs. 想象一下,我们有一些javascript函数库已经由前端开发团队每天维护和更新。 To be specific, imagine one such function looks like this: 具体来说,假设一个这样的函数看起来像这样:

function employeesForStore(store) {
    var dictionary = {
        "downtown": ["Joe", "Mary", "Steve"],
        "uptown": ["Jules", "Vincent", "Matt"],
        // and so on for hundreds of locations
    };
    return dictionary[store];
}

NOTE: Please ignore the details of this function's implementation. 注意:请忽略此功能实现的详细信息。 The actual function may be far more complex than simple JSON dictionary lookups, and assume we don't know any implementation details about the js function. 实际函数可能比简单的JSON字典查找复杂得多,并假设我们不知道有关js函数的任何实现细节。 All we know is it takes a String argument and returns and array of Strings. 我们所知道的是它需要一个String参数并返回和字符串数组。

Now we would like to take advantage of this function in our Java code. 现在我们想在Java代码中利用这个功能。 That is, in our Java code, we'd like to "load" this function, and then be able to call it multiple times, passing it String args and receiving String[] or ArrayList<String> results. 也就是说,在我们的Java代码中,我们想要“加载”这个函数,然后能够多次调用它,传递String args并接收String[]ArrayList<String>结果。

From searching SO and google so far, I understand that this will involve using: 从搜索SO和谷歌到目前为止,我知道这将涉及使用:

  • javax.script.ScriptEngineManager
  • javax.script.ScriptEngine
  • and perhaps scriptEngine.getContext() for passing values into the function and receiving results. 也许是scriptEngine.getContext()用于将值传递给函数并接收结果。

I am a bit hazy on the details of the above, especially since most examples I've found involve running javascript code a single time, rather than making javascript function available to Java. 我对上面的细节有点模糊,特别是因为我发现的大多数例子都涉及一次运行javascript代码,而不是让javascript函数可用于Java。

Example Code I'd Like To See 我希望看到的示例代码

  1. Assuming the js function is in the file "my_functions.js", load that file into Java so all of its functions will be available for use. 假设js函数位于文件“my_functions.js”中,请将该文件加载到Java中,以便所有函数都可以使用。
  2. Call employeesForStore("downtown") and store its results in a native java String[] or List<String> in a variable called downtownResults . 调用employeesForStore("downtown")并将其结果存储在名为downtownResults的变量中的本机java String[]List<String>中。
  3. Same as 2, but call employeesForStore("uptown") and store in variable uptownResults 与2相同,但调用employeesForStore("uptown")并存储在变量uptownResults

You can use Rhino API to execute JS code in java 您可以使用Rhino API在java中执行JS代码

This tutorial covers the examples requested. 教程涵盖了所请求的示例。

Create an interface to act as a facade to your JavaScript code. 创建一个接口,充当JavaScript代码的外观

Here is an example using the Rhino implementation embedded in Oracle's Java 1.7 implementation: 以下是使用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);
  }
}

By specifying an interface we let Rhino coerce the JavaScript types to Java types (String, String[], etc.) 通过指定接口,我们让Rhino将JavaScript类型强制转换为Java类型(String,String []等)

The JRE spec makes no guarantees about what scripting engines should be provided so it may be wise to rely on an external engine. JRE规范不保证应该提供什么脚本引擎,因此依赖外部引擎可能是明智之举。 I don't know if Nashorn will change this. 我不知道Nashorn是否会改变这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM