【Maven】Maven打包机制详解
Maven打包的类型?
以下是几种常见的打包形式:
1、jar (Java Archive)
- 用途:用于包含 Java 类文件和其他资源(如属性文件、配置文件等)的库项目。
- 特点:
- 可以被其他项目作为依赖引用。
- 适合创建独立的应用程序或可重用的组件。
- 生成文件:
.jar文件。
2、war (Web Application Archive)
- 用途:专为 Web 应用程序设计,包含了 Servlets、JSP 页面、静态资源(如 HTML、CSS、JavaScript)、以及其他必要的配置文件。
- 特点:
- 部署在应用服务器上,如 Apache Tomcat、JBoss 等。
- 包含一个特殊的目录结构,例如
WEB-INF/classes和WEB-INF/lib。
- 生成文件:
.war文件。
3、pom (Project Object Model)
- 用途:不是实际的二进制打包格式,而是用来表示一个多模块项目的父 POM。
- 特点:
- 不会产生任何输出文件,除非指定了具体的构建目标。
- 定义了一组共享的配置信息给子模块使用。
- 有助于管理大型、复杂的企业级项目。
- 生成文件:无直接生成的文件,但会生成元数据(如
.pom文件),用于描述项目及其依赖关系。
4、 maven-plugin
- 用途:在自定义插件时,需要指定打包类型为 maven-plugin。最后生成的是 jar 包。
为了指定打包类型,需要在项目的pom.xml文件中定义<packaging>元素。例如:
<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">...<packaging>jar</packaging>...
</project>
附:
1、与 packaging 标签相对的标签是 type,表示引入依赖的类型,例如 pom 类型、jar 类型,默认为 jar 类型。
2、jar 和 war 的比较:
3、Maven 打包文件的来源?[14]
虽然
src/main是放置源代码和资源的地方,但实际打包的是经过编译和处理后存放在target目录下的文件。target目录是构建工具用来存放所有中间产物和最终产物的地方,在每次构建时可能会被清理或更新。
Maven打的jar包有各种依赖吗?
Maven 构建的 JAR 文件是否包含依赖项取决于如何配置构建过程。Maven 提供了几种不同的方式来打包项目,每种方式对依赖项的处理不同:
1、普通 JAR
这是默认的打包方式,当运行 mvn clean package 命令时,Maven 会编译代码并将其打包成一个 JAR 文件,但不会将项目的依赖项包含在这个 JAR 文件中。这意味着生成的 JAR 文件只包含您的项目代码和资源文件。
使用场景:运行环境已经提供了所需依赖,如 big-marketing 项目就使用 Docker 提供了 MySQL、Redis 等。
2、带有依赖的 JAR(Fat/Uber JAR)
有时候可能想要创建一个包含所有依赖项的 JAR 文件,这样就可以直接运行而不需要额外的类路径设置。为了实现这一点,可以使用 Maven 的插件,例如 maven-shade-plugin 或 maven-assembly-plugin。
(1) 使用 maven-shade-plugin 创建 Fat JAR:
<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></execution></executions></plugin></plugins>
</build>
(2) 使用 maven-assembly-plugin 创建 Fat JAR:
<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.MainClass</mainClass></manifest></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins>
</build>
使用场景:当需要一个独立的、可执行的 JAR 文件时。更确切地说,是自定义的归档文件。
Maven打包的插件有几个?
maven-jar-plugin:jar:将普通项目或模块打成 jar 包maven-war-plugin:war:将 JaveWeb 项目或模块打成 war 包maven-shade-plugin:shade:在 jar 目标打包的基础上,将 compile 和 runtime 的依赖打进 fat jarmaven-assembly-plugin:single:个性化打包,用户可以自定义打包的类型、打包的文件、打包的目录结构等。spring-boot-maven-plugin:repackage:在 jar 目标打包的基础上,将 compile、runtime 和 provided 的依赖打进 fat jar。
演示:
1、maven-jar-plugin:jar
- 在父工程 maven-package-demo 中创建一个子模块 jar-project
- 在 pom 文件中指定打包方式 packaging 为 jar(默认为 jar,所以可不指定)
- 执行打包命令 mvn org.apache.maven.plugins:maven-jar-plugin:jar -pl :jar-project
执行流程如下:
xxx@xxxdeMacBook-Air maven-package-demo % mvn org.apache.maven.plugins:maven-jar-plugin:jar -pl :jar-project
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< cn.myphoenix:jar-project >----------------------
[INFO] Building jar-project 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- jar:3.4.1:jar (default-cli) @ jar-project ---
[WARNING] JAR will be empty - no content was marked for inclusion!
[INFO] Building jar: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/jar-project/target/jar-project-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.313 s
[INFO] Finished at: 2024-12-24T21:06:43+08:00
[INFO] ------------------------------------------------------------------------
2、maven-war-plugin:war
- 在父工程 maven-package-demo 中创建一个子模块 war-project
- 在 pom 文件中指定打包方式 packaging 为 war
- 执行打包命令 mvn org.apache.maven.plugins:maven-war-plugin:war -pl :war-project
执行流程如下:
xxx@xxxdeMacBook-Air maven-package-demo % mvn org.apache.maven.plugins:maven-war-plugin:war -pl :war-project
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< cn.myphoenix:war-project >----------------------
[INFO] Building war-project 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- war:3.4.0:war (default-cli) @ war-project ---
[INFO] Packaging webapp
[INFO] Assembling webapp [war-project] in [/Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/war-project/target/war-project-1.0-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/war-project/src/main/webapp]
[INFO] Building war: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/war-project/target/war-project-1.0-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.355 s
[INFO] Finished at: 2024-12-24T21:14:44+08:00
[INFO] ------------------------------------------------------------------------
附:另外,我还将 war 的 packaging 声明删掉了,发现依然能够成功将模块打成 war 包。
3、maven-shade-plugin:shade
- 在父工程 maven-package-demo 中创建一个子模块 shade-project
- 在 pom 文件中引入 maven-shade-plugin 插件,并将其 shade 目标绑定到 package阶段
- 在 pom 文件中引入 5 种依赖范围的依赖
- 执行打包命令
mvn package -pl :shade-project
pom 文件中引入 maven-shade-plugin,并将 shade 目标绑定到 package 阶段
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.6.0</version></plugin></plugins>
</build>
pom 文件中引入的 5 种依赖范围的依赖,观察最终打成的 fat jar 中包含哪种类型的依赖:
<dependencies><!-- compile 的依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.16</version><scope>compile</scope></dependency><!-- test 的依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- provided 的依赖--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>3.0-alpha-1</version><scope>provided</scope></dependency><!-- runtime 的依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><!-- system 的依赖--><dependency><groupId>cn.myphoenix</groupId><artifactId>big-marketing-wheel</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>/Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar</systemPath></dependency>
</dependencies>
命令的执行流程如下:
xxx@xxxdeMacBook-Air maven-package-demo % mvn package -pl shade-project
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< cn.myphoenix:shade-project >---------------------
[INFO] Building shade-project 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The artifact mysql:mysql-connector-java:jar:8.0.33 has been relocated to com.mysql:mysql-connector-j:jar:8.0.33: MySQL Connector/J artifacts moved to reverse-DNS compliant Maven 2+ coordinates.
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ shade-project ---
[INFO] Copying 0 resource from src/main/resources to target/classes
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ shade-project ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 1 source file with javac [debug target 8] to target/classes
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ shade-project ---
[INFO] skip non existing resourceDirectory /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/shade-project/src/test/resources
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ shade-project ---
[INFO] Recompiling the module because of changed dependency.
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ shade-project ---
[INFO]
[INFO] --- jar:3.4.1:jar (default-jar) @ shade-project ---
[INFO] Building jar: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/shade-project/target/shade-project-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- shade:3.6.0:shade (default) @ shade-project ---
[INFO] Including org.mybatis:mybatis:jar:3.5.16 in the shaded jar.
[INFO] Including com.mysql:mysql-connector-j:jar:8.0.33 in the shaded jar.
[INFO] Including com.google.protobuf:protobuf-java:jar:3.21.9 in the shaded jar.
[INFO] Dependency-reduced POM written at: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/shade-project/dependency-reduced-pom.xml
[WARNING] mybatis-3.5.16.jar, mysql-connector-j-8.0.33.jar, protobuf-java-3.21.9.jar, shade-project-1.0-SNAPSHOT.jar define 1 overlapping resource:
[WARNING] - META-INF/MANIFEST.MF
[WARNING] maven-shade-plugin has detected that some files are
[WARNING] present in two or more JARs. When this happens, only one
[WARNING] single version of the file is copied to the uber jar.
[WARNING] Usually this is not harmful and you can skip these warnings,
[WARNING] otherwise try to manually exclude artifacts based on
[WARNING] mvn dependency:tree -Ddetail=true and the above output.
[WARNING] See https://maven.apache.org/plugins/maven-shade-plugin/
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/shade-project/target/shade-project-1.0-SNAPSHOT.jar with /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/shade-project/target/shade-project-1.0-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.254 s
[INFO] Finished at: 2024-12-25T15:05:30+08:00
[INFO] ------------------------------------------------------------------------
打成了两个 jar 包:
- shade-project-1.0-SNAPSHOT.jar:shade 目标打成的包含依赖的 fat jar
- original-shade-project-1.0-SNAPSHOT.jar:原本的 jar 目标打成的 jar 包

