[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/exclude
2 种操作 - 支持执行通配符匹配目标依赖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 的不可映射字符而不能编译.这是因为代码或注释中存在中文引起的 ...
随机推荐
- JS加载机制
做开发多年后发现自己思维任然只定位在功能的实现:忽略了很多代码最终的实现,加载机制等 那我们接下来就借助几篇博客来理理天天看见的js:理理他究竟是怎么过执行的 一.代码检测 首先浏览器会对所有js 进 ...
- mysql安装教程【安装版】和Navicat-for-MySQL破解版
傻瓜式mysql安装教程[安装版]https://blog.csdn.net/qq_59636442/article/details/123058454 Navicat-for-MySQL下载链接:h ...
- GLIBC 升级安装与 SCL 知识盲区
前言 glibc 是 GNU 发布的 libc 库,即 c 运行库.glibc 是 linux 系统中最底层的 api,几乎其它任何运行库都会依赖于 glibc.glibc 除了封装 linux 操作 ...
- 【python基础】循环语句-for循环
1.初始for循环 for循环可以遍历任何可迭代对象,如一个列表或者一个字符串.这里可迭代对象的概念我们后期介绍,先知道这个名词就好了. 其语法格式之一: 比如我们遍历学员名单,编写程序如下所示: f ...
- 现代 C++ 性能飞跃之:移动语义
*以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/Xd_FwT8E8Yx9Vnb64h6C8w 带给现代 C++ 性能 ...
- CSS3实现嵌套立方体旋转的3D效果
刚发现一个网站上面的3D立方体效果挺好看的,就模仿着用CSS3实现了一个类似的效果:http://39.105.101.122/myhtml/CSS/transform_3D/cube_3D.html ...
- Java 使用maven模板创建web项目慢的解决方法
创建的时候在这里加上这个,使用本地仓库创建. 快捷粘贴↓↓↓ archetypeCatalog local
- 一文解开主流开源变更数据捕获技术之Flink CDC的入门使用
@ 目录 概述 定义 什么是CDC? CDC的分类 特性 应用场景 支持数据源 实战 Flink DataStream方式代码示例 FlinkSQL方式代码示例 概述 定义 flink-cdc-con ...
- JS逆向实战19——通杀webpack逆向
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 网站 aHR0cHM6Ly ...
- SpringBoot 如何优雅的进行全局异常处理?
在SpringBoot的开发中,为了提高程序运行的鲁棒性,我们经常需要对各种程序异常进行处理,但是如果在每个出异常的地方进行单独处理的话,这会引入大量业务不相关的异常处理代码,增加了程序的耦合,同时未 ...