前面幾篇已經把 JavaFX 的畫面、FXML 的事件、以及 ABCL 的計算邏輯接起來。這一篇不再寫新功能或調整架構,要準備把已經能跑的程式整理成可交付的 JAR 檔案。
核心重點:
calculator.lisp
class/ 後,再用 jar 包成 JAR
java -jar <JAR檔案>執行,而不需要知道主類別名稱
前一篇已經把 Java 類別編譯好了,而且把 res/ 下的資源也複製進了 class/。現在,目錄看起來大概會是這樣:
CalcFX/
├── class/
│ ├── CalcFX/
│ │ ├── CalcFX.class
│ │ ├── CalcFXController.class
│ └── res/
│ ├── CalcFX.fxml
│ ├── calc.css
│ └── calculator.lisp
├── src/
│ └── CalcFX/
│ ├── CalcFX.java
│ └── CalcFXController.java
├── res/
│ ├── CalcFX.fxml
│ ├── calc.css
│ └── calculator.lisp
└── ...
基本上,class/ 已經是「可執行的成果物」了。裡面除了編譯好的 Java 類別,也有 FXML、CSS、Lisp 等資源副本,程式執行時會直接從這個目錄取資源。這也是後面打包 JAR 的核心。
只要 class/ 產出了,我們就可以用 jar 將它封裝起來:
jar --create --file CalcFX.jar -C class .
這個命令會把 class/ 下的所有東西都塞進 CalcFX.jar,也就是說,CalcFX.class、CalcFXController.class,以及 FXML 和 Lisp 資源檔案都會被放進去。
不過使用者不能直接使用 java -jar CalcFX.jar 執行它。最起碼要知道主類別:java -cp CalcFX.jar CalcFX.CalcFX。
注意:因為依賴 ABCL 和 JavaFX,上面這種直接執行依然會失敗。
要讓 JAR 更像「可執行程式」,就需要設定 Main-Class。可以先建立一個 manifest.txt,放進 Main-Class 設定:
Main-Class: CalcFX.CalcFX
在用jar指令打包一次class資料夾(指定--manifest):
jar --create --file CalcFX.jar --manifest manifest.txt -C class .
這樣一來,當你執行:
java -jar CalcFX.jar
JVM 就知道要先啟動 CalcFX.CalcFX 這個類別。
不過 CalcFX 有使用到其他依賴,所以直接這樣執行仍然會失敗。在使用 java -jar 執行時,依然需要提供 JavaFX 和 ABCL 的 SDK 模組路徑,完整命令如下:
SDK_PATH="<JavaFX的SDK路徑>"
CLASSPATH="<abcl.jar檔案位置>:<abcl-contrib.jar檔案位置>"
java -cp "${CLASSPATH}" --module-path "${SDK_PATH}" --add-modules javafx.controls,javafx.fxml -jar CalcFX.jar
在較新版本的 ABCL,同樣可以使用 --module-path 的方式去使用 ABCL 模組(--add-modules 增加 abcl):
SDK_PATH="<JavaFX的SDK路徑>:<abcl.jar和abcl-contrib.jar檔案所在目錄>"
java --module-path "${SDK_PATH}" --add-modules javafx.controls,javafx.fxml,abcl -jar CalcFX.jar
class/
jar 打包成 JAR對於 JAR 的分發方式還有一些缺陷,最明顯的就是使用者在執行時,仍然需要知道怎麼提供 JavaFX 和 ABCL。下一部分將會用 jpackage 和 jlink 兩種方式,把 JRE 環境打包起來,讓使用者在使用時不需要在意相關細節。