一、引言

在Java开发中,我们常常需要将项目打包成可执行的JAR文件,以便于部署和运行。Maven作为一款强大的项目管理工具,提供了多种方式来打包可执行JAR。接下来,我们就详细探讨三种常见的Maven打包可执行JAR的方式,并进行对比,帮助大家根据不同的应用场景做出合适的选择。

二、方式一:使用Maven Shade Plugin

2.1 应用场景

当项目依赖较多,需要将所有依赖打包到一个单独的JAR文件中,并且希望这个JAR文件可以直接运行时,Maven Shade Plugin是一个不错的选择。比如一些独立的Java应用程序,没有复杂的部署环境,只需要一个可执行的JAR文件就能在不同的机器上运行。

2.2 示例

以下是一个使用Maven Shade Plugin的示例pom.xml文件:

<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.example</groupId>
    <artifactId>my-app</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>
        <!-- 示例依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <!-- 设置主类 -->
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.example.Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

在这个示例中,我们配置了Maven Shade Plugin,指定了主类为com.example.Main。当执行mvn package命令时,会生成一个包含所有依赖的可执行JAR文件。

2.3 技术优缺点

优点

  • 方便部署:将所有依赖打包到一个JAR文件中,只需要将这个文件复制到目标机器上就可以运行,无需额外配置依赖。
  • 独立性强:JAR文件可以独立运行,不受外部环境依赖的影响。

缺点

  • 文件体积大:由于包含了所有依赖,JAR文件的体积会比较大,可能会影响传输和部署的效率。
  • 可能存在冲突:如果依赖之间存在版本冲突,可能会导致打包失败或者运行时出现问题。

2.4 注意事项

  • 要确保主类的配置正确,否则JAR文件无法正常运行。
  • 处理依赖冲突时,可以通过exclude标签来排除不必要的依赖。

三、方式二:使用Maven Assembly Plugin

3.1 应用场景

当需要将项目的依赖和其他资源(如配置文件、脚本等)打包成一个可执行的分发包时,Maven Assembly Plugin是一个很好的选择。例如,开发一个Web应用程序,需要将项目的JAR文件、配置文件和启动脚本打包在一起,方便部署和运行。

3.2 示例

以下是一个使用Maven Assembly Plugin的示例pom.xml文件:

<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.example</groupId>
    <artifactId>my-app</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>
        <!-- 示例依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <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.example.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

在这个示例中,我们配置了Maven Assembly Plugin,指定了主类为com.example.Main,并使用jar-with-dependencies描述符将项目的依赖打包到一个JAR文件中。

3.3 技术优缺点

优点

  • 灵活性高:可以自定义打包的内容,除了依赖,还可以包含其他资源,如配置文件、脚本等。
  • 可定制性强:可以通过自定义描述符来控制打包的结构和内容。

缺点

  • 配置复杂:需要编写详细的配置文件,对于初学者来说可能有一定的难度。
  • 打包速度慢:由于需要处理多个资源和依赖,打包速度可能会比较慢。

3.4 注意事项

  • 要确保描述符的配置正确,否则可能会导致打包内容不符合预期。
  • 注意资源的路径和权限,避免出现运行时错误。

四、方式三:使用Spring Boot Maven Plugin

3.1 应用场景

如果项目是基于Spring Boot开发的,那么使用Spring Boot Maven Plugin是最方便的选择。Spring Boot项目通常需要快速部署和运行,Spring Boot Maven Plugin可以将项目打包成一个可执行的JAR文件,并且可以自动配置启动参数。

3.2 示例

以下是一个使用Spring Boot Maven Plugin的示例pom.xml文件:

<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.example</groupId>
    <artifactId>my-spring-boot-app</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

在这个示例中,我们使用了Spring Boot的父项目,并配置了Spring Boot Maven Plugin。当执行mvn package命令时,会生成一个可执行的Spring Boot JAR文件。

3.3 技术优缺点

优点

  • 简单易用:对于Spring Boot项目,只需要简单配置就可以打包成可执行的JAR文件,无需复杂的配置。
  • 自动配置:Spring Boot Maven Plugin会自动配置启动参数,确保项目可以正常运行。

缺点

  • 仅限于Spring Boot项目:如果项目不是基于Spring Boot开发的,无法使用该插件。
  • 依赖Spring Boot框架:打包的JAR文件依赖于Spring Boot框架,可能会增加文件的体积。

3.4 注意事项

  • 要确保Spring Boot的版本和依赖的兼容性,避免出现版本冲突。
  • 注意Spring Boot的配置文件,确保项目可以正常启动。

五、三种方式的对比与选择

5.1 对比

方式 打包内容 配置复杂度 适用场景 文件体积
Maven Shade Plugin 所有依赖打包到一个JAR文件 较简单 独立Java应用,需要单一可执行JAR 较大
Maven Assembly Plugin 依赖和其他资源打包成分发包 较复杂 Web应用,需要包含配置文件和脚本 可定制
Spring Boot Maven Plugin Spring Boot项目打包成可执行JAR 简单 Spring Boot项目 较大

5.2 选择指南

  • 如果是独立的Java应用,不需要复杂的部署环境,希望一个JAR文件就能运行,建议选择Maven Shade Plugin。
  • 如果是Web应用,需要将项目的依赖、配置文件和脚本打包在一起,方便部署和运行,建议选择Maven Assembly Plugin。
  • 如果是基于Spring Boot开发的项目,使用Spring Boot Maven Plugin是最方便的选择。

六、文章总结

通过对Maven打包可执行JAR的三种方式的详细介绍和对比,我们可以看到每种方式都有其适用的场景和优缺点。在实际开发中,我们需要根据项目的特点和需求来选择合适的打包方式。Maven Shade Plugin适合独立的Java应用,Maven Assembly Plugin适合Web应用,而Spring Boot Maven Plugin则是Spring Boot项目的首选。同时,在使用这些方式时,我们需要注意配置的正确性和依赖的兼容性,以确保打包的JAR文件可以正常运行。