在非模块化的Maven项目中,可以使用javafx.web吗?
我认为这曾经可以工作,但我将一个JavaFX项目更新到了26.0.1,结果出现了一个错误。
Error occurred during initialization of boot layer
java.lang.module.FindException: Module jdk.jsobject not found, required by javafx.web
我做了一个最小示例来演示,基于 org.openjfx:javafx-archetype-simple 模板(见下文)
我并不需要在代码中使用javafx-web的任何类来重现这个错误,只需要把它作为一个依赖即可。在查看依赖项时(目标为 dependency:tree),我看到列出了 jdk-jsobject-26.0.1.jar。
--- dependency:3.7.0:tree (default-cli) @ mavenprojectseven ---
com.nowhere:mavenprojectseven:jar:1.0-SNAPSHOT
+- org.openjfx:javafx-controls:jar:26.0.1:compile
| +- org.openjfx:javafx-controls:jar:win:26.0.1:compile
| \- org.openjfx:javafx-graphics:jar:26.0.1:compile
| +- org.openjfx:javafx-graphics:jar:win:26.0.1:compile
| \- org.openjfx:javafx-base:jar:26.0.1:compile
| \- org.openjfx:javafx-base:jar:win:26.0.1:compile
\- org.openjfx:javafx-web:jar:26.0.1:compile
+- org.openjfx:javafx-web:jar:win:26.0.1:compile
+- org.openjfx:javafx-media:jar:26.0.1:compile
| \- org.openjfx:javafx-media:jar:win:26.0.1:compile
\- org.openjfx:jdk-jsobject:jar:26.0.1:compile
\- org.openjfx:jdk-jsobject:jar:win:26.0.1:compile
如果我创建一个模块化的项目就能工作,但我原来的项目还有一些不是模块化的旧依赖项……
那么,用Maven还能否实现非模块化的JFX项目?
POM文件:
<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.nowhere</groupId>
<artifactId>mavenprojectseven</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>25</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>26.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>26.0.1</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<release>25</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>com.nowhere.mavenprojectseven.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Main文件:
package com.nowhere.mavenprojectseven;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
var label = new Label("Hello, JavaFX");
var scene = new Scene(new StackPane(label), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
解决方案
jdk.jsobject 一直是一个JDK模块,只存在为 javafx.web 服务。它在JDK 24中被弃用,并且在JDK 26中被移除。在模块化项目中,JavaFX Maven插件会将jar放在 module path 上,因此随JavaFX打包的 jdk-jsobject-26.0.1.jar 会自动被识别为一个升级模块。在非模块化项目中,这些jar会落在 classpath 上,因此模块系统永远看不到捆绑的替代品,从而导致 FindException。要修复它,请通过插件传递 --upgrade-module-path:
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>com.nowhere.mavenprojectseven.App</mainClass>
<options>
<option>--upgrade-module-path</option>
<option>${settings.localRepository}/org/openjfx/jdk-jsobject/26.0.1/jdk-jsobject-26.0.1.jar</option>
</options>
</configuration>
</execution>
</executions>
</plugin>
The --upgrade-module-path flag tells the JVM to substitute the JavaFX-bundled jdk.jsobject for the missing JDK module. The path above resolves to the jar already downloaded by Maven into your local repository.