[Maven] maven插件系列之maven-shade-plugin
[Maven] maven插件系列之maven-shade-plugin
1 插件简述/Plugin Overview
1.1 定义与目的/Definition & Goals
- Official Definition
Apache Maven : maven-shade-plugin
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.(该插件提供了将工件打包到uber jar中的功能,包括其依赖项,并对一些依赖项的包进行着色(即重命名)。)
- Goals Overview
The Shade Plugin has a single goal: (Shade插件只有一个目标:)
shade:shade is bound to the package phase and is used to create a shaded jar. (shade:shade绑定到封装阶段,用于创建一个shaded jar。)
- Sample Explain/简单解释:
maven-plugin-shade 插件提供了2个能力:
把整个项目(包含它的依赖)都打包到一个 “uber-jar” 中 shade - 即重命名某些依赖的包。也由此引出了两个问题:
+ 什么是 uber-jar ?
+ 这中打包后带依赖的 Jar 包一般称为uber-jar或fat-jar或者jar-with-dependencies;意思就是包含依赖的 jar。
+ 什么是 shade ?
+ shade 意为遮挡,在此处可理解为:对依赖的 jar 包的重定向(主要通过重命名的方式)。
shade
n. 灯罩;阴凉处;(树)荫;色度;痕迹,影子,遗风;一点;差别;背阴;暗部;阴魂;浓淡深浅
vt. 给…遮挡(光线);画阴影;加灯罩;把…涂暗;险胜
uber
adj.超级的;极其的;最好的;
1.2 Version/版本
If you like to use minimizeJar this means you have to use JDK8+. This is based on a required upgrade of dependencies.
如果你喜欢使用minimizeJar,这意味着你必须使用JDK8+。这是基于所需的依赖项升级。
Latest version(最新版本) = 3.5.0

https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin
2 实践与使用/Usage
2.1 官方插件说明
Official Document/官方文档
General instructions on how to use the Shade Plugin can be found on the usage page. Some more specific use cases are described in the examples given below.
有关如何使用Shade插件的一般说明可以在使用页面上找到。下面给出的示例中描述了一些更具体的用例。
In case you still have questions regarding the plugin's usage, please feel free to contact the user mailing list. The posts to the mailing list are archived and could already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching the mail archive.
如果您对插件的使用仍有疑问,请随时联系用户邮件列表。邮件列表中的帖子已存档,可能已经包含了您问题的答案,作为旧线程的一部分。因此,浏览/搜索邮件档案也是值得的。
If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our issue tracker. When creating a new issue, please provide a comprehensive description of your concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are welcome, too. Contributors can check out the project from our source repository and will find supplementary information in the guide to helping with Maven.
如果你觉得插件缺少功能或有缺陷,你可以在我们的问题跟踪器中填写功能请求或错误报告。创建新问题时,请对您关心的问题进行全面描述。特别是对于修复错误,开发人员能够重现您的问题是至关重要的。出于这个原因,非常感谢整个调试日志、POM,或者最好是附加到该问题的小演示项目。当然,补丁也是受欢迎的。参与者可以从我们的源代码库中查看该项目,并在帮助使用Maven的指南中找到补充信息。
2.2 基本使用 : build>plugin
2.2.0 maven-shade-plguin 的基本使用
- maven-plugin-shade 必须和 Maven 构建生命周期中的 package 阶段绑定。
也就是说,当执行
mvn package时会自动触发shade。
- 要使用
maven-shade-plugin,只需要在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> 标签内配置更具体的规则。
2.2.1 测试验证(maven-shade-plugin)
- pom.xml
<?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>
<artifactId>johnny-webapp-quickstart</artifactId>
<groupId>cn.johnnyzen</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
-->
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<groupId>cn.johnnyzen</groupId>
<artifactId>study-maven</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-shade-plugin.version>3.5.0</maven-shade-plugin.version>
<fastjson.version>2.0.3</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
<configuration>
<!-- 此处按需编写更具体的配置 -->
</configuration>
<executions>
<execution>
<!-- 和 package 阶段绑定 -->
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 打包结果
mvn clean install


