2.5 Maven Assembly Plugin 2.5 Maven Assembly Plugin 详解 2.5.1 Maven Assembly Plugin 概述 在软件开发过程中,我们经常需要将项目打包成不同的格式以满足不同的需求。例如: 可执行 JAR 包 (Executable JAR): 包含项目自身编译后的类文件以及所有运行时依赖,可以直接通过 命令运行。 源代码包 (Source Distribution): 包含项目的源代码,方便用户查看、编译或修改。 二进制发布包 (Binary Distribution): 包含编译后的二进制文件、配置文件、脚本等,用于部署到生产环境。
在软件开发过程中,我们经常需要将项目打包成不同的格式以满足不同的需求。例如:
可执行 JAR 包 (Executable JAR): 包含项目自身编译后的类文件以及所有运行时依赖,可以直接通过 java -jar 命令运行。
源代码包 (Source Distribution): 包含项目的源代码,方便用户查看、编译或修改。
二进制发布包 (Binary Distribution): 包含编译后的二进制文件、配置文件、脚本等,用于部署到生产环境。
Web 应用 WAR 包 (Web Application Archive): 用于部署到 Web 服务器的 Web 应用归档文件。
自定义格式的归档文件: 根据项目需求,组装成特定的文件结构和格式的归档文件。
Maven Assembly Plugin 的核心目标就是 自动化地创建这些不同格式的分发包。它通过读取 Assembly Descriptor (装配描述符) 文件,根据描述符的指示,将项目及其依赖的文件集合起来,并按照指定的格式进行打包。
使用 Assembly Plugin 的优势:
自动化打包: 无需手动复制文件、创建目录结构,Assembly Plugin 可以根据配置自动完成打包过程。
灵活的配置: 通过 Assembly Descriptor 可以精细地控制打包的内容和格式,满足各种复杂的需求。
简化部署和发布流程: 生成标准化的分发包,方便自动化部署和发布。
可维护性: Assembly Descriptor 是声明式的配置文件,易于理解和维护。
在使用 Assembly Plugin 之前,需要理解几个核心概念:
Assembly Descriptor (装配描述符): 这是一个 XML 文件,用于定义如何组装分发包。描述符中包含了要包含的文件、目录、依赖、以及输出格式等信息。Assembly Plugin 根据这个描述符来执行打包操作。
Assembly Format (装配格式): 指定输出分发包的格式,例如 zip, tar.gz, jar, dir 等。
Base Directory (基础目录): 定义了组装后的分发包的根目录结构。你可以自定义根目录的名称,或者保持与项目根目录一致。
File Sets (文件集): 用于指定要包含的项目文件。可以通过 include 和 exclude 模式来选择文件。
Dependency Sets (依赖集): 用于指定要包含的项目依赖。可以根据依赖的 scope、groupId、artifactId 等条件进行选择。
File Mode & Directory Mode (文件模式和目录模式): 用于设置组装后的文件和目录的权限 (Unix-like 系统)。
Mermaid Graph TD 图示 Assembly Plugin 工作流程:
流程解释:
Maven 构建生命周期执行到 assembly:assembly Goal 时,Assembly Plugin 开始工作。
Plugin 读取 Assembly Descriptor 文件 (通常是 src/main/assembly/assembly.xml 或在 pom.xml 中配置)。
Descriptor 文件定义了要包含的文件集 (File Sets)、依赖集 (Dependency Sets)、输出格式 (Format) 等。
Plugin 根据 Descriptor 的配置,收集项目文件和依赖。
应用 File Sets 和 Dependency Sets 中定义的 include 和 exclude 规则,筛选需要包含的文件和依赖。
根据指定的 Format (如 zip, jar, tar.gz),将收集到的文件和依赖打包成归档文件。
生成的分发包通常输出到项目的 target 目录下。
要使用 Assembly Plugin,需要在 pom.xml 文件中进行配置。通常在 <build> 标签下的 <plugins> 部分添加 Assembly Plugin 的配置。
基本配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <!-- 使用最新版本 --> <executions> <execution> <id>make-assembly</id> <!-- 命名 execution,方便引用 --> <phase>package</phase> <!-- 绑定到 package 生命周期阶段 --> <goals> <goal>single</goal> <!-- 使用 single goal 执行打包 --> </goals> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> <!-- 使用预定义的描述符 --> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </build>
配置详解:
<groupId> 和 <artifactId>: 指定 Maven Assembly Plugin 的坐标。
<version>: 指定 Plugin 的版本。建议使用最新版本以获得最佳功能和 bug 修复。
<executions>: 定义 Plugin 的执行配置。
<execution>: 定义一个执行任务。
<id>: 为这个 execution 命名,方便在其他地方引用。
<phase>: 将这个 execution 绑定到 Maven 生命周期阶段。 package 阶段通常用于打包操作。
<goals>: 指定要执行的 Plugin Goal。 single Goal 是最常用的 Goal,用于根据单个描述符创建分发包。
<configuration>: 配置 Plugin 的具体参数。
<descriptorRefs>: 引用预定义的 Assembly Descriptor。 <descriptorRef>jar-with-dependencies</descriptorRef> 是一个常用的预定义描述符,用于创建包含所有依赖的 JAR 包。预定义的 Assembly Descriptors:
Assembly Plugin 提供了一些预定义的描述符,方便快速创建常见的打包格式。常用的预定义描述符包括:
jar-with-dependencies: 创建包含项目自身和所有依赖的 JAR 包 (也称为 "uber-jar" 或 "fat-jar")。
src: 创建包含项目源代码的 ZIP 包。
bin: 创建包含项目二进制文件的 ZIP 包 (通常是编译后的类文件)。
assembly: 引用 src/main/assembly/assembly.xml 自定义的 Assembly Descriptor 文件。
使用自定义 Assembly Descriptor:
预定义的描述符可能无法满足所有需求。这时,可以创建自定义的 Assembly Descriptor 文件,来更精细地控制打包过程。
自定义 Assembly Descriptor 示例 (src/main/assembly/my-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"> <id>my-custom-assembly</id> <!-- Assembly 的 ID,用于标识 --> <formats> <format>zip</format> <!-- 输出格式为 ZIP --> </formats> <includeBaseDirectory>false</includeBaseDirectory> <!-- 不包含基础目录 --> <fileSets> <fileSet> <directory>${project.basedir}/src/main/resources</directory> <!-- 包含 resources 目录 --> <outputDirectory>config</outputDirectory> <!-- 输出到分发包的 config 目录下 --> <includes> <include>*.properties</include> <!-- 包含所有 .properties 文件 --> </includes> </fileSet> <fileSet> <directory>${project.build.directory}/classes</directory> <!-- 包含编译后的 classes 目录 --> <outputDirectory>lib</outputDirectory> <!-- 输出到分发包的 lib 目录下 --> </fileSet> <fileSet> <directory>${project.basedir}/scripts</directory> <!-- 包含 scripts 目录 --> <outputDirectory>bin</outputDirectory> <!-- 输出到分发包的 bin 目录下 --> <fileMode>0755</fileMode> <!-- 设置脚本文件可执行权限 (Unix-like) --> </fileSet> </fileSets> <dependencySets> <dependencySet> <outputDirectory>lib</outputDirectory> <!-- 依赖输出到分发包的 lib 目录下 --> <scope>runtime</scope> <!-- 只包含 runtime scope 的依赖 --> </dependencySet> </dependencySets> </assembly>
自定义 Assembly Descriptor 配置详解:
<assembly>: 根元素,定义 Assembly Descriptor。
<id>: Assembly 的唯一标识符。生成的归档文件名会包含这个 ID。
<formats>: 定义输出格式,可以指定多个格式。
<format>: 指定一种输出格式,例如 zip, tar.gz, jar, dir 等。<includeBaseDirectory>: 是否在分发包中包含基础目录。 false 表示不包含,直接将文件和目录放在根目录下。
<fileSets>: 定义要包含的文件集。
<fileSet>: 定义一个文件集。
<directory>: 源目录,指定要包含文件的目录。可以使用 Maven 属性,如 ${project.basedir}, ${project.build.directory} 等。
<outputDirectory>: 输出目录,指定文件在分发包中的目录。
<includes>: 包含模式,使用 Ant 风格的通配符模式来选择要包含的文件。
<excludes>: 排除模式,使用 Ant 风格的通配符模式来排除不需要包含的文件。
<fileMode>: 设置文件的权限 (Unix-like 系统)。
<directoryMode>: 设置目录的权限 (Unix-like 系统)。
<dependencySets>: 定义要包含的依赖集。
<dependencySet>: 定义一个依赖集。
<outputDirectory>: 依赖输出目录,指定依赖 JAR 包在分发包中的目录。
<scope>: 依赖的 scope,例如 runtime, compile, provided 等。
<includes>: 包含依赖的 groupId 和 artifactId 模式。
<excludes>: 排除依赖的 groupId 和 artifactId 模式。
<useProjectArtifact>: 是否包含项目自身的 artifact (默认 true)。
<unpack>: 是否解压依赖的 JAR 包 (默认 false)。
<unpackOptions>: 解压选项,可以指定包含和排除的文件模式。
在 pom.xml 中配置自定义 Assembly Descriptor:
要在 pom.xml 中使用自定义的 Assembly Descriptor,需要修改 <configuration> 部分:
<configuration> <descriptors> <descriptor>src/main/assembly/my-assembly.xml</descriptor> <!-- 指定自定义描述符文件的路径 --> </descriptors> </configuration>
或者使用 <descriptorRefs> 引用预定义描述符和 <descriptors> 引用自定义描述符:
<configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> <!-- 仍然可以使用预定义描述符 --> </descriptorRefs> <descriptors> <descriptor>src/main/assembly/my-assembly.xml</descriptor> <!-- 同时使用自定义描述符 --> </descriptors> </configuration>
执行 Assembly Plugin:
在配置好 Assembly Plugin 后,可以使用以下 Maven 命令来执行打包操作:
mvn clean package assembly:single
mvn clean package: 执行 Maven 的 clean 和 package 生命周期阶段。 package 阶段会触发 Assembly Plugin 的 execution。
assembly:single: 显式地执行 Assembly Plugin 的 single Goal。 如果在 pom.xml 中配置了 <phase>package</phase>, mvn package 命令也会自动执行 Assembly Plugin。
执行成功后,在项目的 target 目录下会生成以 <id> 和 <formats> 命名的分发包,例如 my-project-my-custom-assembly.zip。
下面通过几个代码示例来演示 Assembly Plugin 的实际应用。
示例 1: 创建可执行 JAR 包 (jar-with-dependencies)
假设我们有一个简单的 Java 项目,需要打包成可执行 JAR 包。
pom.xml 配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass>com.example.MainApp</mainClass> <!-- 指定 Main Class --> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </build>
代码解释:
使用预定义的 jar-with-dependencies 描述符。
<archive> 和 <manifest> 配置用于生成 MANIFEST.MF 文件,并指定 <mainClass>,使得生成的 JAR 包可以执行。
执行命令:
mvn clean package
结果:
在 target 目录下会生成 my-project-1.0-SNAPSHOT-jar-with-dependencies.jar 文件。 可以使用 java -jar target/my-project-1.0-SNAPSHOT-jar-with-dependencies.jar 命令运行。
示例 2: 创建包含配置文件和脚本的 ZIP 发布包
假设我们需要创建一个 ZIP 发布包,包含 resources 目录下的配置文件、scripts 目录下的脚本、以及运行时依赖。
src/main/assembly/distribution.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"> <id>distribution</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>${project.basedir}/src/main/resources</directory> <outputDirectory>config</outputDirectory> </fileSet> <fileSet> <directory>${project.basedir}/scripts</directory> <outputDirectory>bin</outputDirectory> <fileMode>0755</fileMode> </fileSet> </fileSets> <dependencySets> <dependencySet> <outputDirectory>lib</outputDirectory> <scope>runtime</scope> </dependencySet> </dependencySets> </assembly>
pom.xml 配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>make-distribution</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptors> <descriptor>src/main/assembly/distribution.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin> </plugins> </build>
执行命令:
mvn clean package
结果:
在 target 目录下会生成 my-project-1.0-SNAPSHOT-distribution.zip 文件。 解压后,可以看到包含 config, bin, lib 三个目录,分别存放配置文件、脚本和运行时依赖。
示例 3: 创建源代码包 (src)
假设我们需要创建一个包含项目源代码的 ZIP 包。
pom.xml 配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptorRefs> <descriptorRef>src</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </build>
代码解释:
src 描述符。执行命令:
mvn clean package
结果:
在 target 目录下会生成 my-project-1.0-SNAPSHOT-src.zip 文件。 解压后,可以看到包含项目的源代码目录结构。
除了基本的文件集和依赖集配置,Assembly Plugin 还提供了一些高级特性,可以满足更复杂的需求:
Module Assemblies (模块装配): 在多模块 Maven 项目中,可以为每个模块创建独立的 Assembly 分发包,或者将多个模块组装成一个分发包。
Variable Substitution (变量替换): 可以在 Assembly Descriptor 中使用 Maven 属性和自定义变量,并在打包过程中进行替换。
Assembly Merging (装配合并): 可以将多个 Assembly Descriptor 合并成一个,实现更灵活的打包配置。
Custom Assembly Formats (自定义装配格式): 可以扩展 Assembly Plugin,自定义新的输出格式。
Filtering (文件过滤): 可以对文件内容进行过滤和替换,例如替换配置文件中的占位符。
这些高级特性可以根据具体项目需求进行深入研究和应用。
保持 Assembly Descriptor 简洁易懂: 避免在 Assembly Descriptor 中定义过于复杂的文件和依赖选择规则,保持描述符的简洁性和可读性。
合理使用预定义描述符和自定义描述符: 优先考虑使用预定义的描述符,如果预定义描述符无法满足需求,再创建自定义描述符。
充分利用 Maven 属性: 在 Assembly Descriptor 中使用 Maven 属性 (如 ${project.basedir}, ${project.build.directory}, ${project.version}),可以提高配置的灵活性和可维护性。
测试 Assembly 配置: 在发布之前,务必测试生成的 Assembly 分发包,确保内容和格式符合预期。
版本管理 Assembly Descriptor: 将 Assembly Descriptor 文件纳入版本控制,方便团队协作和版本追溯。
了解 Assembly Plugin 的 Goal 和参数: 仔细阅读 Assembly Plugin 的官方文档,了解各种 Goal 和参数的用法,以便更有效地使用 Plugin。
Maven Assembly Plugin 是一个功能强大的打包工具,它通过灵活的 Assembly Descriptor 配置,可以自动化地创建各种格式的分发包。 掌握 Assembly Plugin 的使用,可以极大地简化项目的打包、部署和发布流程,提高开发效率和软件质量。 本章节介绍了 Assembly Plugin 的基本概念、配置方法、代码示例以及最佳实践,希望能够帮助你理解和应用这个重要的 Maven 插件。 通过实践和不断探索,你将能够充分利用 Assembly Plugin 的强大功能,为你的项目构建提供更完善的打包方案。