1 概述

前几天写了两篇关于JFX+IDEA打包跨平台应用的文章,这篇是使用IDEA自带功能打包的,这篇是使用Maven进行打包的,但是效果不太满意,因为从JDK9开始实现模块化,同时JFX部分从JDK中独立出来了,也就是说需要默认JDK不再自带JFX。这意味着外部依赖需要手动处理module-info.java,这是一件非常麻烦的事情。

1.1 不使用Maven

其实不使用Maven也能打包发布跨平台JFX应用,但是没有使用Maven的话,虽然打包出来能直接运行无需jre环境,但是,管理依赖确实麻烦,在使用jlink打包一些外部的jar时,对于一些比较简单的jar还是比较舒服的,参照这里



首先去下载jar,接着生成module-info.java,然后使用jdeps检查依赖,添加对应的jar到路径中,编译生成module-info.java接着更新原来的jar即可。看起来简单,但是笔者碰到了okhttp这种jar,依赖简直环环相扣导致笔者放弃了这种方式。

1.2 使用Maven

使用Maven可以完美解决依赖问题,多亏与强大的pom.xml,几行<dependency>就可以解决依赖问题,但是,还是需要手动处理module-info.java,而且IDEA文档明确表明仅支持Java8的打包为jar:



因此,这篇文章采取一种最简单的方式利用Maven打包发布JFX11应用。

2 新建Maven工程



默认即可,问题不大。

3 添加依赖

<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
</dependencies>

需要再哪个平台在classifier中指定即可。这里是linux与win。mac的话直接“mac”。

同时指定编码与JDK:

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

否则会如此报错:

4 新建Main

新建一个包再新建Main.java,Launcher.java以及Main.fxml:



Main.java:

package com.test;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage; public class Main extends Application {
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/Main.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Hello World");
stage.show();
} public static void main(String[] args) {
launch(args);
}
}

Launcher.java:

package com.test;

public class Launcher {
public static void main(String[] args) {
Main.main(args);
}
}

Main.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?> <AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.2-internal"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.test.Main">
<Label layoutX="228.0" layoutY="185.0" text="Hello World">
<font>
<Font size="25.0"/>
</font>
</Label>
</AnchorPane>

注意getResource中的fxml路径,Main.fxml文件放在resources下,直接通过根路径读取:

getResource("/Main.fxml");

5 添加运行配置

此时应该是没有运行配置的状态,点击Add Configuration:



添加Application:



添加Launcher类作为Main class:



这时候run就没问题了:

6 使用默认Maven打包

虽然现在可以run了,但是,如果直接使用默认的Maven打包的话:



在target下有一个jar,直接右键运行:



会提示no main manifest attribute:



也就是找不到Manifest中入口类。

jar实际上是一个class的压缩包,与zip的区别是jar包含了一个MANIFEST.MF,MANIFEST.MF在META-INF下,一个示例文件如下:



有点类似与键值对的格式,MANIFEST.MF包含了jar文件的内容描述,并在运行时向JVM提供应用程序信息。注意该文件有严格的格式限制,比如第一行不能为空,行与行之间不能存在空行。

一个暴力的解决办法是直接解压jar并修改里面的MANIFEST.MF,添加

Main-Class: com.test.Launcher

但是这样会报找不到Application类的异常:

7 添加新的打包插件

理论上来说,只需要jar包内的相同目录下提供了javafx的jar或者class文件就不会抛出异常了,但是,如果依赖很多需要一个一个添加,这是一个痛苦的过程。

所以,为了优雅地解决这个问题,引入一个叫maven-shade-plugin的插件即可:

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.test.Launcher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

最新版本请到官方github查看,使用时只需要修改:

<mainClass>xxx.xxx.xxx</mainClass>

修改为程序入口类。

8 打包

此时再从右侧栏打包选中Maven,package即可:



但是会有警告:



因为一些class文件重复了,但是也提到了通常来说这是没有危害的并且可以跳过警告,或者修改pom.xml去手动排除某些依赖。

9 运行

直接在IDEA中右键运行或者-jar运行,可以看到没有异常了:



相比起原来自带的Maven打包插件,主要是多了javafx的一些class以及对应平台所需要的一些动态库文件等,比如win上的.dll与linux上的.so文件。



这样一个跨平台的JFX jar包就制作好了,只需

java -jar

即可跨平台运行。

