首頁 > Java > java教程 > JBang,Java 生態系中缺少的腳本工具

JBang,Java 生態系中缺少的腳本工具

Patricia Arquette
發布: 2025-01-05 04:01:39
原創
196 人瀏覽過

Java生態已經有兩個強大的專案管理工具,Maven和Gradle,但缺少一個簡單而強大的腳本工具。
這就是 JBang 發揮作用的地方。
它是一個簡約但功能強大的 Java、Kotlin 和 Groovy 檔案啟動器。
事實上,它允許您像運行腳本一樣輕鬆地運行程式碼。
它還提供許多其他功能,例如依賴管理、模板和 App Store。
讓我們在這篇文章中探索 JBang 及其功能。

設定

jbang 命令列可以使用不同的方法安裝在 Windows、Linux 和 macOS 上,這些方法在此處有詳細記錄。
我們可以透過執行 jbang --version 來驗證安裝。

除此之外,最好為我們最喜歡的 IDE 安裝隨附的 IDE 擴充功能。
此處列出了支援的 IDE 擴充。

JBang 不依賴 JDK 到 JRE,但執行使用 Java 的腳本需要 JDK。
您可以透過執行 jbang jdk install 23 來安裝 JBang,這將安裝 JDK 23。

我們現在準備好要寫我們的第一個腳本。

第一個腳本

讓我們建立一個簡單的腳本來列印「Hello, World!」到控制台。

> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

這將建立一個名為 helloworld.java 的文件,可以使用 jbang helloworld.java 運行。

> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

當您開啟該文件時,您將看到它是一個普通的 Java 文件,帶有 main 方法和特定的第一行。

///usr/bin/env jbang "<pre class="brush:php;toolbar:false">> chmod +x helloworld.java
> ./helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? import static java.lang.System.*; public class helloworld { public static void main(String... args) { out.println("Hello world"); } }

正如我們將看到的,JBang 腳本由三個部分組成:shebang、可選屬性和腳本本身。
我們將在接下來的部分中使用第二部分的一些屬性,但讓我們專注於第一部分。

這部分 ///usr/bin/env jbang "$0" "$@" ;退出$?告訴系統使用 JBang 來執行腳本。
它在 Unix 生態系統中被稱為 shebang,用於指定腳本的解釋器。
我們可以在 Unix 系統(macOS、Linux)上透過執行 chmod x helloworld.java 使腳本可執行,然後執行 ./helloworld.java 來說明這一點。

/// usr/bin/env jbang "<pre class="brush:php;toolbar:false">///usr/bin/env jbang "<pre class="brush:php;toolbar:false">//JAVA 23+
//COMPILE_OPTIONS --enable-preview -source 23
//RUNTIME_OPTIONS --enable-preview
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? //JAVA 23+ //COMPILE_OPTIONS --enable-preview -source 23 //RUNTIME_OPTIONS --enable-preview void main(String... args) { System.out.println("Hello World"); } " "$@" ; exit $? //JAVA 25 //COMPILE_OPTIONS --enable-preview -source 25 //RUNTIME_OPTIONS --enable-preview import java.util.concurrent.Callable; import java.util.concurrent.StructuredTaskScope; import static java.lang.System.*; void main(String... args) { out.println("Hello Java 25"); Callable task1 = () -> { out.println("Task 1" + Thread.currentThread()); return "Task 1"; }; Callable task2 = () -> { out.println("Task 2" + Thread.currentThread()); return 2; }; try ( var scope = new StructuredTaskScope()) { StructuredTaskScope.Subtask subtask1 = scope.fork(task1); StructuredTaskScope.Subtask subtask2 = scope.fork(task2); scope.join(); } catch (Exception e) { e.printStackTrace(); } }

我們現在可以像使用任何 Java 檔案一樣開發腳本。
一旦準備好發布,我們可以將其匯出為不同的格式,如下所示:

  • 一個jar檔:jbang導出可移植的helloworld.java。如果您的腳本使用依賴項,則更建議使用以下命令。
  • A fatjar:包含所有相依性:jbang export fatjar helloworld.java。此方法仍需要在目標機器上安裝JDK/JRE。如果您不想這樣做,更建議使用接下來的命令。
  • 包含 JDK 的 jlink 二進位檔案:jbang export jlink helloworld.java。要執行的二進位檔案是 Unix 上的 helloworld-jlink/bin/helloworld 或 Windows 上的 helloworld-jlink/bin/helloworld.bat。
  • A 原生 imgae:jbang 匯出原生 helloworld.java。這需要安裝 GraalVM。

腳本也可以匯出為 mavenrepo: jbang export mavenrepo helloworld.java

JDK管理

如前一章所示,JBang 可以在您的電腦上安裝 JDK。
您可以使用 jbang jdk list 列出已安裝的 JDK,使用 jbang jdk list --available --show-details 列出可安裝的 JDK,使用 jbang jdk install [version] 安裝新的 JDK。 Jbang 也支援使用 SDKMAN 來管理支援系統上的 JDK。

此外,可以在腳本中指定 JDK 版本。
這是透過將以下行新增至腳本屬性來完成的: //JAVA [version](如果我們想要精確版本)或 //JAVA [version](如果我們至少想要一個特定版本)。
在這種情況下,JBang 將自動安裝所需的 JDK 版本並僅將其用於該腳本,而不更改系統的預設 JDK。

例如,以下腳本使用 Java 25 和一些預覽功能。

> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

沒有「Main」類別的腳本

由於腳本往往是輕量級的,因此最好在沒有類別和 main 方法的情況下編寫它們。
幸運的是,Java 有一個稱為隱式宣告類別和實例主方法的功能(在 Java 23 中仍處於預覽狀態)。
此功能允許在沒有類別和靜態 main 方法的情況下編寫 java 程式和 JBang 腳本。

下面的腳本將被編譯並執行,沒有任何問題。

> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

這是透過向腳本添加以下屬性來實現的。

///usr/bin/env jbang "<pre class="brush:php;toolbar:false">> chmod +x helloworld.java
> ./helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? import static java.lang.System.*; public class helloworld { public static void main(String... args) { out.println("Hello world"); } }

第一行 //JAVA 23 告訴 JBang 使用 Java 23 或更高版本。
第二行和第三行 //COMPILE_OPTIONS --enable-preview -source 23 和 //RUNTIME_OPTIONS --enable-preview 分別啟用編譯和執行時的預覽功能。

一旦功能變得穩定,我們可以刪除這 3 行,腳本仍然可以工作。整齊!

依賴關係

JBang 支援以 Gradle 樣式依賴項的形式為腳本新增依賴項,方法是為每個依賴項新增 //DEPS atrefact-id:atrefact-name:version 行。
例如,要使用 jfiglet 函式庫,我們可以將以下行加入腳本: //DEPS com.github.lalyos:jfiglet:0.0.8.

> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

目錄

JBang 中的目錄允許有效地組織和共享腳本和範本。
此功能對於想要共享常見任務或工作流程的腳本集合的團隊或社群特別有用。
對於想要分發入門程式碼或在不提供原始程式碼的情況下顯示練習結果的教師來說,它也很有用。

目錄是一個名為 jbang-catalog.json 的 JSON 文件,其中包含兩組項目:別名和模板。
別名允許使用簡單的命令從目錄運行腳本,而模板則提供新腳本的起點。
目錄可以是遠端的或本地的,並且可以根據需要添加和使用任意數量的本地或遠端儲存庫。
有趣的是,JBang 在設定過程中創建了一個本地目錄,其中包含一些開箱即用的別名和模板。

JBang 依照下列順序在這些目錄中尋找本機目錄(來源 JBang 文件):

  1. 目前目錄,./jbang-catalog.json
  2. 在./.jbang/jbang-catalog.json中
  3. 在父目錄中,../jbang-catalog.json
  4. 在父級的 .jbang 目錄中,../.jbang/jbang-catalog.json
  5. 並向上遞歸重複步驟3和4到檔案系統的根
  6. 最後一步它將查看 $HOME/.jbang/jbang-catalog.json

JBang 將在許多開源儲存庫(如 GitHub、GitLab、Bitbucket 等)中尋找遠端目錄。
我將在本文中使用 GitHub 作為範例。
若要建立遠端目錄,您需要將 jbang-catalog.json 新增至儲存庫的根資料夾。
然後透過 account/repository_name 引用該目錄。
如果您的儲存庫名為 jbang-catalog,那麼您可以透過帳戶引用它。
因此,例如,如果我的GitHub 帳戶名為yostane,並且我有一個名為curs-java 的儲存庫,其中包含一個名為jbang-catalog.json 的檔案的目錄,我可以透過yostane/cours-java 引用該目錄。此外,如果我在名為 jbang-catalog 的儲存庫中有一個 jbang-catalog.json,那麼我可以透過 yostane/jbang-catalog 或簡單地 yostane 引用它。

> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

以下章節將展示如何使用目錄中的別名和模板。

別名

JBang 中的別名允許從目錄執行腳本。
完整語法是 jbang alias@account/repository [args] 和 jbang alias [args] 分別表示遠端和本地別名。

可以使用以下格式在目錄檔案的別名部分定義別名:

> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

這是我在 DevoxxMA 2024 會議期間使用的目錄。

> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

