最近接手與 Java FX 相關的專案
以下是編譯該專案的一些筆記
專案架構
專案資料夾架構如下
│ .classpath
│ .project
│ pom.xml
│
├─src
│ └─main
│ ├─java
│ │ │ Main.java
│ │ │
│ │ └─com
│ │ └─example
│ │ └─fxtest
│ │ App.java
│ └─resources
└─target
App.java
繼承
javafx.application.Application
;Main.java
則是專案的 main class
pom.xml
為了方便,只留和 Java FX 、mvn package 相關的內容
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies><build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${version.maven-jar-plugin}</version>
<configuration>
<archive>
<manifest><mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>Main</mainClass>
</configuration>
</execution>
</executions>
</plugin></plugins>
</build>
</project>
錯誤: 遺漏執行此應用程式所需的 JavaFX 程式實際執行元件
我專案編譯時(mvn package
),生出來的 .jar
檔執行時會出現
錯誤: 遺漏執行此應用程式所需的 JavaFX 程式實際執行元件
這問題是因為 JavaFX 的 libraries 不在 .jar 檔之中。
要修正的話,可以在 pom 把
org.apache.maven.plugins:maven-jar-plugin
改成
org.apache.maven.plugins:maven-shade-plugin
來解決。
maven-shade-plugin 能將所有使用到的 libraries 都加入至編譯好的 .jar ,這樣就不會出現 .jar 不包含 JavaFX 相關 libraries 的問題了。
maven-shade-plugin
plugin 的內容
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
更改後的 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven Shade Plugin for creating a fat JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>Main</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
建立安裝檔
若今天我是 java14(含)以上,可以使用 JDK 內建的 jpackage 來處理。
在那之前,需要先修改 pom,將自己專案所引用的 libraries 都複製到 target
複製 libraries
首先加上以下 plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<outputDirectory>
的值是 libraries 的 .jar
檔複製的位置。可以根據自己的需求修改。我這邊是複製到專案的 target
資料夾。
增加完 plugin 後,執行 mvn clean package
,target
資料夾除了先前專案的 jar外,還會多其他的 libraries 的 jar 檔。
jpackage
確認有複製libraries後,以我的專案為例,執行以下指令:
cd 專案資料夾
jpackage --name FXText --input target --main-jar myapp.jar --main-class Main --type msi
註:因為我的 main class 在 default package 資料夾,所以
--main-class
直接為 Main
就會在專案資料夾出現 FXText.msi 了。
Can not find WiX tools
jpackage 執行時,可能出現以下錯誤
[09:26:34.180] Can not find WiX tools (light.exe, candle.exe)
[09:26:34.180] Download WiX 3.0 or later from https://wixtoolset.org and add it to the PATH.
Error: Invalid or unsupported type: [exe]
雖然 log 建議你去 wixtoolset,但 wixtoolset 官網給的說明不會幫你下載 light.exe, candle.exe,而是直接安裝一個 wix.exe。
要下載 light.exe, candle.exe,建議直接去 wixtoolset的 github下載。
現在我去的時候,最新的版本是 WiX Toolset v3.14.1,進去後,下載 wix314-binaries.zip, 將之解壓縮,並把解壓縮後的位置加入 PATH 環境變數。
之後重新執行 jpackage 指令,應該就可以編譯了。
使用 pom plugin 來建置安裝檔
jpackage 的動作也可以加入至 pom 之中。
在 pom 加上以下 plugin:
plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/jpackage</executable>
<arguments>
<!-- 以下參數都和先前的 jpackage 相同 -->
<argument>--name</argument>
<argument>FXText</argument>
<argument>--input</argument>
<argument>target</argument>
<argument>--main-jar</argument>
<argument>myapp.jar</argument>
<argument>--main-class</argument>
<argument>Main</argument>
<argument>--type</argument>
<argument>exe</argument> <!-- 根據需求,也可以換成 msi -->
</arguments>
</configuration>
</execution>
</executions>
</plugin>
如此一來,執行 mvn package
就能夠生成 FXText.exe 了
指定 Java 版本
jpackage 是 Java 14 才有的。
若我希望可以測試時,可以直接用 Java 11 編譯,但是最終要出正式版時,才用到 Java 14 的 jpackage,可以把 exec-maven-plugin plugin 放在單獨的 profile:
profile
<profiles>
<profile>
<id>package</id>
<activation>
<jdk>[14</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/jpackage</executable>
<arguments>
<argument>--name</argument>
<argument>FXText</argument>
<argument>--input</argument>
<argument>target</argument>
<argument>--main-jar</argument>
<argument>myapp.jar</argument>
<argument>--main-class</argument>
<argument>Main</argument>
<argument>--type</argument>
<argument>msi</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
這樣子,若使用 java 11 來編譯,就不會處理 jpackage;java 14 (含)以上才會
pom
最終我的 pom 如下
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- package 時,讓所有 libraries 都加入 .jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- mvn javafx:run 可以直接執行專案 -->
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>Main</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<!-- 複製所有的 library jar files 至 ${project.build.directory} -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<!--
使用 java14(含)以上進行 mvn package 時,自動生成安裝用的 msi 檔
如果專案本身就已經確定要使用 java14(含)以上的話,直接把這 profile 的 plugin 放在 project > build > plugins 就可以了
-->
<profile>
<id>package</id>
<activation>
<jdk>[14</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/jpackage</executable>
<arguments>
<argument>--name</argument>
<argument>FXText</argument>
<argument>--input</argument>
<argument>target</argument>
<argument>--main-jar</argument>
<argument>myapp.jar</argument>
<argument>--main-class</argument>
<argument>Main</argument>
<argument>--type</argument>
<argument>msi</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
沒有留言:
張貼留言