如标红处所示,将 compile 范围的 MyBatis 依赖和 runtime 范围的 MySQL 依赖打到了 fat jar 中。
附:
maven-shade-plugin的shade目标通常需要在 Maven 的package阶段执行,这意味着它依赖于之前阶段生成的主要构件(通常是 JAR 文件)。具体来说,在shade操作之前,Maven 必须已经构建并打包了项目的主类文件和资源文件到一个标准的 JAR 文件中。这是因为它的工作原理是基于这个主 JAR 文件,将所有依赖项合并到其中。一、为什么
shade需要先执行jar?
- 主要构件的存在:
maven-shade-plugin需要有一个基础的 JAR 文件来作为起点。这个 JAR 文件包含了编译后的项目代码和资源文件。如果maven-jar-plugin没有正确配置或没有被执行,那么就不会生成这个必要的主 JAR 文件,从而导致shade操作失败。- 生命周期顺序:Maven 的生命周期是有序的,每个阶段都有其特定的任务。
package阶段的任务就是创建可分发格式的包(如 JAR、WAR 等),而maven-shade-plugin的shade目标则是对这些包进行进一步处理。因此,自然地,shade应该在package阶段及之后执行,以确保它能够操作到已经生成好的主 JAR 文件。- 避免重复工作:直接从命令行调用
shade可能会导致一些不必要的重复工作或者跳过某些重要的构建步骤。通过将shade绑定到package阶段,可以保证整个构建过程按照预期的顺序进行,不会遗漏任何关键步骤。二、如何执行 shade 目标?
- 配置插件绑定:在
pom.xml中明确指定maven-shade-plugin的shade目标绑定到package阶段,如下所示:
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version> <!-- 使用最新版本 --><executions><execution><phase>package</phase> <!-- 绑定到 package 阶段 --><goals><goal>shade</goal></goals></execution></executions></plugin></plugins> </build>- 运行完整的生命周期命令:使用像
mvn clean package这样的命令来触发完整的构建过程,而不是直接尝试运行shade目标。这样可以确保所有必要的前期工作都已完成,并且shade操作可以顺利进行。三、shade 目标会将哪些 scope 的依赖打进 fat jar?
- 默认情况下,
maven-shade-plugin会将compile和runtime范围的依赖打包进 Fat JAR 中,而不会包含provided、test和system范围的依赖。上面实验也验证了这一点。
4、maven-assembly-plugin
实验设计:
1、创建子模块如下图所示:
2、最终实现:
- 利用 single 目标生成一个名为 assembly-project-demo.zip 的压缩包
- 将构建过程中生成的 jar 包打包进 assembly-project-demo.zip 的根目录下
- 将 /resources/mybatis 目录下的 MyBatis 的 xml 配置文件打包进压缩包的 config/mybatis 目录下
- 将 /resources 目录下的 application.properties 打包进压缩包的 config 目录下
- 将 /resources/images 目录下的所有图片打包进压缩包的 config/images 目录下
使用 assembly 插件的步骤:
- 构思确定打包的类型、需要打包的文件、最终包的目录结构
- 在 pom 文件中引入 maven-assembly-plugin 插件。建议将 single 目标绑定到某一阶段如 package,当然也可以直接执行插件目标。
- 编写配置文件
- 需要打包的文件,如 jar 包、配置文件、资源文件等
- 打包文件的放置目录,就是把某个文件放到最终包的某个目录下
- 执行打包
实验步骤:
- 在父工程 maven-package-demo 中创建一个子模块 assembly-project
- 创建配置文件 src/main/assembly/assembly_config.xml,在配置文件配置打包的依赖、文件、jar 包等
- 在 pom 文件中引入 maven-assembly-plugin 插件,并将其 single 目标绑定到 package阶段
- 在 pom 文件中引入 4 种依赖范围的依赖
- 执行打包命令
mvn package -pl :assembly-project
配置文件 assembly_config.xml 的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<assembly><!-- 最终打包文件的后缀,格式为 assembly-project-demo --><id>demo</id><!-- 最终打包成一个用于发布的zip文件 --><formats><format>zip</format></formats><!-- 把项目中依赖的 jar 包打进 assembly-project-demo.zip 压缩包的 lib 目录下 --><dependencySets><!-- 打包 runtime 类型的依赖 --><dependencySet><!-- 不使用项目的 artifact --><useProjectArtifact>false</useProjectArtifact><!-- 打包进 zip 文件下的 lib 目录中 --><outputDirectory>lib</outputDirectory><!-- 第三方 jar 不要解压 --><unpack>false</unpack></dependencySet></dependencySets><!-- 把项目中的文件打包进 assembly-project-demo.zip 压缩包 --><fileSets><!-- target 目录下的 jar 包打包进 assembly-project-demo.zip 压缩包的根目录下 --><fileSet><directory>target</directory><outputDirectory>/</outputDirectory><includes><include>*.jar</include></includes></fileSet><!-- /resources/mybatis 目录下的 MyBatis 的 xml 配置文件打包进 assembly-project-demo.zip 压缩包的 config/mybatis 目录中 --><fileSet><!-- 文件原始路径 --><directory>${project.basedir}/src/main/resources/mybatis</directory><!-- 文件打包目标路径 --><outputDirectory>/config/mybatis</outputDirectory><includes><!-- 直接指定所有文件 --><include>*.*</include></includes></fileSet><!-- /resources 目录下的 application.properties 打包进 assembly-project-demo.zip 压缩包的 config 目录中 --><fileSet><directory>${project.basedir}/src/main/resources</directory><outputDirectory>/config</outputDirectory><includes><include>*.properties</include></includes></fileSet><!-- /resources/images 目录下的所有图片打包进 assembly-project-demo.zip 压缩包的 config/images 目录中 --><fileSet><directory>${project.build.directory}</directory><outputDirectory>/config/images</outputDirectory><includes><include>*.jeg</include><include>*.jpeg</include><include>*.png</include></includes></fileSet></fileSets>
</assembly>
pom 文件的主要配置如下:
<!-- 添加 4 种依赖范围的依赖 -->
<dependencies><!-- compile 的依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.16</version><scope>compile</scope></dependency><!-- test 的依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- provided 的依赖--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>3.0-alpha-1</version><scope>provided</scope></dependency><!-- runtime 的依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency>
</dependencies><!-- 配置 assembly 插件-->
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.2.0</version><configuration><!-- 配置打包后的文件前缀名 --><finalName>assembly-project</finalName><descriptors><!-- 指定配置文件的路径 --><descriptor>src/main/assembly/assembly_config.xml</descriptor></descriptors></configuration><!-- 配置 assembly 的 goal --><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins>
</build>
开始实验:
执行命令后,控制台打印如下:
xxx@xxxdeMacBook-Air maven-package-demo % mvn package -pl assembly-project
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< cn.myphoenix:assembly-project >--------------------
[INFO] Building assembly-project 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The artifact mysql:mysql-connector-java:jar:8.0.33 has been relocated to com.mysql:mysql-connector-j:jar:8.0.33: MySQL Connector/J artifacts moved to reverse-DNS compliant Maven 2+ coordinates.
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ assembly-project ---
[INFO] Copying 8 resources from src/main/resources to target/classes
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ assembly-project ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 2 source files with javac [debug target 8] to target/classes
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ assembly-project ---
[INFO] skip non existing resourceDirectory /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/assembly-project/src/test/resources
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ assembly-project ---
[INFO] Recompiling the module because of changed dependency.
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ assembly-project ---
[INFO]
[INFO] --- jar:3.4.1:jar (default-jar) @ assembly-project ---
[INFO] Building jar: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/assembly-project/target/assembly-project-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- assembly:3.2.0:single (make-assembly) @ assembly-project ---
[WARNING] Parameter 'finalName' is read-only, must not be used in configuration
[INFO] Reading assembly descriptor: src/main/assembly/assembly_config.xml
[WARNING] The assembly descriptor contains a *nix-specific root-relative reference (starting with slash). This is not portable and might fail on Windows: /
[WARNING] The assembly descriptor contains a *nix-specific root-relative reference (starting with slash). This is not portable and might fail on Windows: /config/mybatis
[WARNING] The assembly descriptor contains a *nix-specific root-relative reference (starting with slash). This is not portable and might fail on Windows: /config
[WARNING] The assembly descriptor contains a *nix-specific root-relative reference (starting with slash). This is not portable and might fail on Windows: /config/images
[INFO] Building zip: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/assembly-project/target/assembly-project-demo.zip
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.367 s
[INFO] Finished at: 2024-12-25T17:01:21+08:00
[INFO] ------------------------------------------------------------------------
说明:由绿色标注可以看到,assembly 的 single 目标在执行时,先读取了配置文件,然后构建了 zip 文件。
解压打成的 assembly-project-demo.zip 压缩包如下所示,可以看到和设计的目录结构一致:

说明:从 lib 目录可知,assembly:single 默认会将依赖范围是 compile 和 runtime 的依赖打进最终的归档文件。
附:
我搜索的资料,说 maven-assembly-plugin 使用最多。比如大数据项目中往往有很多 shell 脚本、SQL 脚本、.properties 及 .xml 配置文件等,采用 assembly 插件可以自定义打包类型、打包的文件、打包的目录结构。
- assembly 插件的主要作用:允许用户将项目输出项与其依赖项、模块、站点文档、脚本或其他文件等一起组装成一个可分发的归档文件。换句话说,用户可以个性化、选择性、定制化的打包。
- 最常用的标签:dependencySet 用来打包依赖;fileSet 用来打包文件。
参考:
- https://maven.apache.org/plugins/maven-assembly-plugin/?spm=5176.28103460.0.0.2e935d27YS2Bey
- https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
- https://zhuanlan.zhihu.com/p/690199623
- https://juejin.cn/post/6844904095245942798?searchId=20241225160224C56599BB59BAE97F66E5
5、spring-boot-maven-plugin
实验步骤:
- 在父工程 maven-package-demo 中创建一个子模块 boot-maven-plugin-project
- 在 pom 文件中引入 spring-boot-maven-plugin 插件
- 在 pom 文件中引入 5 种依赖范围的依赖
- 执行打包命令
mvn spring-boot:repackage -pl boot-maven-plugin-project
pom 文件中配置如下:
<properties><main-class>com.myphoenix.MyApplication</main-class>
</properties><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.7.5</version><configuration><mainClass>${main-class}</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>
说明:
- 标红:repackage 目标的执行需要借助于 maven-jar-plugin:jar。在此必须指定 repackage,然后执行命令
mvn package后会执行 repackage 目标。 - 标绿:spring-boot-maven-plugin:repackage 的初衷是打一个可以运行的 fat jar,因此,建议配置好主程序类。
执行流程如下所示:
xxx@xxxdeMacBook-Air maven-package-demo % mvn package -pl boot-maven-plugin-project
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< cn.myphoenix:boot-maven-plugin-project >---------------
[INFO] Building boot-maven-plugin-project 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The artifact mysql:mysql-connector-java:jar:8.0.33 has been relocated to com.mysql:mysql-connector-j:jar:8.0.33: MySQL Connector/J artifacts moved to reverse-DNS compliant Maven 2+ coordinates.
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ boot-maven-plugin-project ---
[INFO] Copying 0 resource from src/main/resources to target/classes
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ boot-maven-plugin-project ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 3 source files with javac [debug target 8] to target/classes
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ boot-maven-plugin-project ---
[INFO] skip non existing resourceDirectory /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/boot-maven-plugin-project/src/test/resources
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ boot-maven-plugin-project ---
[INFO] Recompiling the module because of changed dependency.
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ boot-maven-plugin-project ---
[INFO]
[INFO] --- jar:3.4.1:jar (default-jar) @ boot-maven-plugin-project ---
[INFO] Building jar: /Users/xxx/Code_Workspace/IDEA_Workspace/maven_project/maven-package-demo/boot-maven-plugin-project/target/boot-maven-plugin-project-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot:2.7.5:repackage (default) @ boot-maven-plugin-project ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.928 s
[INFO] Finished at: 2024-12-25T18:20:09+08:00
[INFO] ------------------------------------------------------------------------
如下图所示,一共生成了两个包:
- boot-maven-plugin-project-1.0-SNAPSHOT.jar:spring-boot-maven-plugin 打的 fat jar 包
- boot-maven-plugin-project-1.0-SNAPSHOT.jar.original:maven-jar-plugin 打的普通 jar 包