JFX11+Maven+IDEA 发布跨平台应用的完美解决方案的更多相关文章

  1. maven项目引入sqljdbc4 找不到包的完美 解决方案。

    今天碰到了这个问题,解决了,顺便做一下记录.首先来 重现 一下这个问题,maven install报错,说 找不到这个包,但是其实 我已经安装了. 我们 再来 看看 maven本地仓库里面有 什么,这 ...

  2. maven之如何将自己的写的 maven 构件发布到 nexus 私服

    概念:Nexus服务器是一个代码包管理的服务器,可以理解 Nexus 服务器是一个巨大的 Library 仓库.Nexus 可以支持管理的工具包括 Maven , npm 等,对于 JAVA 开发来说 ...

  3. eclipse通过maven远程发布应用到Tomcat

    好久没有写博客了,今天为大家分享一下如何在eclipse通过maven远程发布应用到Tomcat. 一般情况下,我们发布应用到服务器需要现将应用导出成war包,然后连接服务器部署更新,这样是很耗时的, ...

  4. 私有maven库发布及使用流程

    ## 私有maven库发布流程 ### 环境配置 - idea环境下,如果使用内置maven,需要手动生成settings.xml,并关联. - 操作如下 - 生成settings.xml 右键pom ...

  5. 搭建私有maven库发布及使用流程

    一:背景 Apache Maven是当Java技术栈前最流行的项目管理工具,它提供了一系列方便快捷的命令帮助程序员们进行Java工程的开发工作.Maven服务器位于美国,由于出国带宽和众多因素,在国内 ...

  6. maven项目引入sqljdbc4 找不到包的完美 解决方案

    今天碰到了这个问题,解决了,顺便做一下记录.首先来 重现 一下这个问题,maven install报错,说 找不到这个包,但是其实 我已经安装了. 我们 再来 看看 maven本地仓库里面有 什么,这 ...

  7. 使用Ant 和 Maven打包发布命令行程序(转载)

    From:https://www.linux178.com/Java/maven-release.html 用Java写了一个命令行的小程序,使用的Intellij IDE是IDEA13原来一直使用A ...

  8. Taurus.MVC-Java 版本打包上传到Maven中央仓库(详细过程):5、Maven版本发布与后续版本更新(大结局)

    文章目录: Taurus.MVC-Java 版本打包上传到Maven中央仓库(详细过程):1.JIRA账号注册 Taurus.MVC-Java 版本打包上传到Maven中央仓库(详细过程):2.PGP ...

  9. asp.net2.0导出pdf文件完美解决方案【转载】

    asp.net2.0导出pdf文件完美解决方案 作者:清清月儿 PDF简介:PDF(Portable Document Format)文件格式是Adobe公司开发的电子文件格式.这种文件格式与操作系统 ...

随机推荐

  1. python中的enumerate 函数(编号的实现方式)

    enumerate 函数用于遍历序列中的元素以及它们的下标: 默认从0开始,如果想从1开始,可以仿照最后案例 加上逗号,和数字编号 >>> for i,j in enumerate( ...

  2. Flannel和Calico网络插件工作流程对比

    Flannel和Calico网络插件对比   Calico简介 Calico是一个纯三层的网络插件,calico的bgp模式类似于flannel的host-gw Calico方便集成 OpenStac ...

  3. Android中Context样式分析

    目录 1.样式定义以及使用 1.1.默认样式 1.2.样式定义及使用 1.3.当前样式下attr属性的获取 1.4.属性集合的定义与获取 2.Activity中Theme的初始化流程 2.1.系统调用 ...

  4. 《C++ Primer》笔记 第2章 变量和基本类型

    如果你的数值超过了int表示范围,选用long long 如果你需要使用一个不大的整数,那么明确指定它的类型是signed char或者unsigned char 执行浮点数运算选用double 当一 ...

  5. 学习版pytest内核测试平台开发万字长文入门篇

    前言 2021年,测试平台如雨后春笋般冒了出来,我就是其中一员,写了一款pytest内核测试平台,在公司落地.分享出来后,有同学觉得挺不错,希望能开源,本着"公司代码不要传到网上去,以免引起 ...

  6. C# 应用 - 封装类访问 Postgresql 数据库

    引入库类 连接数据库 访问数据库 1)增删改数据库 2)查数据库 数据转换 事务 1. 引入库类 引入 Npgsql.dll using Npgsql; using NpgsqlTypes; 2. 连 ...

  7. 1_JVM与Java体系结构

    目录 JVM与Java体系结构 前言 架构师每天都在思考什么? 为什么要学习JVM Java vs C++ 推荐书籍 Java生态圈 字节码 多语言混合编程 Java发展的重大事件 虚拟机与Java虚 ...

  8. 2019 GDUT Rating Contest III : Problem A. Out of Sorts

    题面: 传送门 A. Out of Sorts Input file: standard input Output file: standard output Time limit: 1 second M ...

  9. PTA 求链式表的表长

    6-1 求链式表的表长 (10 分)   本题要求实现一个函数,求链式表的表长. 函数接口定义: int Length( List L ); 其中List结构定义如下: typedef struct ...

  10. Docker上安装Redis

    Docker可以很方便的进行服务部署和管理,下面我们通过docker来搭建Redis的单机模式.Redis主从复制.Redis哨兵模式.Redis-Cluster模式 一.在Docker上安装单机版R ...