JFX11+IDEA跨平台打包发布的完美解决办法
1 概述
IDEA 2020.1的文档中提到只有JFX8
的工程才支持打成JAR
包,并且,如果直接使用Build Artifacts
的话,会如下提示:
IDEA文档有提到这个的解决办法,是使用一些第三方工具。里面介绍了通过IDEA结合自身/Maven
/Gradle
打包发布JFX11
以上版本的方法。但是,不足的地方有:
- 直接创建
JFX
工程默认只有一个src
目录,不像Maven
工程还带有resources
与test
,给管理资源文件以及外部依赖造成了困难,getClass().getResource()
会出现空指针问题,但是好处是只需具备JDK
环境,打包出来的文件能带上jmods
能跨平台直接运行 - 直接创建
Maven
项目虽然是管理依赖以及资源文件方便,但是无论是直接通过Maven
打出的JAR
包还是通过JavaFX Maven Plugins
打出来的JAR
包默认绑定了开发平台的JFX SDK
,简单地说就是Linux
开发的JFX
程序不能直接跑在具有JDK
环境的Win
上,因为用的是Linux
的JFX SDK
而不是Win
的JFX SDK
因此,本文结合这两者的优点,参照Maven
的目录管理,以JFX
工程为基础,记录了从新建工程到发布跨平台JFX
应用的过程。
2 环境
- IDEA 2020.1
OpenJDK 11
OpenJFX 11 Linux SDK
OpenJFX 11 Linux/Windows/Mac OS X jmods
JDK
安装就不说了,JFX
直接下载然后在工程中通过外部库引入即可,三种jmods
解压出来即可,用于最后生成可执行文件时添加的模块。
3 新建JFX
工程
这里的项目名为TestJFX
,对应修改即可。
4 添加JFX11 SDK
添加上一步下载的对应平台的JFX SDK
。
5 添加module-info.java
在src
目录右键New->module-info.java
,修改如下:
module TestJFX {
requires javafx.fxml;
requires javafx.controls;
opens sample to javafx.fxml;
exports sample;
}
其中TestJFX
为新建项目时的项目名,这个创建module-info.java
时就默认加上了,sample
为默认包,对应修改。
6 添加VM Options
添加
--module-path /usr/local/jfx/lib:out/production
其中
/usr/local/jfx/lib
为下载的JFX JDK
的lib
目录,后面的out
不需要更改,是默认的编译输出的目录。
7 运行
这时候应该可以Shift+F10或者点击绿色小三角运行了:
当然内容是空的,因为什么也没有加。
8 添加资源文件
默认的fxml
是放在与Main
类同一目录下的,getResource()
也没有加路径直接写上文件名:
但是这是src
文件夹,放个fxml
还勉强可以接受,放张图片总不合适吧?所以,新建一个资源文件夹,把css,fxml什么的都放里面:
直接在IDEA中移动fxml
文件,Main
中的引用路径也自动更改,不得不说这个特性是真的好用,但遗憾的是,抛出了空指针异常。
因此采取绝对路径来进行读取文件,通过URL
+System.getProperty()
指定绝对路径:
@Override
public void start(Stage primaryStage) throws Exception{
String path = System.getProperty("user.dir");
URL fxmlUrl = new URL("file:"+path+"/resources/fxml/sample.fxml");
Parent root = FXMLLoader.load(fxmlUrl);
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root);
scene.getStylesheets().add(new URL("file:"+path+"/resources/css/1.css").toString());
primaryStage.setScene(scene);
primaryStage.show();
}
其中
System.getProperty("user.dir")
获取项目路径,注意URL前面要加上file:
,css的获取也同理,只不过是需要转换为String
。
9 外部依赖
由于没有了Maven
管理依赖,所以外部依赖的管理会相对麻烦一点,基本上是以JAR
包的形式手动添加,这里以添加Gson
为例,下载JAR
包后,然后在项目目录下新建一个lib
文件夹,把JAR
包放进去:
接着在项目结构中把整个lib
文件夹添加到外部库:
然后VM Options
中添加lib
路径,在上面的VM Options
后面加一个冒号和lib
就行:
但是,此时可以IDEA还不能进行补全,最后需要修改module-info.java
:
加一行requires
,此时IDEA能够进行补全了,每个JAR
包都不同,对应修改即可。
10 制作跨平台镜像
运行没问题之后就可以制作运行时镜像发布了,终端进入项目根路径:
jlink --module-path jmod/linux:out/production:lib --add-modules TestJFX --output linux
linux/bin/java -m TestJFX/sample.Main
其中
jmod/linux
为开发平台jmod
的路径,可以是绝对路径,也可以是相对与项目根目录的相对路径,out/production
与上面的VM Options
保持一致。
--add-modules
后面跟的是模块名,这是在生成module-info.java
时指定的,为项目名。
--output
为输出目录。
后一条命令中-m
指定模块名,后面跟包名+主类名。
这样Linux
平台的镜像就制作好了,Mac
与Win
的同理,只需要把jmod
换成对应平台的jmod
即可,但是注意语法有一些差别,Mac
的语法同Linux
,只需要把jmod
路径换一下,但是注意需要整个工程在对应的平台进行jlink
:
jlink --module-path xxxxx/{MAC_JMOD}:out/production:lib --add-modules TestJFX --output mac
mac/bin/java -m TestJFX/sample.Main
Win
的语法有些区别,一样需要在Win
下进行jlink
:
jlink --module-path "xxxxx/{WIN_JMOD};out/production" --add-modules TestJFX --output win
win\bin\java -m TestJFX/sample.Main
下面是Win
下的截图: