JavaFX集成Apache POI时出现ClassNotFoundException问题求助
我正在开发一个给公司各成本中心生成Excel文件的脚本,先用普通Java应用基于Apache POI 4.1.2开发,运行正常。现在要切换到带拖拽功能的JavaFX项目,依赖和普通Java项目完全一致,但运行时抛出org/apache/poi/ss/usermodel/Sheet的ClassNotFoundException,错误日志如下:
Model created Init DROOOOOP SETUPPPPPPP Java Messsge:org/apache/poi/ss/usermodel/Sheet
已经确认所有POI依赖版本都是4.1.2,尝试过maven-shade-plugin等方案,问题仍未解决,附上项目pom.xml,求技术帮助。
解决方案
1. 模块化项目需配置模块依赖
如果你的JavaFX项目是模块化(包含module-info.java),必须在模块声明中明确引入POI相关模块:
module your.module.name { requires org.apache.poi.poi; requires org.apache.poi.poi.ooxml; // 若POI需要反射访问你的类,添加opens声明 opens your.package.path to org.apache.poi.poi; }
注意:Apache POI 4.1.2的模块名称为org.apache.poi.poi和org.apache.poi.poi.ooxml,需确保这些模块在模块路径中。
2. 检查依赖Scope
确保POI依赖的scope不是provided——JavaFX运行或打包时不会自动包含provided级别的依赖:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> <!-- 保持默认compile scope即可,不要设为provided --> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency>
3. 正确配置Maven Shade Plugin
如果用shade插件打包,需合并服务提供者文件并排除签名文件,避免SPI加载失败或打包错误:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- 替换为你的JavaFX主类 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>your.package.MainApp</mainClass> </transformer> <!-- 合并SPI配置文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin>
打包后运行生成的shaded jar文件,而非普通jar。
4. 使用Maven JavaFX Plugin处理运行与打包
JavaFX项目推荐用官方插件管理运行和打包,确保所有依赖(包括POI)被正确包含:
<plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <configuration> <mainClass>your.package.MainApp</mainClass> </configuration> <executions> <execution> <id>run</id> <phase>compile</phase> <goals> <goal>run</goal> </goals> </execution> <execution> <id>jlink</id> <phase>package</phase> <goals> <goal>jlink</goal> </goals> </execution> </executions> </plugin>
运行用mvn javafx:run,打包用mvn javafx:jlink,生成的镜像会包含所有依赖。
5. 手动检查运行时类路径
如果手动运行JavaFX应用,需确保所有POI相关jar包在类路径/模块路径中:
java --module-path "path/to/javafx-sdk/lib:path/to/poi-jars" \ --add-modules javafx.controls,javafx.fxml,org.apache.poi.poi,org.apache.poi.poi.ooxml \ -cp your-app.jar your.package.MainApp
需包含的POI相关jar包括:poi-4.1.2.jar、poi-ooxml-4.1.2.jar、poi-ooxml-schemas-4.1.2.jar、commons-codec、commons-collections4等。
内容的提问来源于stack exchange,提问作者Nötter