您可以使用以下命令執行這些別名:

  • jbang palcli@yostane/cours-java 女士
  • jbang palqrest@yostane/cours-java
  • jbang hellojfx@yostane/cours-java

官方JBang GitHub帳號提供了包含許多別名和範本的目錄。
讓我們運行其中的一些:

  • jbang httpd@jbangdev 運行本機網路伺服器。
  • jbang gavsearch@jbangdev [arg] 在 search.maven.org 上搜尋 [arg]。

範本

模板,這是預先定義的腳本,可以用作新腳本的起點。
它們使用以下格式在目錄檔案的範本部分中定義:

///usr/bin/env jbang "<pre class="brush:php;toolbar:false">> chmod +x helloworld.java
> ./helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? import static java.lang.System.*; public class helloworld { public static void main(String... args) { out.println("Hello world"); } }

使用範本時,JBang 會在 file-refs 屬性中建立所有檔案的副本。
當 file-ref 包含 {basename} 時,JBang 會將其替換為正在建立的腳本的名稱。
當檔案引用使用 .qute 副檔名時,JBang 使用 Qute 模板引擎

以下是一些現成可用的範本的範例:

  • 使用 picocli 的 CLI 腳本:jbang init -t cli hellocli.java
  • Quarkus 單檔 REST API:jbang init -t qrest helloqrest.java

我們也可以使用社群共享的網路範本。
例如,此指令建立一個 JUnit 單元測試檔: jbang init -t junit@jbangdev file_to_test.java.
從指令中我們可以找到 jbangdev/jbang-catalog 儲存庫中定義範本的 jbang-catalog.json。

/// usr/bin/env jbang "<pre class="brush:php;toolbar:false">///usr/bin/env jbang "<pre class="brush:php;toolbar:false">//JAVA 23+
//COMPILE_OPTIONS --enable-preview -source 23
//RUNTIME_OPTIONS --enable-preview
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? //JAVA 23+ //COMPILE_OPTIONS --enable-preview -source 23 //RUNTIME_OPTIONS --enable-preview void main(String... args) { System.out.println("Hello World"); } " "$@" ; exit $? //JAVA 25 //COMPILE_OPTIONS --enable-preview -source 25 //RUNTIME_OPTIONS --enable-preview import java.util.concurrent.Callable; import java.util.concurrent.StructuredTaskScope; import static java.lang.System.*; void main(String... args) { out.println("Hello Java 25"); Callable task1 = () -> { out.println("Task 1" + Thread.currentThread()); return "Task 1"; }; Callable task2 = () -> { out.println("Task 2" + Thread.currentThread()); return 2; }; try ( var scope = new StructuredTaskScope()) { StructuredTaskScope.Subtask subtask1 = scope.fork(task1); StructuredTaskScope.Subtask subtask2 = scope.fork(task2); scope.join(); } catch (Exception e) { e.printStackTrace(); } }

應用程式商店

JBang App Store 是一個 Web 應用程序,允許瀏覽索引目錄的別名。
它提供了一種發現和使用各種工具和實用程式的便捷方法,無需複雜的設定或安裝過程。
例如,當我們搜尋 yostane 時,我們應該能夠找到我在不同目錄中定義的不同別名。
下圖顯示了搜尋結果。

JBang, the missing scripting tool of the Java ecosystem

以下是我在App Store瀏覽時發現的一些有趣又好笑的腳本:

  • 考賽。以下是運行腳本的一些範例:
    • jbangowsay@ricksbrown/cowsay MOO!
    • jbangowsay@ricksbrown/cowsay -f Dragon「我是維爾德拉暴風雨!」
  • 尋找類似 grep 的子字串: jbang grep@a-services "hello" 。
  • 從圖像建立 PDF:images2pdf@a-services。以下命令將從兩個影像建立 PDF 檔案:
///usr/bin/env jbang "<pre class="brush:php;toolbar:false">  {
    "catalogs": {},
    "aliases": {
      // aliases
    },
    "templates": {
      // templates
    }
  }
登入後複製
" "$@" ; exit $? //DEPS com.github.lalyos:jfiglet:0.0.9 import com.github.lalyos.jfiglet.FigletFont; public class DependenciesDemo { public static void main(String... args) throws Exception { System.out.println(FigletFont.convertOneLine("JBang is amazing")); } }

當您發布目錄時,它很可能會在 JBang AppStore 下次索引後出現。
這是此處定義的預定 GitHub 操作。

一些具有著名框架的範例

透過 JBang,我們可以建立使用流行框架和函式庫的單文件應用程式。
一些例子包括 Quarkus、picolcli 和 JavaFX。
讓我們在以下部分中探討一些範例。

JavaFX(openjfx)

