网上有一些maven-shade-plugin替代maven-assembly-plugin的文章,原因是代maven-assembly-plugin打出的jar包中要么是不能设置Main-Class,要么spring的META-INF/spring.*文件相互覆盖了。对于这两个问题,maven-assembly-plugin在当前的版本(3.1.0)中都可以解决了(方法见https://my.oschina.net/u/2377110/blog/1584205)。
实际上这两个插件所针对的用途其实是有差异的,而它们与maven默认的maven-jar-plugin都是打包插件,简单的区别如下:
|plugin|function| | -- | -- | |maven-jar-plugin|maven 默认打包插件,用来创建 project jar| |maven-shade-plugin|用来打可执行包,包含依赖,以及对依赖进行取舍过滤| |maven-assembly-plugin|支持定制化打包方式,更多是对项目目录的重新组装|
当你只想将项目打成一个可执行包时,maven-shade-plugin非常适合。一般情况下,pom文件中shade插件配置如下。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-shade-pluginartifactId>
<version>1.4version>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>shadegoal>
goals>
<configuration>
<filters>
<filter>
<artifact>*:*artifact>
<excludes>
<exclude>META-INF/*.SFexclude>
<exclude>META-INF/*.DSAexclude>
<exclude>META-INF/*.RSAexclude>
excludes>
filter>
filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.lcifn.ApplicationmainClass>
transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlersresource>
transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemasresource>
transformer>
transformers>
configuration>
execution>
executions>
plugin>
plugins>
build>
shade插件绑定的是package生命周期目标,并设置com.lcifn.Application为Main-Class,以及将META-INF/spring.*文件合并(追加而非覆盖),并过滤掉所有依赖的META/INF中SF,DSA,RSA后缀文件。这里涉及到filter配置和transformer配置。
Filter操作在打包时将jar包中的内容排除。它是以groupId:artifactId为标识,在filter内部可以使用
<configuration>
<filters>
<filter>
<artifact>junit:junitartifact>
<includes>
<include>junit/framework/**include>
<include>org/junit/**include>
includes>
<excludes>
<exclude>org/junit/experimental/**exclude>
<exclude>org/junit/runners/**exclude>
excludes>
filter>
filters>
configuration>
如果想将整个jar包都过滤掉,可以使用
<configuration>
<artifactSet>
<excludes>
<exclude>classworlds:classworldsexclude>
<exclude>junit:junitexclude>
<exclude>jmock:*exclude>
<exclude>*:xml-apisexclude>
<exclude>org.apache.maven:lib:testsexclude>
<exclude>log4j:log4j:jar:exclude>
excludes>
artifactSet>
configuration>
另外配置
<configuration>
<minimizeJar>trueminimizeJar>
configuration>
<configuration>
<minimizeJar>trueminimizeJar>
<filters>
<filter>
<artifact>log4j:log4jartifact>
<includes>
<include>**include>
includes>
filter>
<filter>
<artifact>commons-logging:commons-loggingartifact>
<includes>
<include>**include>
includes>
filter>
filters>
configuration>
在打包时,存在将多个构件中的class文件或资源文件聚合的需求。shade插件提供了丰富的Transformer工具类。这里介绍一些常用的Transformer。
ManifestResourceTransformer
往MANIFEST文件中写入Main-Class是可执行包的必要条件。ManifestResourceTransformer可以轻松实现。
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.lcifn.ApplicationmainClass>
transformer>
transformers>
configuration>
AppendingTransformer
用来处理多个jar包中存在重名的配置文件的合并,尤其是spring。
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlersresource>
transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemasresource>
transformer>
transformers>
configuration>
ServicesResourceTransformer
JDK的服务发现机制是基于META-INF/services/目录的,如果同一接口存在多个实现需要合并 ,则可以使用此Transformer。
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
transformers>
configuration>
更多的Transformer见http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html
默认情况下,shade插件会覆盖基于项目的jar包,而生成包含所有依赖的jar包。但有时需要原始的jar包和shade后的jar包同时被部署,可以配置如下。
<configuration>
<shadedArtifactAttached>trueshadedArtifactAttached>
<shadedClassifierName>jackofallshadedClassifierName>
configuration>
参考: