NetBeans打包JAR运行报错java.lang.NoClassDefFoundError(POI依赖问题)
我用NetBeans IDE 17开发了一个程序,点击JFrame按钮可以向.xlsx文件写入内容。在NetBeans中运行代码一切正常,但打包成可执行JAR后通过控制台运行时,出现java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook错误。我已经通过NetBeans的“添加依赖”按钮引入了相关依赖,我的pom.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany</groupId> <artifactId>workbookTesting</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.0.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.0.0</version> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>20</maven.compiler.source> <maven.compiler.target>20</maven.compiler.target> <exec.mainClass>com.mycompany.workbooktesting.NewJFrame</exec.mainClass> </properties> <build> <plugins> <plugin> <!-- Build an executable JAR --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.mycompany.workbooktesting.NewJFrame</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project>
当前配置的maven-jar-plugin仅打包了你的项目代码,并未包含依赖的POI等第三方库。虽然你在manifest里配置了类路径前缀,但Maven不会自动将依赖的JAR复制到指定的lib目录,导致运行时找不到这些依赖类。
提供两种可行的解决方式,按需选择:
方式1:打包包含所有依赖的“胖JAR”
使用maven-assembly-plugin将项目代码和所有依赖打包到同一个JAR中,运行时无需额外依赖文件。修改pom.xml的<build>部分:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <mainClass>com.mycompany.workbooktesting.NewJFrame</mainClass> </manifest> </archive> </configuration> </plugin> <!-- 新增assembly插件打包胖JAR --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.mycompany.workbooktesting.NewJFrame</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
修改完成后,在NetBeans中执行clean和package命令,target目录会生成两个JAR文件:一个是仅包含项目代码的普通JAR,另一个是带有-jar-with-dependencies后缀的胖JAR,运行这个胖JAR即可正常执行。
方式2:复制依赖到lib目录并配合原JAR运行
如果不想使用胖JAR,可以用maven-dependency-plugin将依赖复制到target/lib目录,配合原有的JAR配置运行。修改pom.xml的<build>部分:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.mycompany.workbooktesting.NewJFrame</mainClass> </manifest> </archive> </configuration> </plugin> <!-- 新增dependency插件复制依赖到lib目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build>
执行clean和package后,target目录会生成项目JAR和lib文件夹,将JAR和lib目录放在同一层级下,运行JAR文件即可。
内容的提问来源于stack exchange,提问作者ohotnx