打成的 fat jar 解压后结构如下图所示:

说明:将依赖范围是 compile、runtime 和 provided 的依赖打包了,但 test 和 system 的依赖没有打包。
思考:既然 Maven 提供了多个打包插件,而且功能十分强大,为啥 Spring 官方还会再提供一个 spring-boot-maven-plugin 插件?
理解:即使 Maven 官方提供了多个插件,但是默认与生命周期绑定的只有 maven-jar-plugin,它的 jar 目标绑定到了 package 阶段上,只能打普通的 jar 包,无法直接运行。Spring Boot 倡导的一个理念是约定大于配置,其提供好了一些默认的配置。repackage 承袭了 Maven 的默认绑定,并且增强了 jar 目标。
本地文件jar包如何在pom文件里配置?
该题目的意思是,jar 包在自己的机器上,但是不在 Maven 的本地仓库中。所以,不能直接在 pom 文件中引入这个 jar 包。
解决方案:
方案一:
- 使用 scope 标签声明此 jar 包为系统级依赖
- 使用 systemPath 标签指定 jar 包在本地机器上的路径
方案二:
使用mvn install:install-file命令将JAR包安装到本地Maven仓库。你需要提供JAR包的路径、组ID(groupId)、构件ID(artifactId)和版本号(version)。例如:
mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=jar
附:Maven 的设计理念是所有依赖都应当通过仓库来管理,使用系统路径依赖项偏离了这一原则,可能会导致构建行为不可预测。
演示一:
创建一个项目,编写两个类,将项目打成 jar 包:

