Maven 可以从 Java 项目构建一个肥 JAR(Fat JAR)。所谓肥 JAR 就是一个 JAR 文件包含项目中所有编译过的 Java 类,以及项目依赖的所有 JAR 文件中所有编译过的 Java 类。本教程将展示如何用 Maven 创建一个胖 JAR。

当需要构建一个可执行的 JAR 文件时,胖 JAR 很方便,比如一个微服务可执行文件。我么可以把微服务机器所有依赖,打包成一个 JAR 文件。这就让执行更容易,因为我们不用在类路径上列出我们的微服务依赖的所有 JAR 文件。这简化了启动微服务的命令。

如果需要把应用程序打包到 Docker 容器中,肥 JAR 也很方便。这样子不用将应用程序依赖的每个 JAR 文件添加到 Docker 容器,只需要添加应用程序的肥 JAR 即可。同样,这样更短、更容易,让 Dockerfile 独立于应用程序所用的外包依赖(JAR 文件)。

肥 JAR POM 配置

要让 Maven 从项目中构建一个肥 JAR,必须在项目的 POM 文件中包含肥 JAR 构建配置。通过在 POM 文件的 plugin 部分包含 maven-assembly-plugin,就可以配置 Maven 从项目构建胖 JAR。Maven 将它构建的输出产品称为 Assembly(程序集)。这就是 maven-assembly-plugin 名称的由来。如下是 POM 文件的一个示例片段,展示 maven-assembly-plugin 配置的示例:

  1. <build>
  2. <finalName>my-project-name</finalName>
  3. <plugins>
  4. <!-- other Maven plugins ... -->
  5. <plugin>
  6. <groupId>org.apache.maven.plugins</groupId>
  7. <artifactId>maven-assembly-plugin</artifactId>
  8. <version>3.1.1</version>
  9. <configuration>
  10. <descriptorRefs>
  11. <descriptorRef>jar-with-dependencies</descriptorRef>
  12. </descriptorRefs>
  13. </configuration>
  14. <executions>
  15. <execution>
  16. <id>make-assembly</id>
  17. <phase>package</phase>
  18. <goals>
  19. <goal>single</goal>
  20. </goals>
  21. </execution>
  22. </executions>
  23. </plugin>
  24. </plugins>
  25. </build>

maven-assembly-plugin 配置中的 configuration XML 元素包含 descriptorRef,这个元素告诉 Maven 这个配置应该构建什么类型的程序集。值 jar-with-dependencies 是告诉 Maven 去构建一个带有依赖的 JAR 文件,就是胖 JAR 的另一个术语。

executions XML 元素告诉 Maven 这个 Maven 插件应该在哪个 Maven 构建阶段和目录期间被执行。maven-assembly-plugin 应该总是在 package 阶段期间被执行。

构建胖 JAR 的Maven 命令

让 Maven 构建胖 JAR 的 Maven 命令为:

mvn clean package

当用前面所示的 maven-assembly-plugin 配置执行 Maven package 阶段时,Maven 会在 target 目录中输出一个胖 JAR,这个目录是 Maven 输出所有其它构建产品(比如编译过的类、生成的 JavaDoc 等)的地方。胖 JAR 会像这样子命名:

my-project-name-jar-with-dependencies.jar

上述胖 JAR 文件名的 my-project-name 部分来自于本教程前面所示示例中 build XML 元素顶部所包含的 finalName XML 元素。

更多 Maven 命令,请参见上一篇文章。

在官方Maven Assembly 插件文档 中可以阅读到更多有关 Maven Assembly 插件的信息。

胖 JAR 配置的完整 POM 文件

下面是带有胖 JAR 配置的完整 Maven POM 文件,只是为了展示这样一个 POM 文件是什么样的:

<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.jenkov.myprojectname</groupId>
    <artifactId>my-project-name</artifactId>
    <version>1.1.0</version>
    <packaging>jar</packaging>

    <name>My Project Name</name>

    <dependencies>

        <!-- 项目所用的依赖 -->

    </dependencies>

    <build>
        <finalName>my-project-name</finalName>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>

                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>

                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>

            </plugin>
        </plugins>
    </build>
</project>