spring-boot - 浏览器 HEAVYWEIGHT 在场景中不可见
问题描述
我正在尝试将 JXBrowser 嵌入到使用 Java11 运行的 SpringBoot JavaFX 应用程序中。我的问题是当我从创建的可执行 jar 运行应用程序时,浏览器没有显示在场景中。浏览器已加载,提供有关已加载网站的反馈,并且已经是场景的一部分,但不可见。在 IntelliJ 中运行或使用 Maven exec 目前正在运行。当我将浏览器模块切换到 LIGHTWEIGHT 时,这三种运行可能性都运行良好。在 HEAVYWEIGHT mod 中从 jar 运行有什么问题?
我的系统:Windows10-64、Java11、SpringBoot 2.1.0.RELEASE、JXBrowser 6.21、OpenJFX 11
主类
@Slf4j
@SpringBootApplication
public class Main extends Application
{
private ConfigurableApplicationContext springContext;
public static void main(final String[] args)
{
Application.launch(args);
}
@Override
public void init()
{
springContext = SpringApplication.run(Main.class);
springContext.getAutowireCapableBeanFactory().autowireBean(this);
}
@Override
public void start(Stage stage)
{
final Browser browser = new Browser();
stage.setScene(new Scene(new BrowserView(browser)));
stage.show();
browser.loadURL("http://www.google.de");
}
@Override
public void stop()
{
springContext.close();
}
}
开始主类
public class StartMain
{
public static void main(String[] args)
{
Main.main(args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>de</groupId>
<artifactId>app</artifactId>
<version>1.0.10-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<jxbrowser.version>6.21</jxbrowser.version>
<javafx.version>11</javafx.version>
</properties>
<repositories>
<repository>
<id>com.teamdev</id>
<url>http://maven.teamdev.com/repository/products</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.teamdev.jxbrowser</groupId>
<artifactId>jxbrowser-cross-platform</artifactId>
<type>pom</type>
<version>${jxbrowser.version}</version>
</dependency>
<dependency>
<groupId>com.teamdev.jxbrowser</groupId>
<artifactId>jxbrowser-win64</artifactId>
<version>${jxbrowser.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${javafx.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
<mainClass>...StartMain</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>build-info</goal>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
解决方案
我已经设法构建了该项目,并获得了可以运行它的试用许可证。正如您所提到的,从 IDE 或命令行运行mvn compile exec:exec
(我也尝试过使用 Gradle,./gradlew run
添加所需的--add-exports)工作得非常好,显示浏览器并加载给定的 URL。
但是,正如您所说,如果您创建一个胖 jar 并运行它,它不会显示浏览器,但 JavaFX 可以工作,您可以看到一些活动正在进行,只是没有渲染。
我在 JDK 8、9、10 和 11 下都试过了。只有在 8 下我才能得到 fat jar 来显示浏览器。
一般来说,使用胖 jar 是一种不好的做法,现在更糟糕的是,您必须包含 JavaFX SDK 中的 JavaFX 类。
分发应用程序的更好方法是使用jlink。
鉴于这com.teamdev.jxbrowser:jxbrowser
不是模块化的,您不能完全使用jlink
您的项目,但您可以仅使用 JavaFX 模块创建自定义运行时映像,并使用它来运行您的应用程序,唯一的依赖项是jxBrowser
(为了方便,我没有使用弹簧启动)。
因此,如果您从此处下载 JavaFX jmod ,请解压缩并运行:
export PATH_TO_FX_MODS=/path-to/javafx-jmods-11
$JAVA_HOME/bin/jlink --module-path $PATH_TO_FX_MODS \
--add-modules=java.se,javafx.web,javafx.fxml,javafx.swing \
--output jre
您将创建一个包含 JavaFX 的 JRE。
然后您可以运行您的项目,包括类路径中的依赖项:
jre/bin/java -cp \
/Users/<user>/.gradle/caches/modules-2/files-2.1/com.teamdev.jxbrowser/jxbrowser/6.22/c9...6b/jxbrowser-6.22.jar:\
/Users/<user>/.gradle/caches/modules-2/files-2.1/com.teamdev.jxbrowser/jxbrowser-mac/6.22/fa...d4/jxbrowser-mac-6.22.jar:\
build/libs/browserApp.jar jxbrowser.BrowserApp
这也可以正常工作,显示浏览器。因此,我们放弃 JavaFX 11 可能存在的任何问题。
现在我们仍然可以用项目和 jxBrowser 依赖项做一个小胖 jar 。然后如果你运行:
jre/bin/java -cp build/libs/browserApp.jar jxbrowser.BrowserApp
可以想象,这不起作用,浏览器不会出现。
所以我的最终结论是,即使只有两个jxBrowser
依赖项,添加一个 fat jar 也是行不通的。
例如,请参阅这篇文章,了解可能的原因:
多个 JAR 中可能存在具有相同路径的文件,默认情况下,shade 插件包含 fat JAR 中的第一个文件并丢弃其余文件。
因此,我建议您向项目问题跟踪器提交问题(如果存在),并且我还建议您找到一种方法来运行您的应用程序而无需使用 fat-jars。
推荐阅读
- laravel-5 - 在 laravel 上使用 eloquent 加入一对多模型
- java - 信令链路选择
- java - BigDecimal 除法方法返回 0 还是 ArithmeticException?
- python - 创建一个 lambda 字典(所有 lambda 都相同)
- string - QString 最大拆分(块的数量?)
- c++ - 检测 QTableWidget 中是否添加或删除了列
- javascript - 如何计算一个while循环运行了多少次?
- javascript - 纯 Javascript 超级简单的幻灯片图像编号计数器?
- javascript - 如何在内部实现带有 Promise 的渲染逻辑?
- php - 使用 PHP 以 CSV 文件格式下载