Nashorn是在java中高效動態執行JS代碼的運行環境。
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval("print('hello');"); // execute js from source File f = new File("resources/scripts.js"); engine.eval(new FileReader(f)); // execute js from file
調用JS
首先把需要調用的js代碼保存為scripts.js:
function add(a, b) { return a + b; } var f1 = function(name) { print("JS: " + name); return "Greeting from JS"; } var f2 = function(obj) { print("JS Class: " + Object.prototype.toString.call(obj)); }
Java中調用:
ScriptEngine engine = new ScriptEngineManager() .getEngineByName("nashorn"); engine.eval("print('hello');"); // execute js from source File f = new File("resources/scripts.js"); engine.eval(new FileReader(f)); // execute js from file Invocable invocable = (Invocable) engine; Object sum = invocable.invokeFunction("add", 1, 2); System.out.println(sum); invocable.invokeFunction("f2", new Date()); invocable.invokeFunction("f2", LocalDateTime.now());
由於js中的代碼在jvm中是原生態調用,類型不會丟失。
調用Java
Java方法必須是public。否則調用的時候找不到:
public static String greeting(String name) { System.out.println("From Java " + name); return "From Java"; } public static void getCls(Object obj) { System.out.println(obj.getClass()); }
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
File f = new File("resources/scripts.js");
engine.eval(new FileReader(f)); // execute js from file
JS代碼:
var cls = Java.type("nashorn.NashornTest"); print(cls.greeting('Zhijie'));
原始JS類型可以轉換成適當的Java包裝類。原生JS對象表示成內部適配類。
cls.getCls(123); //class java.lang.Integer cls.getCls(49.99); //class java.lang.Double cls.getCls(true); //class java.lang.Boolean cls.getCls("hi there") //class java.lang.String cls.getCls(new Number(23)); //class jdk.nashorn.internal.objects.NativeNumber cls.getCls(new Date()); //class jdk.nashorn.internal.objects.NativeDate cls.getCls(new RegExp()); //class jdk.nashorn.internal.objects.NativeRegExp cls.getCls({foo: 'bar'}); //class jdk.nashorn.internal.scripts.JO4
ScriptObjectMirror
jdk.nashorn.api.scripting.ScriptObjectMirror是JS對象在Java中的映射。這個類實現了Map接口。
public static void f(ScriptObjectMirror mirror) { System.out.println(mirror.getClassName() + ": " + Arrays.toString(mirror.getOwnKeys(true))); } public static void callMethodOfJSObject(ScriptObjectMirror person) { System.out.println("Full Name is: " + person.callMember("getFullName")); }
cls.f({a:'a',b:'b'}); function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = function() { return this.firstName + " " + this.lastName; } } var person1 = new Person("Zhijie", "Liu"); cls.callMethodOfJSObject(person1);
Nashorn擴展了ECMAScript 5:
-
Typed Arrays
-
Collections and For Each
-
Lambda expressions and Streams
-
Extending classes
-
Parameter overloading
-
Java Beans
-
Function Literals
-
Binding properties
-
Trimming strings
-
Whereis
-
Import Scopes
-
Convert arrays
-
Calling Super
-
Loading scripts
可以進一步閱讀http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/