如何打一个FatJar(uber-jar)
FatJar也就叫做UberJar,是一种可执行的Jar包(Executable Jar)。FatJar和普通的jar不同在于它包含了依赖的jar包。
1. maven-jar-plugin
例子
<build><finalName>demo</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.0.0</version><executions><execution><id>copy-dependencies</id><phase>prepare-package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory><overWriteReleases>false</overWriteReleases><overWriteSnapshots>false</overWriteSnapshots><overWriteIfNewer>true</overWriteIfNewer></configuration></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.0.2</version><configuration><archive><manifest><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix><mainClass>com.yourcompay.Demo</mainClass></manifest></archive></configuration></plugin></plugins>
</build>
- 首先使用maven-dependency-plugin把依赖全部copy到outputDirectory中,为了将包打到一个jar中,需要把outputDirectory配置到classes/lib中
- 使用maven-jar-plugin指定MainClass和classpath,需要注意的是classpathPrefix必须是${project.build.finalName}/lib路径
- 执行命令
java -jar ./target/demo.jar
注意:采用maven-jar-plugin方式有个缺点,demo.jar不能移动到其他路径下面执行java -jar命令,因为demo.jar依赖放在了lib/目录下
解决方法有点复杂,首先用maven-dependency-plugin把依赖copy到${project.build.directory}/classes/lib,然后需要自定义jar加载的classloader,真复杂...
2. maven-assembly-plugin
maven-assembly-plugin是一个强大的打包工具,除了jar包还能打zip、tar.gz、tar.bz2等类型的包,描述文件放在assembly.xml中
如何用assembly打一个FatJar,使用预定义格式jar-with-dependencies打包
实际上
<build><finalName>demo</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.0.0</version><configuration><archive><manifest><mainClass>com.yourcompany.Demo</mainClass></manifest></archive><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins>
</build>
执行命令make clean package,得到demo-jar-with-dependencies.jar,这时我们就可以使用java -jar命令了
注意:预定义格式jar-with-dependencies实际上只有基本的FatJar打包功能,背后集成是maven-shade-plugin。下一节就讲shade-plugin
3. maven-shade-plugin
3.1 一个简单的例子
maven-shade-plugin将goal shade:shade绑定到maven的package阶段
<build><finalName>demo</finalName><plugins><plugin><artifactId>maven-shade-plugin</artifactId><version>3.0.0</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions></plugin></plugins>
</build>
执行命令maven package在target目录下生成一个demo.jar
3.2 设置MainClass创建一个可执行的Jar包
<build><finalName>demo</finalName><plugins><plugin><artifactId>maven-shade-plugin</artifactId><version>3.0.0</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>com.yourcompany.Demo</Main-Class></manifestEntries></transformer></transformers></configuration></execution></executions></plugin></plugins>
</build>
执行mvn package命令生成一个demo.jar,执行demo.jar
java -jar ./target/demo.jar
3.2.1 Resource Transformers
- AppendingTransformer 增加一个文件到resource
- XmlAppendingTransformer 增加一个xml到resource
- ManifestResourceTransformer 设置MANIFEST
3.3 使用include/exclude指定需要打包的jar
在configuration元素下增加includes和excludes节点
<configuration><artifactSet><includes><include>org.apache.commons:commons-langs</include></includes><excludes><exclude>com.alibaba:fastjson</exclude></excludes></artifactSet>
</configuration>
3.4 使用filter过滤jar包中的类或者资源
在configuration元素下增加filters节点
<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>
3.5 maven-shade-plugin 自动将所有不使用的类全部排除掉
<executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><minimizeJar>true</minimizeJar></configuration></execution>
</executions>