欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
關(guān)于 Java Scripting API 您不知道的 5 件事

 

簡(jiǎn)介: Java? 語(yǔ)言足以滿(mǎn)足您的一些項目的需求,但是腳本語(yǔ)言在性能方面一直表現不佳。Java Scripting API (javax.script) 支持在 Java 程序中調用腳本,反之亦然,通過(guò)本文,您將了解它在這兩方面是如何做到最好的。


您認為您已經(jīng)了解 Java 編程了嗎?事實(shí)上,大多數開(kāi)發(fā)人員只了解 Java 平臺的皮毛,他們只學(xué)習了足以完成手頭工作所需要的知識而已。在本 系列文章 中,Ted Neward 通過(guò)介紹 Java 平臺的核心功能來(lái)說(shuō)明一些不為人所熟知的知識,這些知識甚至可以幫助您解決最棘手的編程問(wèn)題。

現在,許多 Java 開(kāi)發(fā)人員都喜歡在 Java 平臺中使用腳本語(yǔ)言,但是使用編譯到 Java 字節碼中的動(dòng)態(tài)語(yǔ)言有時(shí)是不可行的。在某些情況中,直接編寫(xiě)一個(gè) Java 應用程序的腳本 部分 或者在一個(gè)腳本中調用特定的 Java 對象是更快捷、更高效的方法。

這就是 javax.script 產(chǎn)生的原因了。Java Scripting API 是從 Java 6 開(kāi)始引入的,它填補了便捷的小腳本語(yǔ)言和健壯的 Java 生態(tài)系統之間的鴻溝。通過(guò)使用 Java Scripting API,您就可以在您的 Java 代碼中快速整合幾乎所有的腳本語(yǔ)言,這使您能夠在解決一些很小的問(wèn)題時(shí)有更多可選擇的方法。

1. 使用 jrunscript 執行 JavaScript

每一個(gè)新的 Java 平臺發(fā)布都會(huì )帶來(lái)新的命令行工具集,它們位于 JDK 的 bin 目錄。Java 6 也一樣,其中 jrunscript 便是 Java 平臺工具集中的一個(gè)不小的補充。

設想一個(gè)編寫(xiě)命令行腳本進(jìn)行性能監控的簡(jiǎn)單問(wèn)題。這個(gè)工具將借用 jmap(見(jiàn)本系列文章 前一篇文章 中的介紹),每 5 秒鐘運行一個(gè) Java 進(jìn)程,從而了解進(jìn)程的運行狀況。一般情況下,我們會(huì )使用命令行 shell 腳本來(lái)完成這樣的工作,但是這里的服務(wù)器應用程序部署在一些差別很大的平臺上,包括 Windows? 和 Linux?。系統管理員將會(huì )發(fā)現編寫(xiě)能夠同時(shí)運行在兩個(gè)平臺的 shell 腳本是很痛苦的。通常的做法是編寫(xiě)一個(gè) Windows 批處理文件和一個(gè) UNIX? shell 腳本,同時(shí)保證這兩個(gè)文件同步更新。

