当前位置: 首页 > 知识库问答 >
问题:

如何使用Maven Assembly插件为JavaFX项目创建一体化jar?

罗诚
2023-03-14

我有一个非常简单的Java类,src/main/java/web浏览器/WebBrowser.java

package webbrowser;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.scene.web.WebEngine;
import javafx.stage.Stage;

public class WebBrowser extends Application {

    @Override
    public void start(Stage stage) {
        WebView browser = new WebView();
        WebEngine webEngine = browser.getEngine();
        webEngine.load("http://www.oracle.com");
        Scene scene = new Scene(browser, 1200, 900);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

}

我有一个pom。列出JavaFX依赖项并配置程序集插件的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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>webbrowser</groupId>
    <artifactId>WebBrowser</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>WebBrowser</name>

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

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-web</artifactId>
            <version>18-ea+9</version>         
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>18-ea+9</version>
        </dependency>
    </dependencies>
  
    <build>
        <finalName>WebBrowser</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>                            
                        </execution>
                    </executions>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>
                                    webbrowser.WebBrowser
                                </mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                </plugin>       
            </plugins>
        </pluginManagement>
    </build>  
</project>

当我在命令行上运行mvn clean install assembly:single时,它会显示“构建成功”,并且日志中没有警告或错误。

然后我运行:

% java -jar target/WebBrowser-jar-with-dependencies.jar
Error: JavaFX runtime components are missing, and are required to run this application

出于某种原因,mvn程序集:单个插件没有包含每个JavaFX依赖项。

但是,当我在命令行上运行此命令时,它工作正常并启动应用程序:

% java --module-path $JAVAFX --add-modules javafx.controls,javafx.web -jar target/WebBrowser-jar-with-dependencies.jar

问题

