我正在尝试制作一个javafx程序来从excel文件中读取数据。我在我的项目中添加了
poi
依赖项。
这是我的
build.gradle
文件代码。
plugins {
id 'java'
id 'application'
id 'org.javamodularity.moduleplugin' version '1.8.12'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'org.beryx.jlink' version '2.25.0'
}
group 'com'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
ext {
junitVersion = '5.9.2'
}
sourceCompatibility = '17'
targetCompatibility = '17'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
application {
mainModule = 'com.al_makkah_traders_app'
mainClass = 'com.al_makkah_traders_app.Main'
}
javafx {
version = '17.0.6'
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
implementation 'org.controlsfx:controlsfx:11.1.2'
implementation 'org.apache.logging.log4j:log4j-core:3.0.0-alpha1'
implementation 'org.apache.poi:poi:5.2.2'
implementation 'org.apache.poi:poi-ooxml:5.2.2'
implementation 'mysql:mysql-connector-java:8.0.33'
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
test {
useJUnitPlatform()}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'app'
}
}
jlinkZip {
group = 'distribution'
}
jar {
duplicatesStrategy = 'EXCLUDE'
manifest {
attributes(
'Main-Class': 'com.al_makkah_traders_app.Main'
)
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
现在,当我尝试运行我的项目时,它会抛出一个错误,指出
> Task :Main.main() FAILED
Error occurred during initialization of boot layer
java.lang.module.FindException: Module commons.math3 not found, required by org.apache.poi.poi
有时它会抛出一个错误,指出
Error occurred during initialization of boot layer
java.lang.module.FindException: Module SparseBitSet not found, required by org.apache.poi.poi.ooxml
我一直在尝试解决这个问题,但我无法解决这个问题。虽然这些模块存在于我的项目中。
使您的项目成为非模块化的(删除
module-info.java
)。如果您需要更多信息,请参阅 openjfx.io. 的入门说明中有关非模块化项目的信息。
常见问题解答
为什么这个问题实际上发生了
您有系统中依赖模块所需的模块(java 模块,而不是 maven 或 gradle 模块),但它们不在模块路径上(可能它们仅在类路径上)。
其中一个模块(SparseBitSet)是一个自动模块(它没有模块信息)。您没有直接依赖于 SparseBitSet,但您的错误消息表明您的 poi 依赖项之一传递地需要它。
我对Gradle的经验有限,但我的经验是Gradle默认将自动模块放置在类路径上而不是模块路径上(您可以通过设置覆盖它,但据我所知,这就是它的工作原理) .
依赖自动模块来使模块化项目工作在我看来是不可取的,因此建议采用非模块化。
将项目设为非模块会有什么坏处吗?
是的。但在这种情况下,我认为利大于弊。
最初并非设计为模块化的依赖项通常可以在模块化环境中工作,但不一定。它们可能会出现很多问题,包括拆分包问题。
因此,IMO,在类路径上运行它们比作为模块运行更可靠。一旦你对某些模块这样做,你就会失去很多使用模块的好处(例如,你不能 jlink 自动模块和从类路径加载的 jar)。 jlink 只能链接带有 module-info 的模块。
当您开始使用自动模块时,您必须承受使用模块系统的痛苦(例如,必须处理您在问题中遇到的模块可访问性问题),同时获得很少的好处。
有些软件仅设计用作模块。这包括最新 JDK 发行版的基本 JDK 系统中的所有模块以及 JavaFX 模块。在模块路径上获取 JDK 模块非常简单,因为这是自动发生的。在模块路径上获取 JavaFX 模块更为复杂(该过程记录为 openjfx.io)。这意味着即使您的应用程序可能不是模块化的,它仍然可以按照预期的方式使用模块化软件作为模块(您不会失去使用模块化软件的能力)。
如果您打算编写一个供其他人使用的库,并且希望他们能够将其用作模块(例如,强制对库用户隐藏私有 API),那么您应该使您的代码模块化(包括模块信息.java)。但如果您正在编写用于部署的应用程序,则这不是问题。