Java项目打包故障:如何生成含本地依赖的可执行Jar包?
解决Maven打包时缺失源码与system依赖的问题
看起来你踩了两个常见的Maven打包坑:用错了插件导致编译后的代码没被打包,以及system scope的依赖默认不会被包含进最终jar里。咱们一步步来解决:
1. 先修正项目结构(Maven规范很重要)
Maven默认约定源码放在src/main/java目录,资源文件放在src/main/resources,你的当前结构不符合这个规范,这会导致Maven编译时找不到你的源码,最终打包自然缺失代码。调整后应该是:
├── src │ └── main │ ├── java │ │ └── controller │ │ └── MainController.java # 对应你的mainClass路径 │ └── resources │ ├── org.eclipse.swt.win32.win32.x86_64_3.106.2.v20171129-0543.jar │ └── swing2swt.jar └── pom.xml
2. 替换插件:用maven-assembly-plugin替代maven-source-plugin
你之前用的maven-source-plugin是用来生成源码jar包的,不是用来打包包含依赖的可执行jar的。正确的选择是maven-assembly-plugin,它能帮你把编译后的代码、所有依赖(包括system scope的)打包到一个jar里。
修改后的完整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>groupId</groupId> <artifactId>MyProgram</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!-- 注意:移除重复的org.eclipse.swt依赖,避免冲突 --> <dependency> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/org.eclipse.swt.win32.win32.x86_64_3.106.2.v20171129-0543.jar</systemPath> </dependency> <dependency> <groupId>swing2swt</groupId> <artifactId>swing2swt</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/swing2swt.jar</systemPath> </dependency> <dependency> <groupId>org.eclipse.ui</groupId> <artifactId>ide</artifactId> <version>3.2.1-M20060915-1030</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <configuration> <!-- 配置可执行jar的主类 --> <archive> <manifest> <mainClass>controller.MainController</mainClass> </manifest> </archive> <!-- 使用预定义的"jar-with-dependencies"描述符 --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <!-- 关键:开启包含system scope的依赖 --> <includeSystemScope>true</includeSystemScope> </configuration> <!-- 绑定到package阶段,执行mvn package时自动打包 --> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
3. 执行打包命令
在项目根目录运行:
mvn clean package
执行完成后,你会在target目录下看到两个jar:
MyProgram-1.0-SNAPSHOT.jar:只包含你的编译后的代码MyProgram-1.0-SNAPSHOT-jar-with-dependencies.jar:包含你的代码+所有依赖(包括那两个system jar)的可执行jar
直接运行这个带依赖的jar即可:
java -jar target/MyProgram-1.0-SNAPSHOT-jar-with-dependencies.jar
关键要点解释
includeSystemScope=true:这是让system依赖被打包进去的核心配置,默认Maven会忽略system scope的依赖,必须显式开启。- Maven项目规范:遵守
src/main/java放源码的约定,Maven才能自动编译你的代码并打包进去,之前的问题很大程度上是因为目录不符合规范导致编译失败,最终jar里没有代码。 - 移除重复依赖:你之前的pom里有两个
org.eclipse.swt依赖,一个是system的,一个是从Maven仓库拉的,这会导致冲突,保留system的那个即可(因为你需要特定的Windows版本的SWT jar)。
内容的提问来源于stack exchange,提问作者Bobby
相关产品推荐
相关产品推荐