得到 jar 包 big-marketing-wheel-1.0-SNAPSHOT.jar,将此 jar 包放置到某个路径下,例如桌面 /Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar。
可以看到,这个 jar 包并没有在本地仓库中,那么我们应该如何在项目中引入此 jar 包呢?
上面已经给出了解决方案。pom 文件配置如下:
<dependency><groupId>cn.myphoenix</groupId><artifactId>big-marketing-wheel</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>/Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar</systemPath>
</dependency>
如下图所示,成功引入了位于桌面的 jar 包:

演示二:
将桌面上的 jar 包安装到本地仓库,然后直接在项目中导入本地仓库的 jar 包。
初始本地仓库中没有此 jar 包:

执行如下命令,将桌面上的 jar 包安装到本地仓库:
mvn install:install-file -Dfile=/Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar -DgroupId=cn.myphoenix -DartifactId=big-marketing-wheel -Dversion=1.0-SNAPSHOT -Dpackaging=jar
执行流程如下:
xxx@xxxdeMacBook-Air sky-takeout % mvn install:install-file -Dfile=/Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar -DgroupId=cn.myphoenix -DartifactId=big-marketing-wheel -Dversion=1.0-SNAPSHOT -Dpackaging=jar
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< cn.myphoenix:sky-takeout >----------------------
[INFO] Building sky-takeout 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- install:3.1.2:install-file (default-cli) @ sky-takeout ---
[INFO] Installing /Users/xxx/desktop/big-marketing-wheel-1.0-SNAPSHOT.jar to /Users/xxx/softwares/developer/apache-maven-3.9.9/repository/cn/myphoenix/big-marketing-wheel/1.0-SNAPSHOT/big-marketing-wheel-1.0-SNAPSHOT.jar
[INFO] Installing /var/folders/lw/_dqb_2nj2pzg16m_c06g9mf80000gn/T/big-marketing-wheel-1.0-SNAPSHOT3384356351638361494.pom to /Users/xxx/softwares/developer/apache-maven-3.9.9/repository/cn/myphoenix/big-marketing-wheel/1.0-SNAPSHOT/big-marketing-wheel-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.238 s
[INFO] Finished at: 2024-12-24T20:36:09+08:00
[INFO] ------------------------------------------------------------------------
如下图所示,成功将桌面上的 jar 包安装到本地仓库:

