取得領先
VMware 提供培訓和認證,以加速您的進度。
了解更多有一段時間以來,我一直對以客戶為中心、基於 Web 的使用者介面感興趣。這些第四代框架的特點是其基於元件、事件驅動的程式設計模型,並專注於完全駐留在用戶端上的呈現邏輯。以這種方式針對 Web 瀏覽器通常需要使用 JavaScript 或 Flash,這本身就帶來了許多獨特的挑戰。
如果我們可以使用 Java 進行程式設計並自動產生 JavaScript 或 Flash 執行時模組,則可以解決許多這些挑戰。如今,用於實現這一目標的兩個眾所周知的產品分別是 Google Web Toolkit (GWT) 和 Open Laszlo。 兩者都可在 OSI 批准的許可證 下使用,並擁有活躍的社群,以及它們自己獨特的複雜性。 一個考慮因素是它們在多大程度上實現了提供透明的、基於 Java 的開發環境這一目標,該環境針對 Web 瀏覽器部署。 此考慮因素有多個方面,包括 IDE 支援、除錯整合、反射功能、執行時 widget 綁定等。 當使用傳統的 Java 技術(例如 Swing 和 Standard Widget Toolkit (SWT))開發豐富用戶端時,所有這些都是正常的考慮因素。
此部落格文章的目的不是批評 GWT 或 Open Laszlo。 相反,我想探索一個名為 Java2Script Pacemaker (J2S) 的開源 Java 到 JavaScript 編譯器,並展示一個初始的 Spring 整合。 這個有趣的專案並不廣為人知,但它以令人鼓舞的方式解決了透明的 Java 到 JavaScript 開發。 J2S 附帶一個增量編譯器、幾乎完整的 JavaScript 版本的 java.lang、java.io 和 java.util 封裝、一個 JavaScript 版本的 Junit、一個 Eclipse SWT JavaScript 實作以及一個 AJAX 函式庫。 更重要的是,J2S 可以將任何現有的 Java 程式碼轉換為 JavaScript,前提是原始程式碼和依賴項也同樣轉換為 JavaScript。
專注於技術考慮,J2S 目前在幾個廣泛方面與 GWT 區分開來。 第一個是它的編譯器技術,它建立在 Eclipse 抽象語法樹 (AST) 之上,因此需要 Eclipse。 但是,Eclipse JDT Core 支援無頭模式,因此從 Ant 外掛程式或 Maven mojo 執行 J2S 編譯並非難事。 第二個區別是 J2S 提供了全面的執行時反射和 widget 綁定功能。 GWT 更喜歡編譯時 JavaScript 優化,但犧牲了這些執行時服務。 另一方面,J2S 認識到 摩爾定律、改進的瀏覽器 JavaScript 直譯器和 JNI 類的 JavaScript 優化共同為充分的效能提供了空間,同時仍然享受更完整的 JRE 模擬和其他執行時服務。
也許最大的技術差異與使用者介面方法有關。 GWT 提供了自己的 Swing 類 API,該 API 專為 Web 瀏覽器整合而設計。 另一方面,J2S 旨在提供 SWT 的實作。 在 J2S 的方法中,顯而易見有很多優點
通過產生基於 JavaScript 的用戶端,J2S 明顯需要某種形式的 Java 到 JavaScript 的遠端處理。 Java 到 JavaScript 遠端處理實作通常採用非同步方法,這意味著在遠端處理調用後執行會立即繼續,並且有一個單獨的回調來處理收到調用結果時的情況。 Java 到 JavaScript 遠端處理的兩種主要方法是 DWR 和 JSON-RPC,儘管 GWT 和 J2S 都提供它們自己的獨立遠端處理方法。 GWT 和 J2S 方法均未提供現成的 Spring 整合,儘管 Spring 靈活的架構使其非常容易做到(我將在下面的 J2S 範例中向您展示)。
在我們研究 Spring 實作之前,讓我們先回顧一下 J2S AJAX 遠端處理協定是如何運作的。 J2S 為每個潛在的遠端呼叫採用準 命令模式。 SimpleRPCRunnable 超類別提供 JavaScript 到 Java 和 Java 到 JavaScript 的序列化,其中子類別指示遠端 URL、要序列化的欄位以及要遠端執行的邏輯
public class LZ77JSSimpleRPCRunnable extends SimpleRPCRunnable {
private transient SomeServicesLayer servicesLayer; // setter omitted
public String jsContent;
public String result;
public String getHttpURL() {
return "http://localhost:8080/echotest/simplerpc";
}
public void ajaxRun() {
result = servicesLayer.computeTheAnswer(jsContent);
jsContent = null;
}
}
欄位宣告很重要。 每個公共非暫時欄位都將由 SimpleRPCRunnable 序列化。 getHttpURL() 指定 J2S servlet 的 URL。 同一個 URL 可以用於任何 J2S 命令,使其成為您應用程式的 J2S 前端控制器。 ajaxRun() 方法包含將在伺服器端執行的邏輯。 在這種情況下,我們的 ajaxRun() 方法正在存取本地(伺服器端)Spring bean。 請注意,servicesLayer 欄位被宣告為暫時的,這意味著 SimpleRPCRunnable 不會序列化它。 相反,Spring IoC 容器會將 SomeServicesLayer 實例依賴項注入到我們的伺服器端命令物件中。 因此,在 J2S 用戶端上,servicesLayer 始終為 null。 為了讓用戶端非同步調用該命令,他們將使用如下程式碼
SimpleRPCSWTRequest.swtRequest(new LZ77JSSimpleRPCRunnable() {
public void ajaxIn() {
jsContent = sourceText.getText();
}
public void ajaxOut() {
resultText.setText(result);
}
});
如圖所示,ajaxIn() 方法用於在用戶端上將公共欄位設定為可接受的值。 ajaxOut() 方法是非同步回調處理程式,這意味著一旦從伺服器返回並反序列化命令物件,它就會執行。 在這種情況下,該命令正在更新 UI widget。 下面的螢幕截圖顯示了將該命令作為 JVM 託管的 SWT 應用程式執行的結果
在伺服器端,我們沒有使用正常的 J2S SimpleRPCHttpServlet。 相反,我們正在使用一個名為 SpringRpcHttpServlet 的新類別(它作為 ZIP 附件 提供,以及此部落格文章中提到的其餘程式碼)。 SpringRpcHttpServlet 的運作方式與正常的 SimpleRPCHttpServlet 相同,只是它從 Spring 應用程式環境定義中獲取伺服器端命令物件。 該程式碼有很好的說明文檔,因此如果您有興趣了解其詳細工作原理,請查看 ZIP 附件。 從本質上講,它允許您在 Spring 應用程式環境定義檔案中定義命令及其依賴項。
如果您的應用程式需要額外的命令,只需建立一個 SimpleRPCRunnable 子類別,然後將其新增到您的應用程式環境定義即可。 那些關注我在 ROO 方面工作的人可能會感興趣地聽到,我打算提供 J2S 遠端處理整合,從而使您無需編寫命令物件或通過 SimpleRPCSWTRequest 進行調用。
總之,對於需要 JavaScript 編譯或 SWT 的 Web 瀏覽器實作的專案,J2S 承諾了一些有吸引力的好處。 它還可以與 Spring 後端成功互通。 J2S 有意選擇利用經過驗證的現有技術(例如 AST 和 SWT)使其成為重用現有程式碼和開發人員技能的一個很好的範例,進而降低了採用障礙和實質性 API 變更的前景。 如果您認為自己是早期採用者、SWT 擁護者,或者需要建立在成熟的 SWT UI 框架之上的、以客戶為中心、基於 Web 的使用者介面,那麼絕對值得仔細研究 J2S。