TeaVM簡介
1. 概述
TeaVM是將 Java 字節碼翻譯成 JavaScript 的強大工具,使 Java 應用程式能夠直接在瀏覽器中運作。這使我們能夠在針對 Web 環境的同時維護基於 Java 的程式碼庫。
在本教程中,我們將探索如何利用 TeaVM 與 DOM 互動的能力並從 JavaScript 呼叫 Java 方法來彌合 Java 和 JavaScript 之間的差距。
2. TeaVM的主要用途
當我們有複雜的基於 Java 的邏輯時,為 Web 重寫相同的功能是不切實際的。 TeaVM 讓我們能夠有效地將 Java 程式碼編譯為 JavaScript,從而優化最終腳本的大小和效能,從而避免冗餘。
不管怎樣,我們要記住,我們的 Java 程式碼必須符合Java 類別庫 (JCL) 模擬的範圍。例如,不支援 Swing 和 JavaFX。
2.1.單頁應用程式 (SPA)
TeaVM 是幾乎完全使用 Java 和 CSS 從頭開始建立單頁應用程式 (SPA) 的正確解決方案,最大限度地減少了編寫 JavaScript 和 HTML 程式碼的需求。這是因為 TeaVM 具有以下特定於 Web 的功能:
- 直接從 JavaScript 呼叫 Java 方法,我們將在接下來的範例中看到
- 使用
@JSBody
註解建立在 JavaScript 中實作的本機 Java 方法 - 使用JSO 庫透過 Java 操作 Web 元素
然而,TeaVM 並沒有完全取代對 JavaScript 或 HTML 的需求,特別是在佈局和一些特定於瀏覽器的邏輯方面。此外,TeaVM 不處理 CSS,我們必須手動編寫或透過外部框架進行管理。
2.2.現有網站
TeaVM 也非常適合將 Java 編寫的功能新增至使用 WordPress 或 Joomla 等傳統 CMS 開發的現有網站。例如,我們可以為 CMS 建立一個 PHP 插件,透過 REST API 向 TeaVM 公開功能,並在我們網站的頁面上包含由 TeaVM 編譯的 JavaScript。
這樣的腳本利用我們的 REST API,可以將 JSON 轉換為 Java 對象,反之亦然,並執行用 Java 編寫的業務邏輯。它還可以修改 DOM 以建立使用者介面或整合到現有介面中。
當客戶端業務邏輯非常複雜以至於我們對 Java 程式碼比對 JavaScript 更熟悉、更熟練和更熟悉時,這個用例就有意義了。
2.3.其他案例
此外,TeaVM 正在積極開發中支援 WebAssembly,新版本正在開發中,它將允許我們的 JavaScript 目標應用程式以最小的變更移植到 WebAssembly。不過,該功能仍處於實驗階段,尚未準備就緒。
TeaVM 也可以將 Java 轉譯為 C。即使這個功能穩定且可以使用,我們也不會深入討論它,因為它超出了 TeaVM 的主要用途。
3.Maven設定和TeaVM配置
首先, TeaVM 目前的 0.10.x 版本支援最高 JDK 21 的 Java 字節碼,並且至少需要 Java 11才能運行其 Java 到 JavaScript 編譯器。當然,這些要求在以後的版本中可能會發生變化。
我們將使用 Maven 並透過在 Java 類別中以程式設計方式配置 TeaVM 來保持pom.xml
最小化。這種方法允許我們根據透過 Maven 的-Dexec.args
選項傳遞給main(…)
方法的參數動態變更配置。這有助於從同一專案中出於不同目的產生不同的 JavaScript 輸出,同時共用相同的程式碼庫。
如果我們喜歡替代方法,或未使用 Maven,官方TeaVM 入門指南提供了進一步的說明。
3.1. pom.xml
檢查Maven 儲存庫中 TeaVM 的最新版本是什麼後,讓我們新增依賴項:
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-classlib</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-tooling</artifactId>
<version>0.10.2</version>
</dependency>
新增這三個依賴項會自動新增其他 TeaVM 傳遞依賴項。 teavm-core
包含teavm-interop
、 teavm-metaprogramming-api
、重新定位的 ASM 函式庫(用於字節碼操作)、HPPC 和 Rhino(JavaScript 引擎)等函式庫。此外, teavm-classlib
引入了teavm-jso
、 commons-io
、 jzlib
和joda-time
。 teavm-tooling
依賴項還包括commons-io
的重新定位版本。
這些傳遞依賴項提供了基本功能,無需手動新增它們。
3.2. TeaVMRunner.java
這個類別配置TeaVM,我們需要使用Maven的-Dexec.mainClass
選項來指定它:
public class TeaVMRunner {
public static void main(String[] args) throws Exception {
TeaVMTool tool = new TeaVMTool();
tool.setTargetDirectory(new File("target/teavm"));
tool.setTargetFileName("calculator.js");
tool.setMainClass("com.baeldung.teavm.Calculator");
tool.setTargetType(TeaVMTargetType.JAVASCRIPT);
tool.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED);
tool.setDebugInformationGenerated(false);
tool.setIncremental(false);
tool.setObfuscated(true);
tool.generate();
}
}
讓我們仔細看看:
-
setTargetDirectory(…)
→ TeaVM 將放置產生的檔案的輸出目錄 -
setTargetFileName(…)
→ 產生的 JavaScript 檔案的名稱 -
setMainClass(…)
→ 應用程式主類別的完全限定名稱 -
setTargetType(…)
→ JavaScript、WebAssembly 或 C -
setOptimizationLevel(…)
→ADVANCED
等級產生最小的 JavaScript 文件,甚至比FULL
等級還要小 -
setDebugInformationGenerated(…)
→ 僅適用於為 TeaVM Eclipse 外掛程式建立偵錯資訊文件 -
setIncremental(…)
→ 如果啟用,編譯速度更快,但會減少最佳化,因此不建議用於生產 -
setObfuscated(…)
→ 啟用後,它會將生成的 JavaScript 的大小減少兩到三倍,因此在大多數情況下應該首選它
官方指南的工具部分還記錄了其他選項,例如用於生成來源映射。
最需要注意的是,使用**setMainClass(…)
建立一個具有全域作用域的 JavaScript main()
函數,該函數執行 Java main(String[])
的翻譯版本**。稍後我們會看到一個例子。
3.3. HTML 頁面
雖然簡單,但這是如何包含 TeaVM 產生的 Javascript 檔案的完整範例。我們省略了元標記,以針對行動裝置、索引以及與 TeaVM 無關的其他要求進行最佳化:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TeaVM Example</title>
<script type="text/javascript" src="calculator.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// Call JS functions here
});
</script>
</head>
<body>
<h1>TeaVM Example</h1>
<div id="calculator-container"></div>
</body>
</html>
在此範例中, calculator.js
是我們先前在setTargetFileName(…)
中指定的檔案。稍後我們將看到用什麼來代替「 Call JS functions here
」註解。最後, <div id=”calculator-container”></div>
是一個佔位符,我們將使用它來建立範例計算器。
4. 計算器範例
讓我們舉一個簡單的加法例子。
4.1.從 Javascript 呼叫 Java 方法
這是我們先前在setMainClass(…)
中指定的類別:
public class Calculator {
public static void main(String[] args) {
}
@JSExport
public static int sum(int a, int b) {
return a + b;
}
}
TeaVM 中的@JSExport
註解用於使 Java 方法、欄位或類別可供 JavaScript 訪問,從而允許直接從 JavaScript 程式碼呼叫它們。因此,編譯程式碼後,讓我們在範例 HTML 頁面中呼叫sum(…)
函數:
[...]
document.addEventListener('DOMContentLoaded', function() {
// Call JS functions here
let result = sum(51, 72);
console.log("Sum result: " + result);
[...]
這是瀏覽器 JavaScript 控制台的輸出:
Sum result: 123
結果正如預期的那樣。
4.2.基於 Java 的 DOM 操作
現在讓我們實作main(…)
函數。讓我們注意到**document.getElementById(“calculator-container”)
選擇我們之前在範例 HTML 檔案中插入的<div id=”calculator-container”></div>
標籤**:
public static void main(String[] args) {
HTMLDocument document = HTMLDocument.current();
HTMLElement container = document.getElementById("calculator-container");
// Create input fields
HTMLInputElement input1 = (HTMLInputElement) document.createElement("input");
input1.setType("number");
container.appendChild(input1);
HTMLInputElement input2 = (HTMLInputElement) document.createElement("input");
input2.setType("number");
container.appendChild(input2);
// Create a button
HTMLButtonElement button = (HTMLButtonElement) document.createElement("button");
button.appendChild(document.createTextNode("Calculate Sum"));
container.appendChild(button);
// Create a div to display the result
HTMLElement resultDiv = document.createElement("div");
container.appendChild(resultDiv);
// Add click event listener to the button
button.addEventListener("click", (evt) -> {
try {
long num1 = Long.parseLong(input1.getValue());
long num2 = Long.parseLong(input2.getValue());
long sum = num1 + num2;
resultDiv.setTextContent("Result: " + sum);
} catch (NumberFormatException e) {
resultDiv.setTextContent("Please enter valid integer numbers.");
}
});
}
該程式碼是不言自明的。簡而言之,它在網頁中動態建立輸入欄位、按鈕和結果顯示區域,所有這些都使用 Java。此按鈕偵聽單擊事件,檢索在輸入欄位中輸入的數字,計算其總和並顯示結果。如果提供了無效的輸入,則會顯示錯誤訊息。
讓我們記住呼叫main()
函數:
document.addEventListener('DOMContentLoaded', function() {
// Call JS functions here
main();
});
結果如下:
從這樣一個簡單的例子開始,我們可以根據需要修改 DOM 以建立任何佈局,甚至可以藉助 CSS。
5. 結論
在本文中,我們探討了 TeaVM 如何促進 Java 字節碼到 JavaScript 的轉換,從而允許 Java 應用程式直接在 Web 瀏覽器中運行。我們介紹了一些關鍵功能,例如如何從 JavaScript 呼叫 Java 方法、執行基於 Java 的 DOM 操作以及實作簡單的 Web 應用程序,而無需編寫大量 JavaScript 程式碼。透過一個實用的計算器範例,我們示範了使用 TeaVM 連接 Java 和 Web 開發的簡單性。
與往常一樣,完整的原始程式碼可以在 GitHub 上取得。