Maven 的打包方式
一、前言
刚开始实习不到一个月的时候,从师兄手中接手了团队的项目,当时第一次听到了 “大包”、“小包” 的概念,只见师兄一顿操作,使用 Maven 将项目进行了打包。当时不太理解,只是记得两点:
- 如果想让项目作为一个依赖提供给他人使用,则将项目打为 “小包”;
- 如果希望项目打出来 Jar 包可以作为一个独立服务运行,则将项目打为 “大包”。
也就是说,可以将项目打包为两类:一类是作为依赖提供给他人使用,一类是作为独立服务使用。
下面将从这两类来讲解使用 Maven 将项目打包的方式。
二、将项目打为小包
所谓打包为 “小包”,其实就是仅打包项目中的代码到 JAR 包中,不打包依赖包。
将项目打包为 “小包” 的做法很简单,就是在 pom.xml 文件中的 plugins
标签给注释掉即可,也就是不做任何打包插件的配置。如下图所示:
<build><!-- 项目最终打包成的名字 --><finalName>community</finalName>
</build>
然后执行打包命令:
# 先执行 clean,再执行 package,并且跳过测试用例的执行
mvn clean package -Dmaven.test.skip=true
最后,会在当前项目的 target 目录生成一个 “小包”:
使用反编译工具查看 Jar 包具体内容:
从 Jar 包内容可以看出来,项目的依赖都以 Maven 依赖的形式保存在了 pom.xml
文件中,源码的部分只有项目本身的代码。这种 Jar 包就是所谓的 “小包”。
三、将项目打包为大包
如果想要打包后的 Jar 包能够作为一个独立服务运行,必须满足以下两点:
在 Jar 包中的
META-INF/MANIFEST.MF
中指定Main-Class
,这样才能确定程序的入口在哪里;要能加载到依赖包。
所以我们将项目打包为大包的中心思想也就是实现上面两点。使用 Maven 将项目打包为大包的方式就比较多了。主要有以下三种方式:
- 方法一:使用
maven-jar-plugin
和maven-dependency-plugin
插件 - 方法二:使用
maven-assembly-plugin
插件 - 方法三:使用
maven-shade-plugin
插件
注意:对于 SpringBoot 项目,在初始的 pom.xml
文件中就提供了 spring-boot-maven-plugin
插件用于将项目打包为可执行 Jar 包,不建议再使用其他任何插件(包括下面的三种插件)打包。
方法一:使用 maven-jar-plugin
和 maven-dependency-plugin
插件
此种打包方式有一个比较明显的缺点:打包后会在 target
目录下生成 lib
目录(存放依赖 Jar)和项目 Jar。也就是说由于依赖都存在于 lib
目录中,所以要想运行 Jar 包,必须将 Jar 包和 lib
目录放在同一个路径下。
pom.xml
文件中关于打包的配置信息如下:
<build><!-- 项目最终打包成的名字 --><finalName>community</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><!-- 会在 MANIFEST.MF 中生成 Class-Path 项 --><!-- 系统会根据 Class-Path 项配置的路径加载依赖 --><addClasspath>true</addClasspath><!-- 指定依赖包所在目录,相对于项目最终 Jar 包的路径 --><classpathPrefix>lib/</classpathPrefix><!-- 指定 MainClass --><mainClass>com.ronz.community.CommunityApplication</mainClass></manifest></archive></configuration></plugin><!-- 配置依赖包 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><!-- 相当于执行 mvn 命令,将依赖打包到指定目录 --><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><!--将依赖打包至 target 下的 lib 目录--><outputDirectory>${project.build.directory}/lib</outputDirectory></configuration></execution></executions></plugin></plugins>
</build>
这个思想也比较简单。
首先说 maven-jar-plugin
插件,它的思想就是:指定启动类、指定依赖包相对于项目最终 Jar 包所在的路径、给 MANIFEST.MF
文件添加 Class-Path
属性(运行项目 Jar 包时会根据 Class-Path
属性来找到具体依赖 Jar 包的路径)。
接着是 maven-dependency-plugin
插件,它的主要思想就是:指定所有依赖被打包为 Jar 包后的存放路径。
pom.xml 文件配置完毕之后,就可以运行打包命令了:
# 跳过测试用例执行 package 命令
mvn package -Dmaven.test.skip=true
打包完成后,会在项目的 target
目录下生成 lib
文件夹(存放项目的所有依赖)和项目的 Jar 包:
为了增强对这种方法的认识,通过反编译工具查看编译后生成的 community.jar
包,其内容如下:
可以看到,在 MANIFEST.MF
文件中生成了 Class-Path
属性,该属性的值是当前项目的所有依赖 Jar 包的路径(即 lib
目录中的 Jar 包);当然还有 MainClass
属性,由于图片尺寸的原因,没有截到。
这种方式打包出来的 Jar 包,在代码层面只包含了项目本身的代码。而项目的依赖都以 Jar 包的形式放在了项目 Jar 包同级别目录下的 lib
目录中,这些依赖 Jar 包的路径在 MANIFEST.MF
文件中都以路径的方式指明了。
方法二:使用 maven-assembly-plugin
插件
使用 maven-assembly-plugin
插件打出来的包只有一个 Jar 包,这个 Jar 包中包含了项目代码以及依赖的代码。也就意味着此种方式打出来的 Jar 包可以直接通过 java -jar xxx.jar
的命令来运行。
pom.xml
文件中关于打包的配置信息如下:
<build><!-- 项目最终打包成的名字 --><finalName>community</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><configuration><archive><!-- 指定启动类 --><manifest><mainClass>com.ronz.community.CommunityApplication</mainClass></manifest></archive><!-- 指定启动类 --><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><!-- 相当于在执行 package 打包时,在后面加上 assembly:single --><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>
这个插件的使用思想也比较简单:首先还是指定启动类;然后配置描述符参数,这个是插件提供的预置参数,不用更改;接下来就是打包时追加的命令了。
然后执行 Maven 打包命令:
# 先后执行 clean、package,并跳过测试文件的执行
mvn clean package -Dmaven.test.skip=true
打包完成之后,会在 target
目录下生成一个 Jar 包:
使用反编译工具查看 Jar 包:
从上图中可以清楚的看到:项目的所有依赖都以源码文件的形式整合在了一起。
方法三:使用 maven-shade-plugin
插件(推荐使用)
根据 Maven 的官方文档介绍,maven-shade-plugin
是一个强大的打包插件。它同样可以将项目的依赖以及项目的源码打包成一个可执行 Jar 包。
pom.xml
文件中关于打包的配置信息如下:
<build><!-- 项目最终打包成的名字 --><finalName>community</finalName><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><configuration><transformers><!-- 指定启动类 --><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.ronz.community.CommunityApplication</mainClass></transformer><!-- 下面的配置仅针对存在同名资源文件的情况,如没有则不用配置--><!-- 有些项目包可能会包含同文件名的资源文件(例如属性文件)--><!-- 为避免覆盖,可以将它们的内容合并到一个文件中 --><transformerimplementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><resource>META-INF/spring.handlers</resource></transformer><transformerimplementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><resource>META-INF/spring.schemas</resource></transformer></transformers></configuration></execution></executions></plugin></plugins>
</build>
这个配置思想很简单:首先指定执行 package
命令时附加命令,这个是固定的,不需要改变;接下来就是指定项目的启动类;然后就是配置一个文件合并操作,主要是因为有的项目可能会有重名的资源文件,为了避免前面的资源文件被后面的覆盖掉,可以将重名的配置文件合并为一个文件,对于无重名资源文件的项目则无需配置。
执行 Maven 打包命令:
# 先后执行 clean、package,并跳过测试文件的执行
mvn clean package -Dmaven.test.skip=true
打包完成之后,会在 target
目录下生成一个 Jar 包,此 Jar 包中也是将项目依赖的源码包含进来了,可以通过 java -jar xxx.jar
命令直接运行 Jar 包。
四、总结
经过我的实际测试, 使用第二种方式的 assembly
打包出来的 Jar 包多多少少有些问题,但是使用第三种方式打包出来的 Jar 包一般都是可用的。所以在将项目打包为大包时,还是推荐使用第三种打包的方式。
参考
- Apache Maven Shade Plugin
- Apache Maven Assembly Plugin
- maven 打包项目的几种方式
Maven 的打包方式相关推荐
- maven 常用打包方式汇总
通用的三种打包 1.方式一: 最小化打包 maven-jar-plugin 用途: 可以用来发布maven仓库 或最小化共享 一般不包含第三方依赖, 可以结合maven-dependency-plug ...
- IDEA中Maven项目打包方式
方式一: 直接打包,不打包依赖包,仅打包出项目中的代码到JAR包中,可称为架包.在其他应用中运行时,必须保证其上面有相应的依赖包,才能运行. maven-->Lifecyle-->Clea ...
- Maven的三种打包方式(jar、shade、assembly)
文章目录 01 引言 02 assembly打包 2.1 介绍 2.2 使用 2.3 字段解析 03 jar打包 3.1 介绍 3.2 使用 3.3 字段解析 04 shade打包 4.1 介绍 4. ...
- IDEA MAVEN项目打包成jar包的两种简单方式
IDEA MAVEN项目打包成jar包的两种简单方式 准备了两个打包方法 1.IEDA自带打包方法 2.用Maven插件maven-shade-plugin打包 IDEA自带打包 适用于任何打包,稍微 ...
- maven三种打包方式详解
目录 maven常用打包命令 1 方法一:使用maven-jar-plugin和maven-dependency-plugin插件打包 2 方法二:使用maven-assembly-plugin插件打 ...
- 探究maven项目的打包方式
前言 现在都是使用idea中maven插件来打包项目,因此此文章将基于idea中的maven插件打包. 概念 打包分为小包和大包两种概念: 小包:只打包我们写的代码,不打包代码依赖的其他jar包. 大 ...
- Maven项目打包为jar的几种方式
Maven项目打包为jar的几种方式 这里收集整理下以往打包MAVEN项目为JAR包的各种方式 ##直接打包,不打包依赖包 直接打包,不打包依赖包,仅打包出项目中的代码到JAR包中.在POM中添加如下 ...
- MAVEN的三种打包方式
MAVEN的三种打包方式 Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现"no main manifest ...
- 解放双手 | Jenkins + gitlab + maven 自动打包部署项目
前言 记录 Jenkins + gitlab + maven 自动打包部署后端项目详细过程! 需求背景 不会偷懒的程序员不是好码农,传统的项目部署,有时候采用本地手动打包,再通过ssh传到服务器部署运 ...
最新文章
- IntelliJ IDEA导入JDK出现The selected directory is not a valid home for JDK问题的解决方法
- 缓存区溢出检测工具BED
- myeclipse 如何显示序号
- linux开发 stc_Linux下构建stc51单片机开发环境
- 1001.害死人不偿命的(3n+1)猜想
- 射频与微波测量之S参数
- 手机号段对应地区编码_漫画:“哈夫曼编码” 是什么鬼?
- 如何给IP Product找到可用的sales organization
- Web应用架构-Full-text Search Service
- C语言 函数不定长参数 ##__VA_ARGS__经典案例 - C语言零基础入门教程
- Android Camera (13)---MTK平台相机插值修改
- Kubernetes学习总结(17)—— Kubernetes 快速入门需要掌握的知识点总结
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round]
- LeetCode每日一题——串联字符串的最大长度
- 关于CAPWAP的一些概念
- 《Think Python》第15章学习笔记
- 出走的门徒之一——地平线 余凯:造物主的一小步
- 在线购物系统—类图设计
- html5 答题源码脚本,自动答题脚本教程及源码分享(无视分辨率)
- ​特拉华大学彭曦教授招收2021 Fall全奖博士生