maven-plugin-shade 详解
一、介绍 [1]
This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
maven-plugin-shade 插件提供了两个能力:
- 把整个项目(包含它的依赖)都打包到一个 "uber-jar" 中
- shade - 即重命名某些依赖的包
由此引出了两个问题:
-
什么是 uber-jar ?
uber-jar 也叫做 fat-jar 或者 jar-with-dependencies,意思就是包含依赖的 jar。
-
什么是 shade ?
shade 意为遮挡,在此处可以理解为对依赖的 jar 包的重定向(主要通过重命名的方式)。
💁♂️ 下文中可能使用 shade 来代替 maven-plugin-shade。
二、基本使用 [2]
maven-plugin-shade 必须和 Maven 构建生命周期中的 package 阶段绑定,也就是说,当执行 mvn package
时会自动触发 shade。
要使用 maven-plugin-shade,只需要在 pom.xml 的 <plugins>
标签下添加它的配置即可,示例如下:
<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version><configuration><!-- 此处按需编写更具体的配置 --></configuration><executions><execution><!-- 和 package 阶段绑定 --><phase>package</phase><goals><goal>shade</goal></goals></execution></executions></plugin></plugins></build>...
</project>
默认情况下会把项目所有的依赖都包含进最终的 jar 包中。当然,我们也可以在 <configuration>
标签内配置更具体的规则。
三、常用功能
3.1 按需选择要添加到最终 jar 包中依赖 [3]
使用 <includes>
排除不需要的依赖,示例如下:
<configuration><artifactSet><excludes><exclude>classworlds:classworlds</exclude><exclude>junit:junit</exclude><exclude>jmock:*</exclude><exclude>*:xml-apis</exclude><exclude>org.apache.maven:lib:tests</exclude><exclude>log4j:log4j:jar:</exclude></excludes></artifactSet>
</configuration>
使用 <filters>
结合 <includes>
& <excludes>
标签可实现更灵活的依赖选择,示例如下:
<configuration><filters><filter><artifact>junit:junit</artifact><includes><include>junit/framework/**</include><include>org/junit/**</include></includes><excludes><exclude>org/junit/experimental/**</exclude><exclude>org/junit/runners/**</exclude></excludes></filter><filter><artifact>*:*</artifact><excludes><exclude>META-INF/*.SF</exclude><exclude>META-INF/*.DSA</exclude><exclude>META-INF/*.RSA</exclude></excludes></filter></filters>
</configuration>
除了可以通过自定义的 filters 来过滤依赖,此插件还支持自动移除项目中没有使用到的依赖,以此来最小化 jar 包的体积,只需要添加一项配置即可。示例如下:
<configuration><minimizeJar>true</minimizeJar>
</configuration>
3.2 重定位 class 文件 [4]
如果最终的 jar 包被其他的项目所依赖的话,直接地引用此 jar 包中的类可能会导致类加载冲突,这是因为 classpath 中可能存在重复的 class 文件。为了解决这个问题,我们可以使用 shade 提供的重定位功能,把部分类移动到一个全新的包中。示例如下:
<configuration><relocations><relocation><pattern>org.codehaus.plexus.util</pattern><shadedPattern>org.shaded.plexus.util</shadedPattern><excludes><exclude>org.codehaus.plexus.util.xml.Xpp3Dom</exclude><exclude>org.codehaus.plexus.util.xml.pull.*</exclude></excludes></relocation></relocations>
</configuration>
涉及标签:
<pattern>
:原始包名<shadedPattern>
:重命名后的包名<excludes>
:原始包内不需要重定位的类,类名支持通配符
例如,在上述示例中,我们把 org.codehaus.plexus.util 包内的所有子包及 class 文件(除了 ~.xml.Xpp3Dom 和 ~.xml.pull 包下的所有 class 文件)重定位到了 org.shaded.plexus.util 包内。
当然,如果包内的大部分类我们都不需要,一个个排除就显得很繁琐了。此时我们也可以使用 <includes>
标签来指定我们仅需要的类,示例如下:
<project>...<relocation><pattern>org.codehaus.plexus.util</pattern><shadedPattern>org.shaded.plexus.util</shadedPattern><includes><include>org.codehaud.plexus.util.io.*</include></includes></relocation>...
</project>
3.3 生成可执行 jar 包 [5]
使用 maven-plugin-shade 后,最终生成的 jar 包可以包含所有项目所需要的依赖。我们会想,能不能直接运行这个 uber-jar 呢?答案是当然可以,并且十分简单,只需要指定 <mainClass>
启动类就可以了。示例如下:
<project>...<configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>org.sonatype.haven.HavenCli</mainClass></transformer></transformers></configuration>...
</project>
熟悉 jar 包的朋友们都知道,jar 包中默认会包含一个 MANIFEST.MF 文件,里面描述了一些 jar 包的信息。使用 java 自带的 jar 命令打包的时候可以指定 MANIFEST.MF,其中也可以指定 Main-Class 来使得 jar 包可运行。那么使用 shade 来指定和直接在 MANIFEST.MF 文件中指定有什么区别呢?
答案是没有区别,细心的读者会发现 <mainClass>
标签的父标签是 <transformer>
有一个 implementation 属性,其值为 "~.ManifestResourceTransformer",意思是 Manifest 资源文件转换器。上述示例只自指定了启动类,因此 shade 会为我们自动生成一个包含 Main-Class 的 MANIFEST.MF 文件,然后在打 jar 包时指定这个文件。
那如果我们想要完全定制 MANIFEST.MF 文件内容怎么办呢?我们可以使用 <manifestEntries>
标签,示例如下:
<project>...<configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>org.sonatype.haven.ExodusCli</Main-Class><Build-Number>123</Build-Number></manifestEntries></transformer></transformers></configuration>...
</project>
4.4 生成资源文件 [6]
项目中涉及到的依赖可能会有它们所必需的资源文件,使用 shade 可以把它们聚合在同一个 jar 包中。
默认地,shade 为我们提供了 12 个 ResourceTransformer 类:
类名 | 作用 |
---|---|
ApacheLicenseResourceTransformer | 防止 LICENSE 文件重复 |
ApacheNoticeResourceTransformer | 准备合并的 NOTICE |
AppendingTransformer | 为某个资源文件附加内容 |
ComponentsXmlResourceTransformer | 聚合 Plexus components.xml |
DontIncludeResourceTransformer | 防止包含指定的资源 |
GroovyResourceTransformer | 合并 Apache Groovy 的扩展模块 |
IncludeResourceTransformer | 添加项目中的文件为资源文件 |
ManifestResourceTransformer | 自定义 MANIFEST 文件 |
PluginXmlResourceTransformer | 聚合 Maven 的 plugin.xml 配置 |
ResourceBundleAppendingTransformer | 合并 ResourceBundles |
ServicesResourceTransformer | 重定位且合并 META-INF/services 资源文件中的 class 文件. |
XmlAppendingTransformer | 为 XML 资源文件附加内容 |
每种 ResourceTransformer 的具体使用可以点击对应链接查看官方示例,这里不再赘述。
如果上述 12 个类都不能够满足我们的需求,我们可以实现 shade 提供的接口,按需自定义一个 ResourceTransformer,实现方法详见官网 Using your own Shader implementation。
参考来源
-
Apache Maven Shade Plugin – Introduction ↩︎
-
Apache Maven Shade Plugin – Usage ↩︎
-
http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.htm ↩︎
-
Apache Maven Shade Plugin – Relocating Classes ↩︎
-
Apache Maven Shade Plugin – Executable JAR ↩︎
-
Apache Maven Shade Plugin – Resource Transformers
相关文章:
maven-plugin-shade 详解
一、介绍 [1] This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies. maven-plugin-shade 插件提供了两个能力: 把整个项目…...
cocosCreator 之 3.x使用NodePool对象池和封装
版本: cocosCreator 3.4.0 语言: TypeScript 环境: Mac NodePool 在项目中频繁的使用instantiate和node.destory对性能有很大的耗费,比如飞机射击中的子弹使用和销毁。 因此官方提供了NodePool,它被作为管理节点对象…...
三、RestClient操作索引库与文档
文章目录 三、RestClient操作索引库与文档3.1 操作索引库3.2 操作文档结束语 三、RestClient操作索引库与文档 ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。 官方文档地址: https://www.ela…...

Hadoop3教程(五):NameNode和SecondaryNameNode
文章目录 (59)NN和2NN的工作机制(60)FsImage镜像文件(61)Edits编辑日志(62)Checkpoint时间设置参考文献 (59)NN和2NN的工作机制 NameNode的数据是存储在磁盘…...

腾讯云我的世界mc服务器多少钱一年?
腾讯云我的世界mc服务器多少钱?95元一年2核2G3M轻量应用服务器、2核4G5M带宽优惠价218元一年、4核8G12M带宽轻量服务器446元一年,云服务器CVM标准型S5实例2核2G优惠价280元一年、2核4G配置服务器748元一年,腾讯云百科txybk.com分享腾讯云我的…...
modelsim实现二选一以及D触发器并仿真
#实验一 二选一 module two_1(in1,in2,cho,out); input[3:0] in1,in2; output[3:0] out; reg[3:0] out; input cho; always* begin if(cho0) outin1; else outin2; end endmodule module two1_test(); …...

直线导轨在喷涂行业中的应用场景
直线导轨因其具有精度高、速度快、刚性强、使用寿命长等特点被广泛应用在各行各种中,其中,在喷涂行业中的应用最为广泛,以下是直线导轨在喷涂行业中的应用场景: 1、平面喷涂:直线导轨可以应用在各种机械加工的平面&…...
纯css+js自制下拉框
前提 因为html的select标签,下拉框自定义程度非常的低,为了贴合而项目ui显示,所以打算自制下拉框 代码 html <div class"pos-rel"><div id"select" class"select get-select"><span class&…...
uniapp在App端如何动态修改原生导航栏?
uniapp在App端如何动态修改原生导航栏? 文章目录 uniapp在App端如何动态修改原生导航栏?page.json配置修改 buttons 文字修改按钮上的角标设置 searchInput的 focus设置 searchInput的 text 在App端可以通过得到 webview 对象,通过当前 webvi…...
Linux:CPUPower管理器 --- cpufreq解析
一、cpufreq是什么? cpufreq是Linux内核下的一种功率管理框架,它负责改变CPU的频率,以降低功耗并延长电池寿命。该框架的主要机制是动态调整CPU频率,该频率受限于CPU的负载和功耗。cpufreq能够动态地将频率降低到最低值或最高值&a…...

【嵌入式开发问答】不是普通的嵌入式八股
1. 进程、线程、堆栈、溢出 【问:】 进程的堆栈的物理内存是什么时候分配的? 堆栈的大小限制是多大?这个限制可以调整吗? 当堆栈发生溢出后应用程序会发生什么? 【答:】...
面试题-springboot篇-SpringBoot的注解
SpringBootApplication是SpringBoot的最核心的注解。 SpringBootApplication注解在SpringBoot的主类上,标识是SpringBoot应用,用来开启SpringBoot的各项能力。由SpringBootConfiguration、EnableAutoConfiguration、ComponentScan三个注解组成。这三个注…...

BaiChuan2保姆级微调范例
前方干货预警:这可能是你能够找到的,最容易理解,最容易跑通的,适用于各种开源LLM模型的,同时支持多轮和单轮对话数据集的大模型高效微调范例。 我们构造了一个修改大模型自我认知的3轮对话的玩具数据集,使用…...
postgresql参数优化
一 相关参数介绍 1.1 内存参数-shared_buffers shared_buffers:共享缓存区的大小,相当于oracle数据库中的SGA. 一般推荐为内存的四分之一,不超过总内存的二分之一。 该值默认是128M。 1.2 cpu并行参数-max_parallel_workers max_parall…...

【极速发表】2-4区SCI (含CCF),平均录用周期仅2个月,最快11天见刊!
一、计算机科学类SCI (11.30截稿) 【期刊概况】IF:4.0-5.0, JCR2区,中科院3区; 【检索情况】SCI在检,正刊; 【国人占比】10.58%; 【自引率】7.50%; 【年发文量】100篇以下; 【预警情况】无…...

Git 提交规范
遇到的问题 在项目中采用 git 管理代码版本时,突然不能进行提交(git commit)。 报错信息如下: ERROR invalid commit message format. Proper commit message format is required for automated changelog generation. Git 规范…...
[Python进阶] 操纵鼠标:PyAutoGUI
6.4 操纵鼠标:PyAutoGUI 6.4.1 说明 PyAutoGUI是一个Python的GUI自动化工具,它可以让程序自动控制鼠标和键盘的一系列操作。它能够模拟鼠标的移动、点击、拖拽等操作,以及键盘的按键按下和释放等操作。PyAutoGUI还提供了其他功能࿰…...
JavaScript querySelector
querySelector方法的语法: var element document.getElementById("id"); element.querySelector(selector)element是要执行选择操作的父元素,selector是CSS选择器,用于指定要选择的元素。 querySelector方法返回匹配选择器的第一…...

Selenium自动化测试
一、Selenium自动化测试(基于python) 1、Selenium简介: 1.1 Selenium是一款主要用于Web应用程序自动化测试的工具集合。Selenium测试直接运行在浏览器中,本质是通过驱动浏览器,模拟浏览器的操作,比如跳转…...

Lua调用C#类
先创建一个Main脚本作为主入口,挂载到摄像机上 public class Main : MonoBehaviour {// Start is called before the first frame updatevoid Start(){LuaMgr.GetInstance().Init();LuaMgr.GetInstance().DoLuaFile("Main");}// Update is called once p…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题
20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起,为了跨网段推流,千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...