1. 概述
本教程将聚焦于如何将 Maven 项目打包成可执行 JAR 文件。当创建 JAR 文件时,我们通常希望无需 IDE 即可直接运行。为此,我们将探讨每种实现方式的配置、优缺点及适用场景。
2. 基础配置
创建可执行 JAR 不需要额外依赖,只需一个标准的 Maven Java 项目,并至少包含一个带有 main(...)
方法的类。示例中我们创建了名为 ExecutableMavenJar
的类。
确保 pom.xml
包含以下核心配置:
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>core-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
⚠️ 关键点:packaging
必须设为 jar
,这是创建可执行 JAR 的基础前提。
2.1 手动配置方案
借助 maven-dependency-plugin
实现手动控制。首先复制所有依赖到指定目录:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
核心要点:
copy-dependencies
目标将依赖复制到outputDirectory
(本例为target/libs
)- 创建可执行 JAR 时需在 MANIFEST 中声明类路径和主类:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.baeldung.executable.ExecutableMavenJar
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
✅ 优点:流程透明可控
❌ 缺点:依赖需外部存放(libs
目录),JAR 文件需与该目录共存才能运行
2.2 Apache Maven Assembly Plugin
Assembly Plugin 可将项目输出、依赖、文档等聚合为单个可运行包。核心目标是 single
(其他目标已废弃):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.baeldung.executable.ExecutableMavenJar
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
输出文件名示例:core-java-jar-with-dependencies.jar
✅ 优点:依赖全打包进 JAR,单文件部署
❌ 缺点:打包控制能力有限(如不支持类重定位)
2.3 Apache Maven Shade Plugin
Shade Plugin 可创建包含所有依赖的 "uber-jar",并支持依赖包重命名(shading):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation=
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.baeldung.executable.ExecutableMavenJar</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
输出文件名示例:core-java-0.1.0-SNAPSHOT-shaded.jar
✅ 优点:依赖全打包,支持高级功能(shading/类重定位)
❌ 缺点:配置较复杂(尤其使用高级特性时)
2.4 One Jar Maven Plugin
One Jar 提供自定义类加载器,可直接从 JAR 内部加载依赖(而非文件系统):
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<mainClass>org.baeldung.executable.
ExecutableMavenJar</mainClass>
<attachToBuild>true</attachToBuild>
<filename>
${project.build.finalName}.${project.packaging}
</filename>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
✅ 优点:清晰的类加载模型,支持外部 JAR 和原生库
❌ 缺点:自 2012 年后停止维护
2.5 Spring Boot Maven Plugin
即使非 Spring Boot 项目,也可用此插件打包可执行 JAR/WAR:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.baeldung.executable.ExecutableMavenJar
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
✅ 优点:依赖全打包,支持 WAR 打包、依赖排除等高级功能
❌ 缺点:会引入不必要的 Spring Boot 相关类
2.6 嵌入式 Tomcat 的 Web 应用
使用 tomcat7-maven-plugin
打包独立 Web 应用:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>exec-war-only</goal>
</goals>
<phase>package</phase>
<configuration>
<path>/</path>
<enableNaming>false</enableNaming>
<finalName>webapp.jar</finalName>
<charset>utf-8</charset>
</configuration>
</execution>
</executions>
</plugin>
执行 mvn package
后生成 webapp.jar
,通过 java -jar target/webapp.jar
启动,访问 localhost:8080
测试。
⚠️ 注意:Servlet 依赖需设为 provided
scope 以免冲突:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
✅ 优点:单文件部署简单
❌ 缺点:因嵌入 Tomcat 导致文件体积较大
2.7 使用 Launch4j 生成 Windows 可执行文件
通过 launch4j-maven-plugin
将 JAR 转为 .exe
:
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>2.5.3</version>
<executions>
<execution>
<id>l4j-clui</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
<configuration>
<headerType>gui</headerType>
<outfile>${project.build.directory}/${project.build.finalName}.exe</outfile>
<jar>${project.build.directory}/${project.build.finalName}.jar</jar>
<errTitle>App Error</errTitle>
<classPath>
<mainClass>com.baeldung.executable.ExecutableMavenJar</mainClass>
</classPath>
</configuration>
</execution>
</executions>
</plugin>
执行 mvn clean package
后在 target
目录生成 .exe
文件。
✅ 优点:简化 Windows 用户分发流程
❌ 缺点:仅限 Windows 平台
3. 创建多个可运行 JAR
当项目需包含多个主类时,可通过以下方式生成独立 JAR:
3.1 使用 maven-assembly-plugin
配置多执行方案:
<profile>
<id>multiple-jar-profile</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-jar-for-main1</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.baeldung.multiplejar.Main1</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>main1-runnable</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
<execution>
<id>create-jar-for-main2</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.baeldung.multiplejar.Main2</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>main2-runnable</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
执行命令:
mvn clean package -Pmultiple-jar-profile
生成文件:
main1-runnable.jar
main2-runnable.jar
测试命令:
java -jar target/main1-runnable.jar # 输出: Hello from Main1!
java -jar target/main2-runnable.jar # 输出: Hello from Main2!
3.2 使用 maven-shade-plugin
替代方案配置:
<profile>
<id>multiple-jar-profile2</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
<executions>
<execution>
<id>shade-main1</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>main1</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.baeldung.multiplejar.Main1</mainClass>
</transformer>
</transformers>
<finalName>main1-runnable</finalName>
</configuration>
</execution>
<execution>
<id>shade-main2</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>main2</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.baeldung.multiplejar.Main2</mainClass>
</transformer>
</transformers>
<finalName>main2-runnable</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
4. 总结
本文系统介绍了多种 Maven 创建可执行 JAR 的方案:
方案 | 适用场景 | 核心优势 | 主要限制 |
---|---|---|---|
手动配置 | 需精细控制依赖 | 流程透明 | 依赖需外部存放 |
Assembly Plugin | 简单单文件部署 | 开箱即用 | 打包控制弱 |
Shade Plugin | 需依赖隔离/重命名 | 支持 shading | 配置复杂 |
One Jar | 特殊类加载需求 | 支持外部 JAR | 已停止维护 |
Spring Boot Plugin | 复杂项目打包 | 功能全面 | 引入冗余类 |
Tomcat Plugin | Web 应用独立部署 | 内嵌容器 | 文件体积大 |
Launch4j | Windows 分发 | 生成 .exe | 跨平台限制 |
测试建议:执行 mvn clean package
构建 JAR 后,通过 java -jar <文件名>
验证。
⚠️ 最后提醒:确保所打包依赖的许可证允许此类操作,虽然多数场景无此限制,但仍需注意合规性。