使用 Maven 构建包含依赖的 JAR 包:新手分步指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

“您的应用只能在 IDE 中运行?是时候解决这个问题了!”

\n\n

如果您曾经用 Java 编写过代码,那么您很可能遇到过这种情况:您自豪地向朋友展示您的新项目,在 IntelliJ IDEA 或 Eclipse 中运行它——一切完美运行。但是,当您将这个项目交给同事或尝试通过命令行运行时,您会遇到 ClassNotFoundException 或 NoClassDefFoundError。熟悉吗?

\n\n

在大多数课程和教程中,会展示如何使用 Maven 创建 JAR 文件,但常常忽略一个重要细节:依赖去哪了?。普通的 JAR 文件只包含您的代码,而所有库(例如 Apache Commons、Jackson、JUnit)都被排除在外。这就是为什么 Stack Overflow 上有数百万 Java 开发者会问这个问题:“如何使用 Maven 创建包含依赖的可执行/可运行 JAR?”

\n\n

在本文中,我们将介绍几种经过验证的方法,使用 Maven 构建包含依赖的可执行 JAR。您将了解如何配置 maven-assembly-plugin、maven-shade-plugin,甚至了解它在 Spring Boot 中是如何工作的。开始吧!

\n\n

为什么普通的 JAR 不起作用?

\n\n

让我们做一个简单的实验。假设您有一个使用 Jackson 库解析 JSON 的应用程序。您使用命令 mvn package 创建了一个普通的 JAR,然后尝试运行它:

\n\n
java -jar my-app.jar
\n\n

然后您会得到类似这样的结果:

\n\n
Exception in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
\n\n

为什么会这样?因为 Maven 默认只打包您编译后的代码(来自 src/main/java 文件夹的类)。您在 pom.xml 中指定的所有依赖都保留在 Maven 本地仓库(~/.m2/repository)中。当您运行 JAR 时,JVM 不知道在哪里找到这些库,因此会报错。

\n\n

解决方案是创建一个 fat JAR(胖 JAR)或 uber JAR,其内部不仅包含您的类,还包含所有必需的依赖。为此,Maven 提供了专门的插件。

\n\n

方法 1:maven-assembly-plugin(简单可靠)

\n\n

最流行且最简单的方法是使用 maven-assembly-plugin。它创建一个 JAR,其中所有依赖都被解压并与您的类合并。让我们来配置它。

\n\n

在您的 pom.xml 的 <build><plugins> 部分添加以下代码:

\n\n
<plugin>\n    <groupId>org.apache.maven.plugins</groupId>\n    <artifactId>maven-assembly-plugin</artifactId>\n    <version>3.6.0</version>\n    <configuration>\n        <descriptorRefs>\n            <descriptorRef>jar-with-dependencies</descriptorRef>\n        </descriptorRefs>\n        <archive>\n            <manifest>\n                <mainClass>com.example.Main</mainClass>\n            </manifest>\n        </archive>\n    </configuration>\n    <executions>\n        <execution>\n            <id>make-assembly</id>\n            <phase>package</phase>\n            <goals>\n                <goal>single</goal>\n            </goals>\n        </execution>\n    </executions>\n</plugin>
\n\n

重要提示: 将 com.example.Main 替换为您的包含 main 方法的类的完整名称。

\n\n

现在使用以下命令构建项目:

\n\n
mvn clean package
\n\n

在 target 文件夹中会出现两个文件:

\n
    \n
  • my-app.jar — 普通

博客

书籍推荐