maven之插件打包详解
maven打包到lib中使用build插件,要么使用assmebly插件要么不用此插件
maven插件的命名约定:
maven插件有着自己的一套命名规范。官方插件命名的格式为maven-xxx-plugin,非官方的插件命名为 xxx-maven-plugin
maven打包方式有如下三种:
maven-jar-plugin,默认的打包插件,用来打普通的project JAR包;maven-shade-plugin,用来打可执行JAR包,也就是所谓的fat JAR包;maven-assembly-plugin,支持自定义的打包结构,也可以定制依赖项等
另外还有spring-boot-maven-plugin 插件打包
1 assmebly
1.1 assmebly简介
Maven-assembly-plugin是maven中针对打包任务而提供的标准插件,可以实现自定义打包。
主要提供如下功能:
- 提供一个把工程依赖元素、模块、网站文档等其他文件存放到单个归档文件里
- 打包成指定格式分发包,支持各种主流的格式如
zip、tar.gz、jar和war等,具体打包哪些文件是高度可控的 - 能够自定义
包含/排除指定的目录或文件
在普通 Maven 工程打包时默认仅会编译工程中新建的 java 文件并存储其 .class 文件,对于 POM 文件中引用的第三方依赖并不会一同打包。
如新建一个 Maven 工程并在依赖中导入 Jackson 依赖库并进行打包编译,可以看到下图编译后的 JAR 文件中只有工程中新建的 MyTest.class 文件,项目中所导入的依赖并没有被一起打包。

而通过 assembly 插件即可将 POM 配置中的所有依赖一同打包编译至 JAR 文件中。

assmebly 是从官网下载:http://maven.apache.org/plugins/maven-assembly-plugin/download.cgi
1.2 自定义assmebly配置
assembly 插件中,descriptors 和 descriptorRefs 是两个用于定义打包配置的不同标签。它们的主要作用是指定如何定义和使用 assembly 描述文件。下面是这两个标签的详细区别和使用方法:
descriptorRefs
功能:descriptorRefs标签用于引用预定义的、常用的 assembly 描述符。这些预定义的描述符由maven-assembly-plugin提供,通常用于常见的打包需求,如创建包含所有依赖的 JAR 文件、创建 ZIP 文件等。
常用描述符:jar-with-dependencies:创建一个包含所有项目依赖的 JAR 文件。bin:创建一个包含项目的二进制文件的压缩包。src:创建一个包含源代码的压缩包。
descriptors
功能:descriptors标签用于指定自定义的assembly描述符文件。这些描述符文件是 XML 文件,定义了如何将项目的文件和依赖打包到最终的分发包中。
在项目的src/assembly目录下创建自定义的 XML 描述符文件,来指定如何打包项目文件、依赖文件和其他资源。
1.2.1 maven中配置
在maven的<build>标签中配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}<version>
<configuration>
<!-- 打出包最终名字 -->
<finalName>test-${project.version}</finalName>
<!--用于控制在生成的归档文件(如 ZIP、JAR)中是否包含组件的构建 ID(assemblyId)-->
<!--如果组件构建ID是assembly那么生成的归档文件名将会是 artifactId-version-assembly.zip -->
<!--若为fasle则artifactId-version.zip-->
<appendAssemblyId>false</appendAssemblyId>
<!-- 配置描述符文件 指定文件位置 -->
<descriptors>
<descriptor>assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- 绑定到package生命周期 -->
<phase>package</phase>
<goals>
<!-- 只运行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
1.2.2 maven标签
1.2.2.1 configuration标签说明
descriptor标签中的assembly.xml就是指定的配置文件位置

1.2.3 assembly.xml配置
<assembly>
<id>assembly</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<!-- 启动信息 -->
<directory>src/main/bin</directory>
<includes>
<include>*.sh</include>
</includes>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<!-- 配置信息 -->
<directory>src/main/conf</directory>
<outputDirectory>conf</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/sql</directory>
<includes>
<include>*.sql</include>
</includes>
<outputDirectory>sql</outputDirectory>
</fileSet>
<fileSet>
<directory>target/classes/</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
<include>*.txt</include>
</includes>
<outputDirectory>conf</outputDirectory>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${project.artifactId}-${project.version}.jar</source>
<outputDirectory>.</outputDirectory>
</file>
</files>
<dependencySets>
<!-- 打包到lib目录下 -->
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<outputDirectory>/lib</outputDirectory>
</dependencySet>
<!-- 如果是需要启动jar单独和其他隔离开,可以这样指定启动jar在根目录 -->
<dependencySet>
<outputDirectory>/</outputDirectory>
<unpack>false</unpack>
<scope>runtime</scope>
<includes>
<include>cn.test:main:jar</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
1.2.4 assembly标签
1.2.4.1 id标签
id标识符,添加到生成文件名称的后缀符。如果指定 id 的话,目标文件则是 ${artifactId}-${id}.tar.gz
1.2.4.2 formats标签
formats是assembly插件支持的打包格式有zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war,可以同时指定多个打包格式
<formats>
<format>tar.gz</format>
<format>dir</format>
</formats>
1.2.4.3 includeBaseDirectory标签
includeBaseDirectory标签指定打的包是否包含打包层目录(比如finalName是terminal-dispatch,当值为true,所有文件被放在包内的terminal-dispatch目录下,否则直接放在包的根目录下)

