JavaでJavaScriptを実行するにはjavax.script.ScriptEngineを使用する。
実行の際にはパラメータを渡したり計算結果を受け取ったりするがそのための方法がリファレンスを読んでもわかりにくかったのでどう受け渡しができるのかを試してみた。
パラメータをひとつづつ渡す
パラメータを渡すにはScriptEngineのputメソッドにJavaScriptでの変数名を指定する。
JavaScript側では通常の変数として利用できる。
try {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine e = factory.getEngineByName("js");
e.put("a", "hello");
e.put("b", "world");
String script = "ab=a + ' ' +b;";
Object ret = e.eval(script);
Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
for(String key : b.keySet()) {
Object v= b.get(key);
System.out.println("key=" + key + "; value=" + v + " (" + v.getClass() + ")");
}
} catch (ScriptException ex) {
ex.printStackTrace();
}
実行結果
key=a; value=hello (class java.lang.String)
key=b; value=world (class java.lang.String)
key=ab; value=hello world (class java.lang.String)
retには最後に実行した式の結果が入る。ここではabの値と同じ。
パラメータをMapで渡す
Mapで渡したパラメータはJavaScript側ではオブジェクトのプロパティとして使用できる。
try {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine e = factory.getEngineByName("js");
Map<String, Object> map = new HashMap();
map.put("x", "hello");
map.put("y", "world");
e.put("map", map);
String script = "x = map.x; xy=map.x+' '+map.y;";
Object ret = e.eval(script);
Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
for(String key : b.keySet()) {
Object v= b.get(key);
System.out.println("key=" + key + "; value=" + v + " (" + v.getClass() + ")");
}
} catch (ScriptException ex) {
ex.printStackTrace();
}
実行結果
key=map; value={x=hello, y=world} (class java.util.HashMap)
key=x; value=hello (class java.lang.String)
key=xy; value=hello world (class java.lang.String)
パラメータをListで渡す
Listで渡したパラメータはJavaScript側では配列として使用できる。
try {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine e = factory.getEngineByName("js");
List<String> list = new ArrayList();
list.add("Tokyo");
list.add("Nagoya");
list.add("Osaka");
e.put("list", list);
String script = "list0=list[0]; list1=list[1]; list2=list[2]; length=list.size();";
Object ret = e.eval(script);
Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
for(String key : b.keySet()) {
Object v= b.get(key);
System.out.println("key=" + key + "; value=" + v + " (" + v.getClass() + ")");
}
} catch (ScriptException ex) {
ex.printStackTrace();
}
実行結果
key=list; value=[Tokyo, Nagoya, Osaka] (class java.util.ArrayList)
key=list0; value=Tokyo (class java.lang.String)
key=list1; value=Nagoya (class java.lang.String)
key=list2; value=Osaka (class java.lang.String)
key=length; value=3 (class java.lang.Integer)
Listの要素にMapを渡すこともできる。
try {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine e = factory.getEngineByName("js");
List<Map<String, Object>> list = new ArrayList();
Map<String, Object> map1 = new HashMap();
map1.put("v1", 100);
map1.put("v2", 200);
map1.put("v3", 300);
lista.add(map1);
Map map2 = new HashMap();
map2.put("v1", 110);
map2.put("v2", 210);
map2.put("v3", 310);
lista.add(map2);
e.put("list", list);
String script = "list0_v1=lista[0].v1; list1_v1=lista[1].v1;";
Object ret = e.eval(script);
Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
for(String key : b.keySet()) {
Object v= b.get(key);
System.out.println("key=" + key + "; value=" + v + " (" + v.getClass() + ")");
}
} catch (ScriptException ex) {
ex.printStackTrace();
}
実行結果
key=list; value=[{v1=100, v2=200, v3=300}, {v1=110, v2=210, v3=310}] (class java.util.ArrayList)
key=list0_v1; value=100 (class java.lang.Integer)
key=list1_v1; value=110 (class java.lang.Integer)