但是,任何閱讀過(guò) The Pragmatic Programmer 的人都知道,這嚴重違反了 DRY (Don't Repeat Yourself) 原則,而且會(huì )產(chǎn)生許多缺陷和問(wèn)題。我們真正希望的是編寫(xiě)一種與操作系統無(wú)關(guān)的腳本,它能夠在所有的平臺上運行。

當然,Java 語(yǔ)言是平臺無(wú)關(guān)的,但是這里并不是需要使用 “系統” 語(yǔ)言的情況。我們需要的是一種腳本語(yǔ)言 — 如,JavaScript。

清單 1 顯示的是我們所需要的簡(jiǎn)單 shell 腳本:


清單 1. periodic.js
            while (true)
            {
            echo("Hello, world!");
            }

由于經(jīng)常與 Web 瀏覽器打交道,許多 Java 開(kāi)發(fā)人員已經(jīng)知道了 JavaScript(或 ECMAScript;JavaScript 是由 Netscape 開(kāi)發(fā)的一種 ECMAScript 語(yǔ)言)。問(wèn)題是,系統管理員要如何運行這個(gè)腳本?

當然,解決方法是 JDK 所帶的 jrunscript 實(shí)用程序,如清單 2 所示:


清單 2. jrunscript
            C:\developerWorks\5things-scripting\code\jssrc>jrunscript periodic.js
            Hello, world!
            Hello, world!
            Hello, world!
            Hello, world!
            Hello, world!
            Hello, world!
            Hello, world!
            ...

注意,您也可以使用 for 循環(huán)按照指定的次數來(lái)循環(huán)執行這個(gè)腳本,然后才退出?;旧?,jrunscript 能夠讓您執行 JavaScript 的所有操作。惟一不同的是它的運行環(huán)境不是瀏覽器,所以運行中不會(huì )有 DOM。因此,最頂層的函數和對象稍微有些不同。

因為 Java 6 將 Rhino ECMAScript 引擎作為 JDK 的一部分,jrunscript 可以執行任何傳遞給它的 ECMAScript 代碼,不管是一個(gè)文件(如此處所示)或是在更加交互式的 REPL(“Read-Evaluate-Print-Loop”)shell 環(huán)境。運行 jrunscript 就可以訪(fǎng)問(wèn) REPL shell。


2. 從腳本訪(fǎng)問(wèn) Java 對象

能夠編寫(xiě) JavaScript/ECMAScript 代碼是非常好的,但是我們不希望被迫重新編譯我們在 Java 語(yǔ)言中使用的所有代碼 — 這是違背我們初衷的。幸好,所有使用 Java Scripting API 引擎的代碼都完全能夠訪(fǎng)問(wèn)整個(gè) Java 生態(tài)系統,因為本質(zhì)上一切代碼都還是 Java 字節碼。所以,回到我們之前的問(wèn)題,我們可以在 Java 平臺上使用傳統的 Runtime.exec() 調用來(lái)啟動(dòng)進(jìn)程,如清單 3 所示:


清單 3. Runtime.exec() 啟動(dòng) jmap
            var p = java.lang.Runtime.getRuntime().exec("jmap", [ "-histo", arguments[0] ])
            p.waitFor()
            

數組 arguments 是指向傳遞到這個(gè)函數參數的 ECMAScript 標準內置引用。在最頂層的腳本環(huán)境中,則是傳遞給腳本本身的的參數數組(命令行參數)。所以,在清單 3 中,這個(gè)腳本預期接收一個(gè)參數,該參數包含要映射的 Java 進(jìn)程的 VMID。

除此之外,我們可以利用本身為一個(gè) Java 類(lèi)的 jmap,然后直接調用它的 main() 方法,如清單 4 所示。有了這個(gè)方法,我們不需要 “傳輸” Process 對象的 in/out/err 流。


清單 4. JMap.main()
            var args = [ "-histo", arguments[0] ]
            Packages.sun.tools.jmap.JMap.main(args)
            

Packages 語(yǔ)法是一個(gè) Rhino ECMAScript 標識,它指向已經(jīng) Rhino 內創(chuàng )建的位于核心 java.* 包之外的 Java 包。


3. 從 Java 代碼調用腳本

從腳本調用 Java 對象僅僅完成了一半的工作:Java 腳本環(huán)境也提供了從 Java 代碼調用腳本的功能。這只需要實(shí)例化一個(gè) ScriptEngine 對象,然后加載和評估腳本,如清單 5 所示:


清單 5. Java 平臺的腳本調用
            import java.io.*;
            import javax.script.*;
            public class App
            {
            public static void main(String[] args)
            {
            try
            {
            ScriptEngine engine =
            new ScriptEngineManager().getEngineByName("javascript");
            for (String arg : args)
            {
            FileReader fr = new FileReader(arg);
            engine.eval(fr);
            }
            }
            catch(IOException ioEx)
            {
            ioEx.printStackTrace();
            }
            catch(ScriptException scrEx)
            {
            scrEx.printStackTrace();
            }
            }
            }

eval() 方法也可以直接操作一個(gè) String,所以這個(gè)腳本不一定必須是文件系統的一個(gè)文件 — 它可以來(lái)自于數據庫、用戶(hù)輸入,或者甚至可以基于環(huán)境和用戶(hù)操作在應用程序中生成。


4. 將 Java 對象綁定到腳本空間

僅僅調用一個(gè)腳本還不夠:腳本通常會(huì )與 Java 環(huán)境中創(chuàng )建的對象進(jìn)行交互。這時(shí),Java 主機環(huán)境必須創(chuàng )建一些對象并將它們綁定,這樣腳本就可以很容易找到和使用這些對象。這個(gè)過(guò)程是 ScriptContext 對象的任務(wù),如清單 6 所示:


清單 6. 為腳本綁定對象
            import java.io.*;
            import javax.script.*;
            public class App
            {
            public static void main(String[] args)
            {
            try
            {
            ScriptEngine engine =
            new ScriptEngineManager().getEngineByName("javascript");
            for (String arg : args)
            {
            Bindings bindings = new SimpleBindings();
            bindings.put("author", new Person("Ted", "Neward", 39));
            bindings.put("title", "5 Things You Didn't Know");
            FileReader fr = new FileReader(arg);
            engine.eval(fr, bindings);
            }
            }
            catch(IOException ioEx)
            {
            ioEx.printStackTrace();
            }
            catch(ScriptException scrEx)
            {
            scrEx.printStackTrace();
            }
            }
            }

訪(fǎng)問(wèn)所綁定的對象很簡(jiǎn)單 — 所綁定對象的名稱(chēng)是作為全局命名空間引入到腳本的,所以在 Rhino 中使用 Person 很簡(jiǎn)單,如清單 7 所示:


清單 7. 是誰(shuí)撰寫(xiě)了本文?
            println("Hello from inside scripting!")
            println("author.firstName = " + author.firstName)
            

您可以看到,JavaBeans 樣式的屬性被簡(jiǎn)化為使用名稱(chēng)直接訪(fǎng)問(wèn),這就好像它們是字段一樣。


5. 編譯頻繁使用的腳本

腳本語(yǔ)言的缺點(diǎn)一直存在于性能方面。其中的原因是,大多數情況下腳本語(yǔ)言是 “即時(shí)” 解譯的,因而它在執行時(shí)會(huì )損失一些解析和驗證文本的時(shí)間和 CPU 周期。運行在 JVM 的許多腳本語(yǔ)言最終會(huì )將接收的代碼轉換為 Java 字節碼,至少在腳本被第一次解析和驗證時(shí)進(jìn)行轉換;在 Java 程序關(guān)閉時(shí),這些即時(shí)編譯的代碼會(huì )消失。將頻繁使用的腳本保持為字節碼形式可以幫助提升可觀(guān)的性能。

我們可以以一種很自然和有意義的方法使用 Java Scripting API。如果返回的 ScriptEngine 實(shí)現了 Compilable 接口,那么這個(gè)接口所編譯的方法可用于將腳本(以一個(gè) String 或一個(gè) Reader 傳遞過(guò)來(lái)的)編譯為一個(gè) CompiledScript 實(shí)例,然后它可用于在 eval() 方法中使用不同的綁定重復地處理編譯后的代碼,如清單 8 所示:


清單 8. 編譯解譯后的代碼
            import java.io.*;
            import javax.script.*;
            public class App
            {
            public static void main(String[] args)
            {
            try
            {
            ScriptEngine engine =
            new ScriptEngineManager().getEngineByName("javascript");
            for (String arg : args)
            {
            Bindings bindings = new SimpleBindings();
            bindings.put("author", new Person("Ted", "Neward", 39));
            bindings.put("title", "5 Things You Didn't Know");
            FileReader fr = new FileReader(arg);
            if (engine instanceof Compilable)
            {
            System.out.println("Compiling....");
            Compilable compEngine = (Compilable)engine;
            CompiledScript cs = compEngine.compile(fr);
            cs.eval(bindings);
            }
            else
            engine.eval(fr, bindings);
            }
            }
            catch(IOException ioEx)
            {
            ioEx.printStackTrace();
            }
            catch(ScriptException scrEx)
            {
            scrEx.printStackTrace();
            }
            }
            }

在大多數情況中,CompiledScript 實(shí)例需要存儲在一個(gè)長(cháng)時(shí)間存儲中(例如,servlet-context),這樣才能避免一次次地重復編譯相同的腳本。然而,如果腳本發(fā)生變化,您就需要創(chuàng )建一個(gè)新的 CompiledScript 來(lái)反映這個(gè)變化;一旦編譯完成,CompiledScript 就不再執行原始的腳本文件內容。


結束語(yǔ)

Java Scripting API 在擴展 Java 程序的范圍和功能方面前進(jìn)了很大一步,并且它將腳本語(yǔ)言的編碼效率的優(yōu)勢帶到 Java 環(huán)境。jrunscript — 它顯然不是很難編寫(xiě)的程序 — 以及 javax.script 給 Java 開(kāi)發(fā)人員帶來(lái)了諸如 Ruby (JRuby) 和 ECMAScript (Rhino) 等腳本語(yǔ)言的優(yōu)勢,同時(shí)還不會(huì )破壞 Java 環(huán)境的生態(tài)系統和可擴展性。

請繼續閱讀下一篇文章 5 件事 系列文章:JDBC。


參考資料

學(xué)習


本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
走近WSH
腳本語(yǔ)言
IBM developerWorks 中國 : developerWorks 中國:Java 平臺腳本語(yǔ)言支持
2020年Java發(fā)展前景與職業(yè)方向解析
使用JavaScript調用手機平臺上的原生API
python命令常用參數
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久