2.2.2 测试验证(maven-compile-plugin)
- pom.xml
<?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>
<artifactId>johnny-webapp-quickstart</artifactId>
<groupId>cn.johnnyzen</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
-->
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<groupId>cn.johnnyzen</groupId>
<artifactId>study-maven</artifactId>
<properties>
<java.jdk.version>1.8</java.jdk.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-shade-plugin.version>3.5.0</maven-shade-plugin.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<fastjson.version>2.0.3</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.jdk.version}</source>
<target>${java.jdk.version}</target>
<!--<encoding>${project.build.outputEncoding}</encoding>-->
<!-- <skipTests>true</skipTests> --><!-- 跳过测试 -->
<!--<verbose>true</verbose>--> <!--<showWarnings>true</showWarnings>--> <!--<fork>true</fork>--><!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 -->
<!--<executable>--><!-- path-to-javac --><!--</executable>--><!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> -->
<!--<compilerVersion>${java.version}</compilerVersion>--><!-- 指定插件将使用的编译器的版本 -->
<!--<meminitial>128m</meminitial>--><!-- 编译器使用的初始内存 -->
<!--<maxmem>512m</maxmem>--><!-- 编译器使用的最大内存 -->
<!--<compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument>--><!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
- 打包效果
mvn clean install


2.2.3 测试验证(build is empty)
- pom.xml
<?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>
<artifactId>johnny-webapp-quickstart</artifactId>
<groupId>cn.johnnyzen</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
-->
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<groupId>cn.johnnyzen</groupId>
<artifactId>study-maven</artifactId>
<properties>
<java.jdk.version>1.8</java.jdk.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-shade-plugin.version>3.5.0</maven-shade-plugin.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<fastjson.version>2.0.3</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>
</build>
</project>
- 打包效果
mvn clean install


