原文: JDK中內嵌JS引擎介紹及使用 - Stars-One的雜貨小窩 最近研究閱讀這個APP,其主要功能就是通過一個個書源,從而實現移動端閱讀的體驗 比如說某些線上小說閱讀網站,會加上相應的廣告,從而影響用戶閱讀體驗,於是閱讀這個APP就是做了類似凈化閱讀體驗 但是小說閱讀網站千千萬萬,如果去適 ...
原文: JDK中內嵌JS引擎介紹及使用 - Stars-One的雜貨小窩
最近研究閱讀這個APP,其主要功能就是通過一個個書源,從而實現移動端閱讀的體驗
比如說某些線上小說閱讀網站,會加上相應的廣告,從而影響用戶閱讀體驗,於是閱讀這個APP就是做了類似凈化閱讀體驗
但是小說閱讀網站千千萬萬,如果去適配每個小說閱讀網站,豈不是累死,且作者也會有被髮律師函的危險,於是作者提供了對應的工具,允許各位用戶可自定義書源,閱讀APP則通過導入書源,即可實現對某個小說閱讀網站的支持
這裡說的書源,實際上就是JS腳本代碼,作者本質上是使用了rhino這個Java的JS引擎技術來實現的
介紹
JDK1.6和JDK1.7採用Rhino。Nashorn 支持 ECMAScript 5.1 規範,使用基於 JSR 292 的新語言特性,其中包含在 JDK 7 中引入的 invokedynamic,將 JavaScript 編譯成 Java 位元組碼。
從JDK1.8開始,Java採用Nashorn作為嵌入式 JavaScript 引擎。
本質上,都是通用標準ECMAScriptJS規範,沒啥過多的區別
JDK內置的方式,其實也就是將對應JS引擎的jar包一起集成在Java環境里了,如果想使用新版本的JS引擎,可以去對應的JS引擎上找最新版本的jar包或通過maven來引用依賴即可
rhino目前是由火狐瀏覽器團隊開發的,使用Java寫的一個JS引擎,目前也是在更新,如果想要更新,而不想更新JDK的話,可以直接使用maven引入最新的jar包即可
Nashorn之前是oracle團隊在開發,現在看github的話,是有openjdk團隊在維護
而在Android平臺方面,由於平臺對JVM進行了調整,所以預設是不支持的,但是好消息的是,有大神將移植到了Android平臺上,具體可以查看APISENSE/rhino-android,需要的話可以直接引入依賴即可
不過作者寫的使用文檔不太清晰,這裡我比較推薦使用閱讀APP開發者的gedoor/rhino-android,實際上也是基於APISENSE/rhino-android
進行了一定的調整,使用起來和Java內置的步驟是一樣的
可能有同學就有疑惑了,使用這個JS引擎能有什麼作用呢?
這裡就舉個例子,有個加密方法,是通過js去實現的,但是現在如果讓我們想要獲取到加密的結果,得通過閱讀JS源碼,看懂加密思路後再使用Java代碼重現實現,是不是十分的複雜?
但如果採用JS引擎,我們只需要將對應的JS方法代碼拿到,之後我們只需要傳參數,通過JS引擎執行加密過程,即可得到加密後的參數了
PS: 最後,註意一下,上述說到的兩種JS引擎,只支持部分ES6特性,所有,如果你的JS代碼有ES6特性的,可能執行的時候會報錯!
下文以JDK8內置的JS引擎為例,講解一下使用
使用
1.基本使用
首先,我們需要通過ScriptEngineManager
對象獲取JS腳本引擎engine對象,之後通過engine.eval()
方法來執行我們需要的js代碼
// 1、獲得腳本引擎對象,選擇腳本語言
val manager = ScriptEngineManager()
// 亦可以是js縮寫,代表JavaScript腳本語言
val engine = manager.getEngineByName("js")
val result = engine.eval("""
var num = 5+2;
num
""".trimIndent())
println(result)
PS: 如果是
gedoor/rhino-android
,getEngineByName()
方法裡面傳rhino
這個字元串!
2.獲取JS變數數值
比較多的情況就是,我們需要通過JS去執行邏輯,之後得到返回的結果,有以下2種方式獲取數值
- 通過eval()方法的返回值(如上面基本使用的示例代碼),可以理解為在瀏覽器的控制台執行js代碼後的控制台會輸出的數值
- 通過作用域變數
作用域變數的方式代碼如下:
// 1、獲得腳本引擎對象,選擇腳本語言
val manager = ScriptEngineManager()
// 亦可以是js縮寫,代表JavaScript腳本語言
val engine = manager.getEngineByName("js")
//聲明一個變數
engine.put("finalResult","")
//註冊一個js方法
engine.eval("""
function add(a,b){
return a + b
}
""".trimIndent())
//執行獲取結果,賦予finalResult數據
engine.eval("finalResult = add(2,3)")
println(engine["finalResult"])
或者直接在js中聲明變數finalResult
,如下代碼:
// 1、獲得腳本引擎對象,選擇腳本語言
val manager = ScriptEngineManager()
// 亦可以是js縮寫,代表JavaScript腳本語言
val engine = manager.getEngineByName("js")
//註冊一個js方法
engine.eval("""
function add(a,b){
return a + b
}
""".trimIndent())
//執行獲取結果
engine.eval("var finalResult = add(2,3)")
println(engine["finalResult"])
3.JS使用Java類型數值
// 1、獲得腳本引擎對象,選擇腳本語言
val manager = ScriptEngineManager()
// 亦可以是js縮寫,代表JavaScript腳本語言
val engine = manager.getEngineByName("js")
val file = File("D:\\temp\\qrcode.gif")
//將文件的對象設置為JS變數
engine.put("myFile",file)
//註冊一個js方法
engine.eval("""
print(myFile.getPath());
""".trimIndent())
上面js中的print實際上也是Java提供的方法,而myFile則是我們Java中的一個File對象,JS代碼中可以使用這個對象及相應的Java方法
參考
- JAVA使用ScriptEngine 解析腳本_雪_糕的博客-CSDN博客
- JavaScript腳本引擎Rhino_唯有一片炙熱的博客-CSDN博客_rhino引擎
- 初探Java Nashorn腳本引擎_軟體開發隨心記的博客-CSDN博客_nashorn引擎
- mozilla/rhino: Rhino is an open-source implementation of JavaScript written entirely in Java
- openjdk/nashorn: https://openjdk.org/projects/nashorn
- nashorn官方使用文檔API
提問之前,請先看提問須知 點擊右側圖標發起提問 或者加入QQ群一起學習 TornadoFx學習交流群:1071184701