一、概述
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项目模块
2)在\src\main\resources目录下创建资源文件(assembly.xml)
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)创建父工程,管理打包构建配置和依赖版本信息
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>