2.3 扩展配置: build>plugin>configuration
2.3.1 include/exclude : 按需选择要添加到最终 jar 包中依赖
- 支持
include/exclude2 种操作 - 支持执行通配符匹配目标依赖JAR包:
'*' 、'?' - 配置格式:
groupId:artifactId[[:type]:classfier]
- 样例配置
<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>
2.3.2 filter : 过滤
- 使用
<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>
2.3.3 minimizeJar : 最小化JAR包体积
- 除了可以通过自定义的 filters 来过滤依赖,此插件还支持自动移除项目中没有使用到的依赖,以此来最小化 jar 包的体积,只需要添加一项配置即可。示例如下:
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
2.3.4 relocations : 重定位 class 文件
如果最终的 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>
2.3.5 mainClass:生成可执行 jar 包
- 使用 maven-shade-plugin 后,最终生成的 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>
可执行jar包通过 java -jar 命令启动
2.3.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 资源文件附加内容 |
如果上述 12 个类都不能够满足我们的需求,我们可以实现 shade 提供的接口,按需自定义一个 ResourceTransformer,实现方法详见官网 Using your own Shader implementation。
X 参考文献/Reference Document
- Apache Maven:maven-shade-plugin
- maven-plugin-shade 详解 - CSDN
[Maven] maven插件系列之maven-shade-plugin的更多相关文章
- maven添加插件,与maven打包
1.编译插件 添加编译器插件来告诉 Maven 使用哪个 JDK 版本是用来编译项目. 2.pom <plugin> <groupId>org.apache.maven.plu ...
- maven的学习系列(二)—maven的文件夹结构
maven的文件有自己的组织方式,例如以下所看到的: ---maven ----src ---main ----java ---test ----java -----pom.xml 当运行完mvn c ...
- Maven 默认插件以及功能
Maven 默认插件 已知 Maven 使用 plugin 来执行实际操作的,在默认情况下,Maven 会绑定以下几个插件来完成基本操作. plugin function life cycle pha ...
- 【maven】插件和依赖管理
1.插件管理 定义 pluginManagement 用来做插件管理的.它是表示插件声明,即你在项目中的pluginManagement下声明了插件,Maven不会加载该插件,pluginManage ...
- IntelliJ IDEA(九) :酷炫插件系列
最近项目比较忙,很久没有更新IDEA系列了,今天介绍一下IDEA的一些炫酷的插件,IDEA强大的插件库,不仅能给我们带来一些开发的便捷,还能提高我们的与众不同. 1.插件的安装 打开setting文件 ...
- IntelliJ IDEA插件系列
参考: IntelliJ IDEA插件系列 1. activate-power-mode 和 Power mode II 根据Atom的插件activate-power-mode的效果移植到IDEA上 ...
- Maven提高篇系列之(六)——编写自己的Plugin(本系列完)
这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) ...
- [Apache Maven Shade Plugin] [example] [001] 官方例子:includes-excludes
链接地址:[Selecting Contents for Uber JAR](http://maven.apache.org/plugins/maven-shade-plugin/examples/i ...
- 施用 maven shade plugin 解决 jar 或类的多版本冲突
施用 maven shade plugin 解决 jar 或类的多版本冲突 使用 maven shade plugin 解决 jar 或类的多版本冲突java 应用经常会碰到的依赖的三方库出现版本 ...
- Maven系列(一)plugin
Maven系列(一)plugin maven-compiler-plugin 使用 mvn compile 命令,出现错误: 编码 GBK 的不可映射字符而不能编译.这是因为代码或注释中存在中文引起的 ...
随机推荐
- CVE-2021-41773 apache路径遍历
来自tryhackeme的漏洞复现 CVE-2021-41773/42013 利用:路径遍历利用将允许服务器公开任意文件 需要启用mod_cgi模块才能获得远程代码执行 2021 年 10 月 5 日 ...
- JavaWeb入门必备JavaEE规范!
前言 对于学习 Java 的同学,大都是 Web 方向的.我们学习 JavaWeb 开发肯定是一个循序渐进的过程,学习前有一些前置知识要掌握,比如 JavaSE 相关知识,HTML.CSS.JavaS ...
- 【AGC】云监控日志服务查询不到Logger日志相关问题2
[关键字] AGC.云监控.日志服务 [问题描述] 之前有开发者反馈在使用AGC云监控,填写了Logger日志,但是在云监控的日志服务查不到的问题.具体如下所述: 云函数按要求写了Logger日志, ...
- SQL ERVER 表转化为C#实体(SQL 代码)
本文推出SqlServer表转化为实体的sql代码 在VS中有可以自带生成实体类的快捷操作,但是生成的代码比较杂乱,很多东西都是不需要的,一个一个去敲又很浪费时间,关键太无聊了 在闲暇之余写一份代码供 ...
- 暗黑2能用Java开发?还能生成APP?
最近烧哥发现个宝藏项目,竟然用Java开发了暗黑2出来. 众所周知,暗黑2是暴雪开发的一款经典游戏,距今虽有20多年,仍然有很多粉丝. 粉丝延续热情的方式有很多,一种是做Mod,比如魔电,对怪物.技能 ...
- [Java基础]String,StringBuffer,StringBuilder的区别
String 和 StringBuffer/StringBuilder应该分开来看 java.lang.String源码中的注释说明 java.lang.StringBuffer源码中的注释说明 ja ...
- CF1580C Train Maintenance题解
我们以 \(\sqrt m\) 为分界点来进行平衡. 设当前在进行第 \(k\) 次操作,询问 \(i\). 对于 \(x_i + y_i \leq \sqrt m\),可以在 \(last_{x_i ...
- CVPR 2023 | RCF:完全无监督的视频物体分割
TLDR: 视频分割一直是重标注的一个task,这篇CVPR 2023文章研究了完全不需要标注的视频物体分割.仅使用ResNet,RCF模型在DAVIS16/STv2/FBMS59上提升了7/9/5% ...
- Day09_Java_作业
A:简答题 1.什么是多态,多态的前提是什么? 2.多态中成员(成员变量,成员方法,静态成员方法)的访问特点是什么? 3.多态的好处? 4.多态的弊端是什么,如果我们想访问子类的特有的功能我们应该怎么 ...
- Struts2 小知识点
配置struts.xml文件,选择开发模式 在实际应用开发或者是产品部署的时候,对应着两种模式: 开发模式(devMode):此时 DevMode=ture: 产品模式(proMode):此时 Dev ...