如何将 JavaFX SDK 直接捆绑在输出 jar 中?
How to bundle the JavaFX SDK directly in the output jar?
目前我在启动我的程序时使用 JVM 参数来查找 JavaFX 库,如下所示:
java -javaagent:lib/aspectjweaver-1.9.5.jar -javaagent:lib/spring-instrument-5.2.3.RELEASE.jar --module-path lib/javafx-sdk-13.0.2/lib --add-modules=javafx.controls -jar target/Some_Service-1.0.jar
我的 POM.xml 的插件部分非常简单。除了 Docker 和 Launch4j 插件,我只有这个:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
有没有办法告诉 Maven 将整个 lib 目录(其中包含 JavaFX 库和 aspectJ/spring 工具 java 代理)捆绑在 jar 中?这样做可以解决在我部署应用程序的任何地方都必须携带该 lib 文件夹的问题!谢谢!
******编辑******
我弄乱了 spring boot maven 插件选项,不幸的是我的 jar 仍然不包含我的文件夹:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<folders>
<folder>lib</folder>
</folders>
<agent>lib/aspectjweaver-1.9.5.jar</agent>
<agent>lib/spring-instrument-5.2.3.RELEASE.jar</agent>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
******编辑 2******
我刚刚找到了一个很棒的库,它让您在运行时以编程方式加载它们,从而完全消除了对 -javaagent 参数的需要。看起来 AspectJ 和 Spring-Instrument 在我的类路径上的存在也是它所需要的!检查一下:https://github.com/subes/invesdwin-instrument.
我现在需要的是以某种方式将 JavaFX 运行时捆绑到我的 jar 中,而不是使用命令行参数从外部引用它。
警告: 因为 fat/uber JAR 可能会导致 JavaFX 被放置在 class-路径,注意这个方法is not supported.
不使用 JavaFX SDK,而是在 pom.xml
文件中声明对 JavaFX 的依赖。然后你可以使用 maven-shade-plugin 创建一个可执行的 fat/uber JAR。从 Maven Central 下载的适当 JavaFX JAR(例如图形 JAR 文件)嵌入了需要的、特定于平台的 本机代码,这些代码将在运行时提取(例如给用户主目录)。
这是一个最小的例子:
Launcher.java:
package com.example;
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
Application.launch(App.class, args);
}
}
App.java:
package com.example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane(new Label("Hello, World!"));
primaryStage.setScene(new Scene(root, 500, 300));
primaryStage.show();
}
}
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>javafx-uber-jar</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>13</release>
</configuration>
</plugin>
<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.example.Launcher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>13.0.2</version>
</dependency>
</dependencies>
</project>
命令行:
mvn package
以上将创建一个平台特定 uber JAR。有关如何创建跨平台超级 JAR 的想法,请参阅 。
根据您用于开发应用程序的 Java 版本,您可以查看 jlink
(Java 9+) and/or jpackage
(Java 14,抢先体验)作为创建 fat/uber JAR 文件的替代方法。如果您使用其中之一,请考虑使用 files of JavaFX (can be found here),因为它配置自定义图像以更好地处理本机代码(即不提取)。
请注意,主要 class 不是 Application
的子 class。这对于将 JavaFX 库放在 class 路径 上的应用程序是强制性的,至少对于 JavaFX 9-13。此要求的原因与允许 JavaFX 应用程序没有 main 方法的实现有关;如果 javafx.graphics
模块不在 模块路径 上,则假定“JavaFX 组件丢失”。但这只有在主要 class 和 Application
class 相同时才会发生,因此上述解决方法。
目前我在启动我的程序时使用 JVM 参数来查找 JavaFX 库,如下所示:
java -javaagent:lib/aspectjweaver-1.9.5.jar -javaagent:lib/spring-instrument-5.2.3.RELEASE.jar --module-path lib/javafx-sdk-13.0.2/lib --add-modules=javafx.controls -jar target/Some_Service-1.0.jar
我的 POM.xml 的插件部分非常简单。除了 Docker 和 Launch4j 插件,我只有这个:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
有没有办法告诉 Maven 将整个 lib 目录(其中包含 JavaFX 库和 aspectJ/spring 工具 java 代理)捆绑在 jar 中?这样做可以解决在我部署应用程序的任何地方都必须携带该 lib 文件夹的问题!谢谢!
******编辑******
我弄乱了 spring boot maven 插件选项,不幸的是我的 jar 仍然不包含我的文件夹:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<folders>
<folder>lib</folder>
</folders>
<agent>lib/aspectjweaver-1.9.5.jar</agent>
<agent>lib/spring-instrument-5.2.3.RELEASE.jar</agent>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
******编辑 2******
我刚刚找到了一个很棒的库,它让您在运行时以编程方式加载它们,从而完全消除了对 -javaagent 参数的需要。看起来 AspectJ 和 Spring-Instrument 在我的类路径上的存在也是它所需要的!检查一下:https://github.com/subes/invesdwin-instrument.
我现在需要的是以某种方式将 JavaFX 运行时捆绑到我的 jar 中,而不是使用命令行参数从外部引用它。
警告: 因为 fat/uber JAR 可能会导致 JavaFX 被放置在 class-路径,注意这个方法is not supported.
不使用 JavaFX SDK,而是在 pom.xml
文件中声明对 JavaFX 的依赖。然后你可以使用 maven-shade-plugin 创建一个可执行的 fat/uber JAR。从 Maven Central 下载的适当 JavaFX JAR(例如图形 JAR 文件)嵌入了需要的、特定于平台的 本机代码,这些代码将在运行时提取(例如给用户主目录)。
这是一个最小的例子:
Launcher.java:
package com.example;
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
Application.launch(App.class, args);
}
}
App.java:
package com.example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane(new Label("Hello, World!"));
primaryStage.setScene(new Scene(root, 500, 300));
primaryStage.show();
}
}
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>javafx-uber-jar</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>13</release>
</configuration>
</plugin>
<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.example.Launcher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>13.0.2</version>
</dependency>
</dependencies>
</project>
命令行:
mvn package
以上将创建一个平台特定 uber JAR。有关如何创建跨平台超级 JAR 的想法,请参阅
根据您用于开发应用程序的 Java 版本,您可以查看 jlink
(Java 9+) and/or jpackage
(Java 14,抢先体验)作为创建 fat/uber JAR 文件的替代方法。如果您使用其中之一,请考虑使用
请注意,主要 class 不是 Application
的子 class。这对于将 JavaFX 库放在 class 路径 上的应用程序是强制性的,至少对于 JavaFX 9-13。此要求的原因与允许 JavaFX 应用程序没有 main 方法的实现有关;如果 javafx.graphics
模块不在 模块路径 上,则假定“JavaFX 组件丢失”。但这只有在主要 class 和 Application
class 相同时才会发生,因此上述解决方法。