5

問題の説明

私の質問を説明するためのやや不自然な例。フロントエンド開発者の軍隊によってすでに維持され、毎日更新されている JavaScript 関数のライブラリがあると想像してください。具体的には、そのような関数の 1 つが次のようになると想像してください。

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 と google を検索した結果、これには以下を使用する必要があることを理解しています。

  • javax.script.ScriptEngineManager
  • javax.script.ScriptEngine
  • おそらくscriptEngine.getContext()関数に値を渡し、結果を受け取るためです。

特に、私が見つけたほとんどの例では、javascript 関数を Java で使用できるようにするのではなく、javascript コードを 1 回実行する必要があるため、上記の詳細については少し曖昧です。

見たいサンプルコード

  1. js 関数がファイル "my_functions.js" にあると仮定すると、そのファイルを Java にロードして、そのすべての関数を使用できるようにします。
  2. を呼び出しemployeesForStore("downtown")て、その結果をネイティブ JavaString[]またはList<String>という変数に格納しますdowntownResults
  3. 2 と同じですが、呼び出しemployeesForStore("uptown")て変数に格納しますuptownResults
4

2 に答える 2

3

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);
  }
}

インターフェースを指定することで、Rhino が JavaScript 型を Java 型 (String、String[] など) に変換できるようにします。

JRE 仕様では、どのスクリプト エンジンを提供する必要があるかについて保証されていないため、外部エンジンに依存することが賢明な場合があります。Nashornがこれを変更するかどうかはわかりません。

于 2013-04-24T15:13:29.750 に答える