2015-10-13 75 views
2

我正在研究Java中的API,它允許用戶編寫腳本並訪問由Nashorn腳本引擎傳入(以API對象的形式)的特定一組方法。將JavaScript日期提供給Nashorn腳本

我想在JavaScript中調用函數getDate(),它將返回一些從Java端提供的任意日期(作爲本地JavaScript日期)。

我試着簡單地把一個org.java.util.Date放在API對象上,但那不會像JS日期那樣工作。我們的目標是儘可能簡化對JS有經驗的最終用戶。

的Java實施例:

public class MyAPI { 
    public void log(String text){ 
     System.out.println(text); 
    } 

    public Date getDate(){ 
     // Return something that converts to a native-JS date 
    } 

    public static void main(){ 
     // MyClassFilter implements Nashorn's ClassFilter 
     ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(new MyClassFilter()); 
     ((Invokable) engine).invokeFunction("entryPoint", new MyAPI()); 
    } 

JavaScript示例

function entryPoint(myApi){ 
    var date = myApi.getDate(); 
    myApi.log(date.getMinutes()); 
} 

回答

2

的犀牛發動機具有其內部使用的物體,其代表了JavaScript對象。正如你已經猜到了java.util.Date != new Date()(在JavaScript中)。該引擎使用名爲jdk.nashorn.internal.objects.NativeDate的類來表示其JS日期。

如果我構建了這個,我不會在Java中構造NativeDate,而是在Javascript中包含一個包含MyApi對象的包裝,該對象將包含一些其他本機JS方法,如getDate()

var MYAPI_JAVASCRIPT = { 
    log: function() { 
     print(arguments); 
    }, 
    getDate: function() { 
     return new Date(); 
    } 
} 

然後,您可以傳遞該對象作爲方法參數。


但是,如果你在Java代碼中使用NativeDate,那麼你可以構建一個像這樣真正的設置:

public NativeDate getDate() { 
    return (NativeDate) NativeDate.construct(true, null); 
} 
+0

謝謝,第二個選項做到了!僅供參考,我需要這樣做,因爲API中的方法調用了大量的Java代碼。 –

+1

@MoscowModder如果你尋找任何可以使用'print(Date.prototype)'的Javascript對象的本地類,當然用你尋找的任何對象替換'Date'。在Date的情況下,你會得到如下內容:'jdk.nashorn.internal.objects。NativeDate $ @原型b7f23d9' –

3

jdk.nashorn.internal *包犀牛內部實現類。無法保證在JDK版本之間不會更改或刪除這些內容。除了周圍的安全管理員,直接從Java代碼訪問這些包將導致拋出SecurityException!使用jdk9模塊化jdk,這些包不是從nashorn模塊導出的包,所以javac甚至不會在jdk9中編譯您的代碼!

我建議在用戶「ug_」的答案中使用JS包裝(解決方案1)。如果您必須從Java調用,則可以使用從jdk.nashorn.api.scripting包導出的API。

如果「發動機」是你的犀牛的javax.script.ScriptEngine中,那麼你可以做類似如下:

import jdk.nashorn.api.scripting.*; 

.. 

public Object getDate() { 
    // get JS Date constructor object - you can get once and store 
    // as well/ 
    JSObject dateConstructor = (JSObject) engine.eval("Date"); 
    // now do "new" on it 
    return dateConstructor.newObject(); 
} 

就這樣,你的JS腳本可以調用「GETDATE()」你的API對象並獲得一個JS Date0對象。請注意,您也可以將構造函數參數傳遞給newObject方法調用(它是一種Java可變參數方法)。