之前在一次機緣巧合的情況下,需要時用java執行js方法,查閱了一些文檔,找到了相關解決方法,這裡和大家分享一下。
在jdk1.6中為我們提供了一個<code>scriptenginemanager</code>類,scriptenginemanager 為 scriptengine 類實作一個發現和執行個體化機制,還維護一個鍵/值對集合來存儲所有 manager 建立的引擎所共享的狀态。此類使用服務提供者機制枚舉所有的 scriptenginefactory 實作。
scriptenginemanager 提供了一個方法,可以傳回一個所有工廠實作和基于語言名稱、檔案擴充名和 mime 類型查找工廠的實用方法所組成的數組。
鍵/值對的 bindings(即由管理器維護的 “global scope”)對于 scriptenginemanager 建立的所有 scriptengine 執行個體都是可用的。bindings 中的值通常公開于所有腳本中。
通過上面的描述,我們就應該知道了,需要時用到的類為<code>scriptenginemanager</code>和<code>scriptengine</code>。
我們先來看一下<code>scriptenginemanager</code>,
構造方法如下:
方法名
說明
scriptenginemanager()
如果調用者可通路線程上下文 classloader,則調用此構造方法的效果與調用 scriptenginemanager(thread.currentthread().getcontextclassloader()) 相同
scriptenginemanager(classloader loader)
此構造方法使用服務調用者機制加載對于給定 classloader 可見的 scriptenginefactory 實作
方法摘要如下:
傳回值
object
get(string key)
擷取 global scope 中指定鍵的值
bindings
getbindings()
getbindings
scriptengine
getenginebyextension(string extension)
查找并建立一個給定擴充的 scriptengine
getenginebymimetype(string mimetype)
查找并建立一個給定 mime 類型的 scriptengine
getenginebyname(string shortname)
查找并建立一個給定名稱的 scriptengine
list<scriptenginefactory>
getenginefactories()
傳回一個數組,該數組的元素是發現機制找到的所有 scriptenginefactory 類的執行個體
void
put(string key, object value)
設定 global scope 中指定的鍵/值對
registerengineextension(string extension, scriptenginefactory factory)
注冊一個 scriptenginefactory 來處理擴充
registerenginemimetype(string type, scriptenginefactory factory)
注冊一個 scriptenginefactory 來處理 mime 類型。
registerenginename(string name, scriptenginefactory factory)
注冊一個scriptenginefactory 來處理語言名稱
setbindings(bindings bindings)
setbindings 存儲 globalscope 字段中的指定 bindings
我們首先來看一下,jdk為我們提供了哪些可用的腳本引擎工廠,寫一段代碼測試一下:
運作結果如下:
<code>[nashorn, nashorn, js, js, javascript, javascript, ecmascript, ecmascript]</code>
通過控制台輸出的結果,我們知道jdk已經為我們實作了js相關的腳本引擎,我們直接使用就可以了,解決了引擎的問題,下面我們再來看看腳本引擎如何使用,這就需要<code>scriptengine</code>了。
scriptengine 是基礎接口,該接口的方法在此規範的每個實作中都必須具有完整的功能。
這些方法提供基本的腳本功能。為這個簡單接口編寫的應用程式應該對每個實作稍做修改就能夠運作。這包括執行腳本的方法,以及設定和擷取值的方法。
這些值是兩種類型的鍵/值對。組成第一種類型的鍵/值對中的鍵是此規範或個别實作中保留和定義的鍵。包含保留鍵的鍵/值對中的值具有指定的含義。
另一種類型由那些建立 java 語言 bindings 的鍵/值對組成,值通常通過相應鍵或其裝飾的形式用腳本表示。
createbindings()
傳回一個未初始化的 bindings
eval(reader reader)
除了腳本的源是以 reader 形式提供的外,與 eval(string) 相同
eval(reader reader, bindings n)
除了腳本的源是以 reader 形式提供的外,與 eval(string, bindings) 相同
eval(reader reader, scriptcontext context)
與 eval(string, scriptcontext) 相同,其中腳本的源是從 reader 讀取的
eval(string script)
執行指定的腳本
eval(string script, bindings n)
執行腳本,腳本執行期間使用 bindings 參數作為 scriptengine 的 engine_scope bindings
eval(string script, scriptcontext context)
立即執行腳本,該腳本的源是作為第一個參數傳遞的 string
擷取在此引擎的狀态中設定的值
getbindings(int scope)
傳回指定值的範圍
scriptcontext
getcontext()
傳回 scriptengine 的預設 scriptcontext,在沒有指定 scriptcontext 時,該 scriptengine 的 bindings、reader 和 writer 被用于腳本執行
scriptenginefactory
getfactory()
傳回此 scriptengine 所屬的類的 scriptenginefactory
設定 scriptengine 的狀态中的鍵/值對,它建立一個将在腳本執行中使用或者以其他方式使用的 java language binding,具體取決于該鍵是否被保留
setbindings(bindings bindings, int scope)
設定将由腳本使用的指定值的範圍。
setcontext(scriptcontext context)
設定 scriptengine 的預設 scriptcontext,在沒有指定 scriptcontext 時,該 scriptengine 的 bindings、reader 和 writer 被用于腳本執行
下面我們通過代碼來示範具體的使用方法
首先我們先來看一下如何執行一段簡單的js表達式:
通過這段代碼,我們很容易的就實作了java執行js的一段表達式。
在java中,我們不僅可以運作js的表達式,我們還可以執行js函數
這裡我們用到了<code>invocable</code>接口,<code>invocable</code>由 scriptengines 實作的可選接口,該 scriptengines 的方法允許在以前執行過的腳本中調用程式。當然啦,我們不僅能執行函數,還可以傳遞參數:
除此之外,我們還可以将java對象注入到js代碼中運作:
是不是很神奇呢?下面再介紹一種更神奇的,java通過線程啟動js函數:
好了,到這裡java運作js的方法已經介紹的差不多了,下面貼出完整的測試代碼: