1 分钟搞定多项目打包:Maven 公共 Assembly 模块开箱即用

43 阅读4分钟

一、概述

Maven 的 maven-assembly-plugin(assembly 插件)是用于自定义项目打包结构的工具,核心原理是: 按照用户定义的规则(通过 assembly.xml 配置文件),将项目代码、依赖、配置文件、脚本等资源 “组装” 成一个或多个归档包(如 tar.gz、zip、jar 等),实现 “一键打包分发”。 也就是,把不同位置的文件整合到你想要的目录结构中,然后进行压缩。

核心原理拆解:3 个关键步骤

1. 读取 assembly.xml 配置文件(定义打包规则)

assembly 插件的核心是 assembly.xml 描述符文件,它定义了:

  • 输出格式:要生成的归档包类型(如 tar.gz、zip、dir 等,可同时生成多种)。
  • 文件来源:从哪里收集文件(项目编译后的 class 文件、依赖的 JAR 包、src 目录下的配置文件、外部脚本等)。
  • 目录结构:归档包内部的文件夹组织方式(如 lib/ 放依赖、conf/ 放配置、bin/ 放脚本)。
  • 权限设置:文件 / 目录的权限(如 0755 表示可执行)。
  • 依赖处理:是否包含项目依赖、依赖的过滤规则(如排除测试依赖)。

2. 收集文件(按规则聚合资源)

  • 插件根据 assembly.xml 的配置,从不同位置收集文件:

  • 项目自身资源:编译后的 class 文件(默认在 target/classes)、src/main/resources 下的配置文件等。

  • 第三方依赖:项目的 dependencies 中声明的 JAR 包(默认从本地 Maven 仓库获取)。

  • 外部资源:如 src/main/scripts 下的 .sh 或 .bat 脚本、其他模块复制过来的文件(如通过maven-dependency-plugin 提取的资源)。收集过程中会按照配置的规则进行过滤(includes/excludes),只保留需要的文件。

3. 生成归档包(按结构打包)

将收集到的文件按照 assembly.xml 定义的目录结构,打包成指定格式的归档包:

  • 例如,配置 formats 为 tar.gz 和 zip,则会生成两个包。
  • 包内的目录结构完全由 assembly.xml 控制(如 lib/ 放依赖、conf/ 放配置),与项目源码目录可能无关。
  • 最终包默认输出到 target/ 目录下,文件名通常包含项目名、版本和 assembly.xml 中定义的 id(如 myproject-1.0-dist.tar.gz)。

二、基本assembly.xml 信息

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

    <!-- 必须写,否则打包时会有 assembly ID must be present and non-empty 错误 这个名字最终会追加到打包的名字的末尾,如项目的名字为 speed-api-0.0.1-SNAPSHOT, 则最终生成的包名为
        speed-api-0.0.1-SNAPSHOT-bin.zip -->
    <id>app</id>

    <!-- 打包后的文件格式,可以是zip,tar,tar.gz,tar.bz2,jar,war,dir -->
    <formats>
        <format>tar.gz</format>
    </formats>

    <!-- 压缩包下是否生成和项目名相同的根目录 -->
    <includeBaseDirectory>false</includeBaseDirectory>

    <dependencySets>
        <dependencySet>
            <!-- 不使用项目的artifact,第三方jar不要解压,打包进zip文件的lib目录 -->
            <useProjectArtifact>false</useProjectArtifact>
            <outputDirectory>lib/libs</outputDirectory>
            <unpack>false</unpack>
        </dependencySet>
    </dependencySets>

    <fileSets>
        <!-- 把项目相关的说明文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>${project.basedir}</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>README*</include>
                <include>LICENSE*</include>
                <include>NOTICE*</include>
                <include>HELP*</include>
            </includes>
        </fileSet>

        <!-- 把项目的执行文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>${project.build.directory}/assembly-resources/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <directoryMode>0775</directoryMode>
            <includes>
                <include>*.sh</include>
                <include>*.bat</include>
            </includes>
            <fileMode>0775</fileMode>
        </fileSet>

        <!-- 把项目的配置文件,打包进zip文件的config目录 -->
        <fileSet>
            <directory>${project.basedir}/src/main/resources</directory>
            <outputDirectory>config</outputDirectory>
            <includes>
                <include>*.xml</include>
                <include>*.yml</include>
            </includes>
        </fileSet>

        <!-- 把项目的脚本文件,打包进zip文件的bin目录 -->
        <fileSet>
            <directory>${project.basedir}/src/assembly/log-dir</directory>
            <outputDirectory>logs</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/src/assembly/windows-service</directory>
            <outputDirectory>windows-service</outputDirectory>
        </fileSet>

        <!-- 把项目自己编译出来的jar文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>lib</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

三、pom文件中插件配置


<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>${maven-assembly-plugin.version}</version>
    <configuration>
        <descriptors>
            <descriptor>${project.build.directory}/assembly-resources/assembly/base-assembly.xml
            </descriptor>
        </descriptors>
        <outputDirectory>${project.build.directory}</outputDirectory>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase> <!-- 在package阶段执行打包 -->
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

四、将assembly封装成一个独立模块,提供给其他模块引入使用

1、assembly_common项目模块

1)使用普通maven创建assembly_common项目模块

image.png

2)在\src\main\resources目录下创建资源文件(assembly.xml)

image.png

3)pom文件配置构建信息

<build>
    <resources>
        <resource>
            <!-- 配置项目打包生成的文件 -->
            <directory>src/main/resources</directory>
            <includes>
                <include>assembly/*.xml</include>
                <include>bin/*.sh</include>
            </includes>
        </resource>
    </resources>
</build>

2、父工程(common_parent)common_parent)

1)创建父工程,管理打包构建配置和依赖版本信息

image.png

2)配置pom配置信息

父工程只是管理依赖,配置构建信息。

  • maven-assembly-plugin插件

根据assembly规则构建打包压缩文件

  • maven-dependency-plugin插件

实现整合assembly模块打包的核心,解压assembly_common的jar中的assembly.xml文件和其他启动文件输出到制定目录。

  • maven-jar-plugin、spring-boot-maven-plugin两个插件实现三方依赖摘除,生成的jar包能正常启动。
<?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>com.h.nexue_toolkit_common_utils</groupId>
    <artifactId>nexue_toolkit_common_utils</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>17</java.version>
        <spring.ai.version>1.0.3</spring.ai.version>
        <spring.boot.version>3.5.6</spring.boot.version>
        <maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring.ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.h.assembly_common</groupId>
                <artifactId>assembly_common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!-- 指向解压后的描述符文件 -->
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>${maven-assembly-plugin.version}</version>
                    <configuration>
                        <descriptors>
                            <descriptor>${project.build.directory}/assembly-resources/assembly/base-assembly.xml
                            </descriptor>
                        </descriptors>
                        <outputDirectory>${project.build.directory}</outputDirectory>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase> <!-- 在package阶段执行打包 -->
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- 添加dependency-plugin来解压依赖中的资源 -->
                <!-- 在项目构建的 generate-resources 阶段,自动从 assembly_common 依赖的 JAR 包中提取指定文件(assembly
                目录下的所有 .xml 文件),并复制到当前项目的 target/assembly-resources 目录中-->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>${maven-assembly-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>unpack</id>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>unpack</goal>
                            </goals>
                            <configuration>
                                <artifactItems>
                                    <artifactItem>
                                        <!-- 目标依赖:从哪个 JAR 包中提取文件 -->
                                        <groupId>com.h.assembly_common</groupId>
                                        <artifactId>assembly_common</artifactId>
                                        <version>1.0-SNAPSHOT</version>
                                        <!-- 提取后的文件输出目录 -->
                                        <outputDirectory>${project.build.directory}/assembly-resources</outputDirectory>
                                        <!-- 提取规则:只包含哪些文件 -->
                                        <includes>assembly/*.xml,bin/*.sh</includes>
                                    </artifactItem>
                                </artifactItems>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

                <!-- 1. 编译配置:指定Java版本 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>17</source> <!-- 源代码Java版本 -->
                        <target>17</target> <!-- 编译后class文件兼容版本 -->
                    </configuration>
                </plugin>

                <!-- 2. 单元测试:跳过单元测试 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <skipTests>true</skipTests> <!-- 打包时不执行单元测试 -->
                    </configuration>
                </plugin>

                <!-- 3. 生成基础JAR:配置MANIFEST.MF,指定依赖路径 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <configuration>
                        <archive>
                            <manifest>
                                <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <!-- 添加实现信息到MANIFEST -->
                                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> <!-- 添加规范信息到MANIFEST -->
                                <!--suppress UnresolvedMavenProperty -->
                                <mainClass>${start-class}</mainClass> <!-- 主启动类 -->
                                <addClasspath>true</addClasspath> <!-- 生成classpath到MANIFEST -->
                                <classpathPrefix>./libs/</classpathPrefix> <!-- 依赖存放目录(外部libs) -->
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>

                <!-- 4. Spring Boot打包:生成可执行JAR,排除第三方依赖 -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring.boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal> <!-- 重新打包为Spring Boot可执行JAR -->
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <!--suppress UnresolvedMavenProperty -->
                        <mainClass>${start-class}</mainClass>
                        <includes>
                            <!-- 排除所有第三方依赖(仅保留项目自身代码) -->
                            <include>
                                <groupId>nothing</groupId>
                                <artifactId>nothing</artifactId>
                            </include>
                        </includes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

3、其他项目导入使用

只需在pom文件引入构建配置即可完成,需要啥引入父工程配置的版本,构建信息进行使用。这样就实现了把打包模块提取到一个模块,不用重复写pom配置信息。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>first</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>