2015-10-22 30 views
2

我正嘗試從Rhino遷移/更新我的項目以使用Nashorn。我在Java中實現了一些全局實用功能,並將其添加到目標腳本引擎的全局範圍中,典型示例是log(message)將Java實現的函數添加到Nashorn的全局範圍中

在Rhino中它經由

public static class LogFunction extends org.mozilla.javascript.BaseFunction { 
    @Override 
    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { 
     ... 
    } 
} 

其實例加入到目標範圍實施。在納什恩的情況下需要做些什麼?我無法找到Nashorn如何實現獨立功能。

回答

4

您可以在Java中輕鬆實現腳本功能。您只需使用lambda實現任何@FunctionalInterface(https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html)接口,並通過調用ScriptEngine.put(https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngine.html#put-java.lang.String-java.lang.Object-)方法公開相同的全局變量。下面的例子實現了在Java代碼中實現的兩個這樣的腳本'函數'。

import javax.script.*; 
import java.util.function.*; 
import java.util.Random; 

public class Main { 
    public static void main(String[] args) throws Exception { 
    ScriptEngineManager m = new ScriptEngineManager(); 
    ScriptEngine e = m.getEngineByName("nashorn"); 

    // expose 'log' function - any @FunctionInterface Java 
    // object can be exposed as 'function' 
    e.put("log", (Consumer<String>)System.out::println); 

    Random r = new Random(); 
    // expose 'next gaussian' as script global function 
    e.put("gaussian", (Supplier<Double>)r::nextGaussian); 

    // call functions implemented in Java! 
    e.eval("log('hello')"); 
    e.eval("print(gaussian())"); 
    e.eval("print(gaussian())"); 
    } 
} 
1

問我再次一派,發現這個職位的問題了一段時間後:http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-December/002520.html

*)實現JDK(或您自己的 @FunctionalInterface任何@FunctionalInterface接口)和合格/認沽 javax.script.Bindings甚至是全局作用域中的對象。腳本可以通過 訪問這些功能。

*)在你的類中實現jdk.nashorn.api.scripting.JSObject,並在其上實現「調用」方法。同樣,nashorn的靈活dynalink基於 鏈接器將對待您的JSObject impl。就好像它是一個功能一樣。這個 也可以用來實現「構造函數」(newObject方法)中的Java 等代碼。

我決定去與JSObject實現和我的代碼看起來更犀牛般,比Sundararajan的答覆建議的方法更接近我原來的代碼。不確定他們之間是否有任何性能差異。

import jdk.nashorn.api.scripting.AbstractJSObject; 

public static class PrintFunction extends AbstractJSObject { 

    public PrintFunction() { 
    } 

    @Override 
    public boolean isFunction() { 
     return true; 
    } 

    @Override 
    public Object call(Object thiz, Object... args) { 
     ... do something ... 

     return null; 
    } 
} 

... 

void onInitScriptObjects(Bindings scope) { 
    scope.put("print", new PrintFunction()); 
} 
相關問題