1.2.4.4 dependencySets标签
用来定制工程依赖 jar 包的打包方式,核心元素如下表所示:
outputDirectory: 指定包依赖目录,该目录是相对于根目录includes/include*:包含依赖excludes/exclude*:排除依赖useProjectArtifact:指定打包时是否包含工程自身生成的jar包unpack:布尔值,false表示将依赖以原来的JAR形式打包,true则表示将依赖解成*.class文件的目录结构打包scope:表示符合哪个作用范围的依赖会被打包进去。compile与provided都不用管,一般是写runtime
1.2.4.5 fileSets标签
fileSets标签用来设置一组文件在打包时的属性:
directory:源目录的路径。includes/excludes:设定包含或排除哪些文件,支持通配符。fileMode:指定该目录下的文件权限,采用Unix八进制描述法,(User Group Other)所属属性默认值是0644,Read = 4,Write = 2和Execute = 1outputDirectory:指定文件集合的输出目录,生成目录的路径,该目录是相对于根目录
1.2.4.6 files标签
files标签可以指定目的文件名到指定目录,其他和 fileSets 相同,核心元素如下表所示:
source:源文件,相对路径或绝对路径outputDirectory:输出目录destName: 目标文件名fileMode:文件权限
1.3 预定义assembly
<descriptorRef> 用于引用 Maven 官方或自定义预定义的组装描述符。这些预定义的描述符通常已经内置在插件中,无需自己提供 assembly.xml 文件。
常用的预定义描述符包括:
jar-with-dependencies:将所有依赖打包到一个可运行的 JAR 文件中。bin:构建一个二进制分发包。src:构建一个源码分发包。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- Set jar file name -->
<finalName>${project.artifactId}-${project.version}-all</finalName>
<appendAssemblyId>false</appendAssemblyId>
<attach>false</attach>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<!-- Set effect phase -->
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
2 直接打包
这种方式就不用配置assmebly文件,直接打包就可以了
2.1 build 自带标签
2.1.1 maven-resources-plugin 标签
maven-resources-plugin 主要负责复制和过滤项目中的资源文件(如 .properties、.xml、.yml 等),默认处理的资源目录:src/main/resources(生产环境的资源)和src/test/resources(测试环境的资源)
主要功能:
- 将资源文件复制到构建目录,例如
target/classes。 - 支持过滤操作(动态替换文件中的变量,如
${}),此处配置是 全局过滤配置 - 可以通过配置指定资源文件的目标路径。
示例文件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<encoding>UTF-8</encoding>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!--配置文件打包成config目录下 -->
<outputDirectory>${project.build.directory}/twin-web/config</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
2.1.2 resources标签
在 Maven 项目中,<resources> 标签用于配置资源文件的处理逻辑,如果项目中没有显式配置 <resources>,Maven 默认会将 src/main/resources 目录下的所有文件(不进行过滤)复制到 target/classes 目录。这些文件在打包时会自动被包含到最终的 JAR/WAR 包中。
简单示例:
<resources>
<resource>
<directory>src/main/resources</directory>
<!--filerting设置为true,则打包过程中会对这些文件进行过滤处理,此处是 具体配置 -->
<!-- 在打包时动态替换资源文件中的占位符(如 ${} 变量),就需要为true -->
<filtering>true</filtering>
<!--指定目标路径为config-->
<targetPath>${project.build.directory}/config</targetPath>
<includes>
<!--使用通配符-->
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
<include>mapper/*.xml</include>
<!-- 这里可以根据你实际想要包含的配置文件类型来添加更多的include配置 -->
</includes>
</resource>
</resources>
2.1.3 maven-surefire-plugin 标签
maven-surefire-plugin 测试执行插件,负责运行项目中的单元测试或集成测试。
默认执行 src/test/java 下的测试代码(基于 JUnit、TestNG 等框架)。
测试执行命令:mvn test
功能:
- 执行测试用例并生成测试报告。
- 支持配置测试框架(如 JUnit 4/5、TestNG)。
- 提供参数化测试、并行测试支持。
示例文件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
2.1.4 maven-dependency-plugin 标签
maven-dependency-plugin 依赖管理插件,主要用于处理项目的依赖,提供下载、分析、复制、解压和报告依赖的功能。
功能:
- 下载项目依赖的 JAR 包到
本地仓库。 - 分析项目依赖(包括依赖冲突)。
- 将特定的依赖文件复制到指定目录。
- 解压依赖包以供项目使用。
常用目标(Goals):
dependency:copy:将依赖复制到指定目录。dependency:unpack:解压指定的依赖文件。dependency:tree:显示项目的依赖树结构。dependency:analyze:分析未使用或缺失的依赖。
示例文件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
2.1.5 maven-jar-plugin 标签
maven-jar-plugin 打包插件,主要用于将项目的编译产物打包成 JAR 文件,默认打包输出路径为 target/${project.artifactId}-${project.version}.jar。
功能:
- 自定义
JAR文件的结构。 - 支持将额外的资源文件或依赖包添加到 JAR 包中。
- 可以配置主类(
Main-Class),生成可执行 JAR。
简单示例
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<!-- <version>2.4</version>-->
<!-- 对要打的jar包进行配置 -->
<configuration>
<outputDirectory>
<!--输入打包可执行的jar到twin-web\libs\下-->
${project.build.directory}/twin-web/
</outputDirectory>
<!-- Configuration of the archiver -->
<archive>
<!--生成的jar中,不要包含pom.xml和pom.properties这两个文件-->
<addMavenDescriptor>false</addMavenDescriptor>
<!-- Manifest specific configuration -->
<manifest>
<!-- 指定运行类 -->
<mainClass>
cn.test.App
</mainClass>
<!--是否要把第三方jar放到manifest的classpath中-->
<addClasspath>true</addClasspath>
<!-- 生成的manifest中classpath的前缀-->
<!-- 因为要把第三方jar放到lib目录下, 所以classpath的前缀是lib/ -->
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<!-- 增加配置文件的classpath-->
<Class-Path>./config/</Class-Path>
</manifestEntries>
</archive>
<!--过滤掉不希望包含在jar中的文件-->
<excludes>
<!-- 排除不需要的文件夹(路径是jar包内部的路径) -->
<exclude>**/assembly/</exclude>
</excludes>
</configuration>
</plugin>
2.2 详细配置示例文件
<build>
<plugins>
<!-- maven依赖打包配置 -->
<!-- 引入上面的 maven-dependency-plugin示例 -->
<!-- maven主文件打包 -->
<!-- 引入上面的 maven-jar-plugin 示例 -->
</plugins>
</build>
3 使用SpringBoot插件打包
3.1 简介
spring-boot-maven-plugin是spring boot提供的 maven打包插件。可打直接可运行的 jar包或war包。
如果使用 2.2.1.RELEASE 版本,则需要maven版本在2.0及以上,JDK在1.8及以上
该插件是spring boot官方提供的一个打包插件,主要用来打出fat jar,并且提供了支持java -jar xxx.jar方式启动。官网地址:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/
3.2 pom示例
<?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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.11</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>mine</artifactId>
<dependencies>
···
</dependencies>
<build>
<!-- mavne打包动态修改替换配置文件中的占位符 -->
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<!-- 处理其中的可替换参数(@..@符合标注的变量) -->
<filtering>true</filtering>
</resource>
<!-- 可以配置引入哪些配置文件includes或排除哪些文件excludes -->
</resources>
<plugins>
<!-- 跳过单元测试的 插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<!-- 默认关掉单元测试,不用手动关闭了 -->
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- 配置文件处理插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<encoding>utf-8</encoding>
<!-- 是否使用默认占位符@@ -->
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 指定该 Main Class 为全局的唯一入口 -->
<mainClass>cn.test.App</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<!-- 将依赖到的包都放进去 -->
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.3 插件详解
插件提供了6个maven goal:
build-info:生成项目的构建信息文件build-info.propertieshelp:用于展示spring-boot-maven-plugin的帮助信息。使用命令行mvn spring-boot:help -Ddetail=true -Dgoal=<goal-name>可展示goal的参数描述信息。repackage:可生成可执行的jar包或war包。插件的核心goal。run:运行 Spring Boot 应用start:在集成测试阶段,控制生命周期stop:在集成测试阶段,控制生命周期
3.3.1 打包 repackage
将 spring-boot-maven-plugin 引入pom,执行 mvn package 命令,即可打jar包(插件默认打jar包),target文件夹里的 *.jar 即为可执行jar包。
打包主要使用的是 repackage goal,它是 spring-boot-starter-parent为插件设置的默认goal。这个 goal绑定在maven的 package 生命周期上,完整命令为 mvn package spring-boot:repackage。在 mvn package 执行打包之后,repackage 再次打包生成可执行的 jar包或war包。
默认情况下,repackage生成包的名称与 mvn package 生成的原始包名称相同,而原始包被重命名为 *.origin
repackage 命令生成的包,默认会包含项目引入的所有依赖,包括scope为provied的依赖
若项目引入了spring-boot-devtools,默认spring-boot-devtools 会被打在包里,若想排除,应设置 repackage 的 excludeDevtools参数为true。在打war包时,还应将spring-boot-devtools 的optinal设置为true或将scope设置为provided。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<excludeDevtools>true</excludeDevtools>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
repackage 会在Manifest文件中写入Main-Class and Start-Class属性。当默认值不能使程序正常运行时,可以通过插件配置。Manifest文件位于的META-INF文件夹中
打可执行jar包时,示例如下:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: beauty
Start-Class: com.demo.beauty.BeautyApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.2.1.RELEASE
Created-By: Apache Maven 3.6.3
Build-Jdk: 1.8.0_251
Main-Class: org.springframework.boot.loader.JarLauncher
对应的plugin
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.demo.beauty.BeautyApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
可以看出,打可执行jar包时,spring-boot-maven-plugin 的 mainClass 参数对应的是 Manifest 文件中的 Start-Class 属性,即项目的启动类。
3.3.2 layout标签
Manifest 文件中的 Main-Class 属性由插件的 layout 决定。layout 属性值默认为jar/war。layout种类有:
JAR,即通常的可执行jar。Main-Class : org.springframework.boot.loader.JarLauncherWAR,即通常的可执行war。Main-Class : org.springframework.boot.loader.warLauncher。为避免将war包部署在容器中运行时可能的冲突问题,provided类型的依赖都被放置在可执行war包的WEB-INF/lib-provided文件夹中,包括直接运行war需要的内置容器。ZIP,亦可作DIR,类似于JAR。Main-Class : org.springframework.boot.loader.PropertiesLauncher
当启动时需要用-Dloader.path=lib/指定额外的类加载路径-Dloader.path是Spring Boot应用程序的特性,用于指定额外的类加载路径。
在Spring Boot应用程序中,通常使用-Dloader.path来指定外部库和配置文件的路径。-classpath是Java应用程序的标准参数,用于指定类加载器在运行时搜索类和资源文件的路径。
在普通Java应用程序中,使用-classpath参数来指定类加载路径
NONE,打包所有依赖库和项目资源,但是不打包任何启动器。可以看到在layout为NONE时,打出的包中的org文件夹没有了,Manifest 文件中没有Start-Class属性,Main-Class属性值为项目的启动类。
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: beauty
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.2.1.RELEASE
Created-By: Apache Maven 3.6.3
Build-Jdk: 1.8.0_251
Main-Class: com.demo.beauty.BeautyApplication
3.4 启动方式解析
springboot插件打出的包是启动的入口,实际上在这个包里面springboot会自动打入一个引导类org.springframework.boot.loader.Launcher,它是 Spring Boot 可执行 jar 的主要入口点,它是 Spring Boot jar 文件中的实际 Main-Class,用于设置适当的 URLClassLoader 并最终调用 Spring Boot项目中定义的 main()方法。
Launcher有三个子类(JarLauncher、WarLauncher 和 PropertiesLauncher),如果我们打包插件的layout配置的是ZIP的方式,它会使用PropertiesLauncher
PropertiesLauncher机制说明:
- 默认情况下,
PropertiesLauncher在BOOT-INF/lib/中加载,我们可以通过设置loader.properties中的loader.path或LOADER_PATH环境变量来增加其它的加载位置。 loader.path:配置逗号分隔的 Classpath 类路径,例如lib,${HOME}/app/lib,前面的路径优先,类似于 javac 命令中的 -classpath。loader.home:用于解析loader.path配置的相对路径,默认是${user.dir}

浙公网安备 33010602011771号