  1. 为什么assembly:single goal没有打包javafx。控件和javafx。包含依赖项的目标/WebBrowser jar中的web依赖项。jar

共有2个答案

吕骞尧
2023-03-14

除了jewelsea的完美答案之外,这里还有一个最简单的gradle方法,它非常有效。。。(对于您使用的操作系统,使用可执行的webbrowser all.jar)

<代码>构建。渐变

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin'  version '0.0.11'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

repositories {
    mavenCentral()
}

application {
    mainClass = 'webbrowser.Launch'
}

javafx {
    modules = [ 'javafx.controls', 'javafx.web']
    version = '18+'
}

shadowJar {
    baseName = 'webbrowser'
    classifier = 'all'
}

添加启动器启动。java

package webbrowser;

import javafx.application.Application;

public class Launch {
public static void main(String[] args) {
    Application.launch(WebBrowser.class, args);
    }
}

还有你的WebBrowser.java

package webbrowser;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class WebBrowser extends Application{

    @Override
    public void start(Stage stage) {
        WebView browser = new WebView();
        WebEngine webEngine = browser.getEngine();
        webEngine.load("http://www.oracle.com");
        Scene scene = new Scene(browser, 1200, 900);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

}
林夕
2023-03-14

建议:更改打包方法

不要尝试为您的应用程序创建单个jar。

以下是打包资源的链接:

  • javafx标记信息

我建议您查看其中的信息,然后为您的应用程序选择并实施适当(且不同)的打包解决方案。

了解错误消息:缺少JavaFX运行时组件

这意味着您的应用程序无法访问JavaFX运行时。JavaFX模块应该在您的模块路径上,如果您将它们放在应用程序jar中,这目前是不可能的。

请参阅Eden编码教程,以了解有关这方面的一些信息和一些基本解决方案(尽管它不包括打包应用程序,因为这是一个非常复杂的主题):

  • 缺少JavaFX运行时组件

来回答你的具体问题

1为什么javafx依赖项不在包含依赖项的jar中。罐子

我复制了您的代码,并在带有OpenJDK 17的Windows计算机上进行了本地尝试。

构建了一个带有依赖项的jar,jar中包含了javafx Windows库。您可以通过在jar文件上运行jar-tvf来看到这一点。它包括JavaFX平台类文件和Windows本机DLL。

但是当罐子建成时,有一条信息消息:

[INFO] module-info.class already added, skipping

这是关键。每个模块化JavaFX jar都有自己的模块信息文件,这是它在模块化环境中运行所必需的。当跳过一些时,模块化就会被破坏,应用程序将不再脱离模块路径运行。

如果Maven程序集插件足够聪明,能够识别依赖项中的模块化jar并在被要求创建具有依赖项的单个jar时明确警告这一点,那就太好了,因为java运行时目前不支持多模块jar。

要了解当前无法将多个Java平台模块放在一个jar中的原因,请参阅:

  • 单个Maven模块中的多个Java 9模块

2创建具有依赖项的jar

您可以从组装插件切换到阴影插件并在以下位置使用该解决方案:

  • 缺少Maven Shade JavaFX运行时组件

但是你不必这样做,如果这是你真正想做的,你可以继续使用汇编插件。

如果您这样做,请了解链接中的警告,即您正在类路径而不是模块路径之外的不受支持的配置中运行JavaFX。

要对部件执行此操作,请执行以下操作:

>

  • 添加一个启动器类来欺骗JavaFX运行时允许它自己从类路径而不是模块路径运行。

    package webbrowser;
    
    public class WebBrowserLauncher {
        public static void main(String[] args) {
            WebBrowser.main(args);
        }
    }
    

    更改为程序集定义的主类以引用新类:

    <mainClass>
        webbrowser.WebBrowserLauncher
    </mainClass>
    

    如果要允许应用在与构建应用不同的操作系统上运行,请将这些平台的依赖项添加到pom.xml.有关所需其他依赖项的示例,请参阅:

    • 缺少Maven Shade JavaFX运行时组件

    我做了更改1

    执行命令和输出:

    java -jar target/WebBrowser-jar-with-dependencies.jar
    Jan 21, 2022 7:59:51 PM com.sun.javafx.application.PlatformImpl startup
    WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @41dc7fe'
    

    存在警告是因为JavaFX是从类路径而不是模块路径加载的。

    将多个jar组装到zip或tar归档中

    Assembly仍然是一个有用的插件,可以在构建过程中使用,但用途不同。

    如果确实想坚持装配方法,可以:

    • 创建一个没有依赖项的jar
    • 使用程序集创建一个lib目录,其中包含您需要支持的平台的依赖项和JavaFX模块
    • 提供一个特定于平台的脚本来启动应用程序,该脚本适当地配置类路径和模块路径,以使用从存档中提取的库依赖项。
      • 这很方便,因为用户可以在命令行中键入完整的命令,尽管这可能比只执行脚本更痛苦

      然后,用户将能够解压缩您的归档文件,并使用您的启动程序脚本来运行应用程序(只要他们预装了适当的JVM)。

      汇编对这一点很好,但jlink或jpackage可能是首选的替代方案,因为这些选项不需要预安装JVM。

      openjfx maven插件在其jlink功能中有一个类似的选项,但包含一个链接的java运行时:

      • 设置后,将创建生成的运行时映像的zip

  •  类似资料:
    • 问题内容: 我已经有一个小的Java项目。我想将其移至Maven,因此我想使用Eclipse创建pom.xml,以便可以从命令提示符下使用pom进行构建。尽管我曾与Ant合作,但我之前从未与Maven合作过。 如何使用Eclipse为我的Java项目创建pom.xml? 问题答案: 您应该使用新的可用m2e插件在Eclipse中进行Maven集成。在该插件的帮助下,您应该创建一个新项目并将源移到该

    • 我有一块帆布。它要求用户从a-Z、a-Z或0-9中绘制一个字符。一旦用户绘制了一个角色(比如a),当前画布对象将保存在画布的arraylist中。另一个空白画布弹出,要求用户绘制B,以此类推。 这些程序运行良好。但是我想创建一个文件,并绘制所有可接受的字符。 我在最后显示的画布下方有一个按钮,单击该按钮时,将从画布的arraylist中提取所有字符,并创建一个文件从中删除。但是怎么做呢?

    • 如何在IntelliJ IDEA中从头开始打开JavaFX Maven项目?由于Java项目和JavaFx项目之间没有区别,我想打开一个包含Maven模块的专用JavaFx项目(从创建项目向导中选择JavaFx)。

    • 第 1 步,创建项目 要创建一个新项目,可以依次点击菜单 【File】→【New...】→【Projects】,你可以创建下列几种项目类型: Qt4 Console Application – 控制台应用程序 Qt4 Gui Application – GUI 应用程序(主要是含有界面布局的类型) C++ Library – C++库 这里我们创建一个基于 Qt4 Gui Application

    • 当我想要在中创建一个新的项目时,当我进入命名项目的阶段时,我会收到以下错误消息: "无法自动设置JavaFX平台。请转到Platform Manager,创建一个非默认JavaSE平台,然后转到JavaFX选项卡,启用JavaFX并填写有效JavaFX SDK和JavaFX运行时的路径。注意:JavaFX SDK可从JavaFX网站下载” 我如何解决这个问题?

    • 本文向大家介绍使用Vert.x Maven插件快速创建项目的方法,包括了使用Vert.x Maven插件快速创建项目的方法的使用技巧和注意事项,需要的朋友参考一下 本文介绍了使用Vert.x Maven插件快速创建项目的方法,分享给大家,具体如下: 文档地址: https://reactiverse.io/vertx-maven-plugin 已有项目添加该插件 在项目 pom.xml 目录,执行