JavaFX 是一個桌面和 UI 框架。
其官方網站是 openjfx.io,也受到 Gluon 的支持,Gluon 提供了額外的 UI 元件,並為 JavaFX 帶來了行動應用程式支援。
JBang 支援此​​框架,可用於建立單一檔案 JavaFX 應用程式。

以下是使用 JBang 建立的一些 JavaFX 應用程式範例:

  • 基本視窗
  • 更漂亮的例子jbang https://gist.github.com/FDelporte/c69a02c57acc892b4c996a9779d4f830
  • 模板 jbang init -t javafx@yostane hellojfx

誇庫斯

Quarkus 是一個針對 Kubernetes 和無伺服器環境進行最佳化的 Java 框架。
它提供快速啟動時間和低記憶體消耗,使其成為雲端原生應用程式的理想選擇。

感謝 JBang,我們可以創建利用該框架強大功能的單一檔案 Quarkus 應用程式。
以下範例顯示了一個測試字串是否為回文的 REST API。它具有 JSON 解析、日誌記錄並提供 OpenAPI 和 Swagger 文件。

> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

我們可能會注意到腳本中的 //SOURCES PalindromeService.java 行。
它告訴 JBang 在與腳本相同的目錄中尋找名為 PalindromeService.java 的檔案。
這意味著JBang支援多檔案腳本。

您可以使用 jbang palqrest@yostane/cours-java 執行伺服器並使用curl http://localhost:8080/palindrome?input=madam 呼叫端點。

> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

其他語言

JBang 支援執行 Java、Kotlin、JShell 和 Groovy 程式碼。
它甚至可以從 Markdown 檔案運行 Java 程式碼。
以下是如何在不同語言中使用 JBang 的一些範例:

  • Kotlin:您可以使用 jbang init -t hello.kt filename.kt 初始化 Kotlin 腳本。請注意,這與官方 .main.kts Kotlin 腳本不同。事實上,JBang 創建的 Kotlin 腳本可以受益於目錄和 App Store 功能。以下是使用 JBang 建立的 Kotlin 腳本的範例。
> jbang init helloworld.java
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
  • 有趣的事實:JBang 的想法來自針對 Kotlin 生態系統的 kscript。
  • Kotlin 已經具有原生腳本支援(使用 .main.kts 腳本),但似乎缺乏目錄、範本和 App Store 功能。
    • Groovy:使用 jbang init -t hello.groovy filename.groovy 初始化 Groovy 腳本。以下是使用 JBang 建立的 Groovy 腳本的範例。
> jbang helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製
  • JShell:JBang 支援帶有 .jsh 或 .jshell 副檔名的 JShell 腳本以及使用 jbang -c 'System.out.println("Inline Java ☕ yay!")' 的內聯腳本。以下是使用 JBang 建立的 JShell 腳本範例。
///usr/bin/env jbang "<pre class="brush:php;toolbar:false">> chmod +x helloworld.java
> ./helloworld.java
Hello world
登入後複製
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? import static java.lang.System.*; public class helloworld { public static void main(String... args) { out.println("Hello world"); } }
  • 使用 Java 和 JShell 程式碼區塊進行 Markdown:您可以使用 jbang my_markdown.md 直接從 Markdown 檔案執行 Java 和 JShell 程式碼區塊。
/// usr/bin/env jbang "<pre class="brush:php;toolbar:false">///usr/bin/env jbang "<pre class="brush:php;toolbar:false">//JAVA 23+
//COMPILE_OPTIONS --enable-preview -source 23
//RUNTIME_OPTIONS --enable-preview
登入後複製
登入後複製
登入後複製
" "$@" ; exit $? //JAVA 23+ //COMPILE_OPTIONS --enable-preview -source 23 //RUNTIME_OPTIONS --enable-preview void main(String... args) { System.out.println("Hello World"); } " "$@" ; exit $? //JAVA 25 //COMPILE_OPTIONS --enable-preview -source 25 //RUNTIME_OPTIONS --enable-preview import java.util.concurrent.Callable; import java.util.concurrent.StructuredTaskScope; import static java.lang.System.*; void main(String... args) { out.println("Hello Java 25"); Callable task1 = () -> { out.println("Task 1" + Thread.currentThread()); return "Task 1"; }; Callable task2 = () -> { out.println("Task 2" + Thread.currentThread()); return 2; }; try ( var scope = new StructuredTaskScope()) { StructuredTaskScope.Subtask subtask1 = scope.fork(task1); StructuredTaskScope.Subtask subtask2 = scope.fork(task2); scope.join(); } catch (Exception e) { e.printStackTrace(); } }

以上是JBang,Java 生態系中缺少的腳本工具的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板