本文代码仓库:https://github.com/Acura-bit/maven-package-demo.git
相关文章:
【Maven】Maven打包机制详解
Maven打包的类型? 以下是几种常见的打包形式: 1、jar (Java Archive) 用途:用于包含 Java 类文件和其他资源(如属性文件、配置文件等)的库项目。特点: 可以被其他项目作为依赖引用。适合创建独立的应用程…...
Python 向量检索库Faiss使用
Faiss(Facebook AI Similarity Search)是一个由 Facebook AI Research 开发的库,它专门用于高效地搜索和聚类大量向量。Faiss 能够在几毫秒内搜索数亿个向量,这使得它非常适合于实现近似最近邻(ANN)搜索&am…...
pd.Timestamp接收的参数类型
pd.Timestamp() 是 Pandas 中用于表示单个日期时间的函数,它可以接受多种类型的参数。以下是 pd.Timestamp() 可以接受的主要参数类型,并举例说明: 1. 日期时间字符串(Date/Time String) pd.Timestamp() 可以接收标准…...
FOC控制原理-ADC采样时机
0、文章推荐 SimpleFOC移植STM32(五)—— 电流采样及其变换_极对数对电流采样的影响-CSDN博客 FOC 电流采样方案对比(单电阻/双电阻/三电阻) - 知乎 (zhihu.com) FOC中的三种电流采样方式,你真的会选择吗?…...
运行python程序报错 undefined symbol: ffi_type_uint32 的参考解决方法
文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境: Ubuntu20.04 ROS-Noetic 一、问题描述 运行 python 程序出现如下问题: Traceback (most recent call last):File "<string>", line 1, in <module&…...
怎么使用阿里的docker国产镜像源
要使用 阿里云 Docker 镜像加速器,你需要先注册并获取加速器的 URL,然后将其配置到 Docker 的配置文件中。下面是具体的使用步骤: 步骤 1:登录阿里云控制台并获取镜像加速器 URL 登录阿里云控制台 打开 阿里云官网,并…...
cloudns二级免费域名python更新ipv6 dns记录
没找到api,托管到cloudflare也不行。就只能写代码了(只写了更新和添加单条ipv6记录) 需要修改的地方 请求头的cookies填自己的 data里的zone填自己的 import requests from lxml import etree host#子域名 cookies填自己的 zone自己域名的 …...
nginx中try_files $uri $uri index.html的作用 和 $uri的含义
try_files $uri $uri/ /index.html; 这句话是Nginx服务器配置中的一条指令,用于设置处理请求的策略。 $uri:这是Nginx内置的一个变量,代表当前请求的URI,不包括参数部分。例如,如果请求的URL是http://example.com/user…...
高转化的Facebook广告文案的秘诀
Facebook 广告文案是制作有效 Facebook 广告的关键方面。它侧重于伴随广告视觉元素的文本内容。今天我们的博客将深入探讨成功的 Facebook 广告文案的秘密! 一、广告文案怎么写? 正文:这是帖子的正文,出现在您姓名的正下方。它可…...
CentOS修改docker镜像存储位置并进行数据迁移
在 CentOS 上修改 Docker 镜像存储位置并进行数据迁移是一个常见的需求。以下是一个详细的步骤指南,帮助你完成这个任务。 1. 停止 Docker 服务 首先,确保 Docker 服务已经停止,以避免在迁移过程中出现数据损坏。 sudo systemctl stop doc…...
ES7+ React/Redux/GraphQL/React-Native snippets 使用指南
VS Code React Snippets 使用指南 目录 简介基础方法React 相关React Native 相关Redux 相关PropTypes 相关控制台相关React 组件相关 简介 ES7 React/Redux/GraphQL/React-Native snippets 是一个用于 VS Code 的代码片段插件,它提供了大量用于 React 开发的代…...
【ARM】PK51关于内存模式的解析与区别
1、 文档目标 解决PK51中三种内存模式所对应的不同场景选择。 2、 问题场景 在PK51中有三种内存模型可以进行选择,但是这三种内存模型的具体作用以及应用场景大部分工程师都不太清楚。 图2-1 3、软硬件环境 1)、软件版本:Keil PK51 9.60 …...
Linux高级--2.4.5 靠协议头保证传输的 MAC/IP/TCP/UDP---协议帧格式
任何网络协议,都必须要用包头里面设置写特殊字段来标识自己,传输越复杂,越稳定,越高性能的协议,包头越复杂。我们理解这些包头中每个字段的作用要站在它们解决什么问题的角度来理解。因为没人愿意让包头那么复杂。 本…...
【每日学点鸿蒙知识】输入法按压效果、web组件回弹、H5回退问题、Flex限制两行、密码输入自定义样式
1、HarmonyOS 输入法键盘按键的按压效果? 可以使用Button组件通过stateEffect属性设置按钮按下时是否开启按压态显示效果。参考链接如下: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-button-V5https:…...
制造BOM的应用思考
一、制造BOM的作用 制造BOM(Manufacturing BOM,MBOM)在制造过程中的应用非常广泛,具体包括以下几个方面: 1. 生产计划和调度: 制造BOM提供了生产过程中所需的所有输入及输出间的关系,包括材料、部品的数量、结构以及制程等信息。这些信息是生产拉动物料需求计划以及成本…...
嵌入式硬件杂谈(八)电源的“纹波”到底是什么?
纹波的引入:在我们嵌入式设备中,很多时候电路电源的纹波很敏感,纹波太大会导致系统不工作,因此设计一个纹波很小的电路就是我们的需求了。 电路的纹波是什么? 纹波(Ripple)是指电源输出中叠加在…...
保姆级教程Docker部署ClickHouse镜像
目录 1、安装Docker及可视化工具 2、创建挂载目录 3、运行ClickHouse容器 4、Compose运行ClickHouse容器 5、查看ClickHouse运行状态 1、安装Docker及可视化工具 Docker及可视化工具的安装可参考:Ubuntu上安装 Docker及可视化管理工具 2、创建挂载目录 # 创…...
【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 7.3.1. super 我们可以通过在路径开头使用super来访问父级模块路径中的内容,就像使用..语法启动文件系统路径。例如ÿ…...
【前端,TypeScript】TypeScript速成(七):数组与函数式编程相结合
数组与函数式编程相结合 使用函数式编程遍历数组 一个最简单的例子如下: const a [1, 2, 3, 4]a.forEach(v > {console.log(v) })由于此处使用了函数式编程,因此我们可以做一些比 console.log 更复杂的事情,比如将 a 中的数据放到另一…...
第十六届蓝桥杯模拟赛(第一期)(C语言)
判断质因数 如果一个数p是个质数,同时又是整数a的约数,则p称为a的一个质因数。 请问2024有多少个质因数。 了解 约数,又称因数。整数a整除整数b,b为a的因数(约数)质数,又称素数。只有1和它本身两…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...


