Maven学习(六) - 插件maven-shade-plugin
网上有一些maven-shade-plugin替代maven-assembly-plugin的文章,原因是代maven-assembly-plugin打出的jar包中要么是不能设置Main-Class,要么spring的META-INF/spring.*文件相互覆盖了。对于这两个问题,maven-assembly-plugin在当前的版本(3.1.0)中都可以解决了(方法见http://www.voidcn.com/article/p-nbextunx-brh.html)。
实际上这两个插件所针对的用途其实是有差异的,而它们与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.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.lcifn.Application</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</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配置。
filters和artifactSet
Filter操作在打包时将jar包中的内容排除。它是以groupId:artifactId为标识,在filter内部可以使用<include>/<exclude>更细致地控制,既可以移除代码文件,也可以移除配置文件。
<!-- 按package过滤junit包 -->
<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>
</filters>
</configuration>
如果想将整个jar包都过滤掉,可以使用<artifactSet>,也是指定groupId:artifactId的标识。
<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>
另外配置<minimizeJar>将项目中没有使用的依赖自动移除
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
<minimizeJar>可以和<filters>共同使用
<configuration> <minimizeJar>true</minimizeJar> <filters> <filter> <artifact>log4j:log4j</artifact> <includes> <include>**</include> </includes> </filter> <filter> <artifact>commons-logging:commons-logging</artifact> <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.Application</mainClass> </transformer> </transformers> </configuration>
AppendingTransformer
用来处理多个jar包中存在重名的配置文件的合并,尤其是spring。
<configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </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构件
默认情况下,shade插件会覆盖基于项目的jar包,而生成包含所有依赖的jar包。但有时需要原始的jar包和shade后的jar包同时被部署,可以配置如下。
<configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <!-- 名称会作为后缀在shade构件jar包后 --> <shadedClassifierName>jackofall</shadedClassifierName> </configuration>
参考:
- http://maven.apache.org/plugins/maven-shade-plugin/index.html
- http://www.jianshu.com/p/14bcb17b99e0