打包可运行 jar 包的几种方式
概述
我们知道 spring boot 项目可以打包成一个可直接运行的 fat jar,事实上除了 spring boot 项目,我们自建的 maven 项目也可以打包成可运行的 jar 包,本文将介绍几个 maven 插件,以及如何利用这些插件来打包可执行 jar 包。
可以利用下面的三个 maven 插件来打包可以执行 jar 包,他们分别是:
- maven-jar-plugin
- maven-assembly-plugin
- maven-shade-plugin
maven-jar-plugin
该插件提供了构建 JAR 包的能力,但它只会编译位于 src/main/java 和 /src/main/resources/ 目录下的 Java 文件,不包括依赖的 JAR 文件。
为了创建可执行的 jar,我们先引入 maven-jar-plugin 插件,然后使用 mainClass 指定 main 方法所在类的全限定类名。下面的例子中,假设 main 方法所在的类为 net.verytools.prac.Main。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>net.verytools.prac.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
打包方法很简单,在 maven 项目根目录下执行 mvn package
即可。打包完成后通常在 target 目录下生成 jar 包,假设生成的 jar 包名称为 prac-execjar-1.0.jar,接下来运行 jar 包的命令如下:
java -jar prac-execjar-1.0.jar
前面提到了,该插件不会打包依赖的其他 jar,假如我们的项目依赖了 hutool,那么打包出来的 jar 不能直接运行,需要在 classpath 中包含 hutool 以及 hutool 本身依赖的所有 jar,才可以执行 prac-execjar-1.0.jar 中的 main 方法(假设 main 中使用到了 hutool 库中的方法)。
这个时候我们可以借助 maven-dependency-plugin 将本项目所有依赖的 jar 全部拷贝到一个指定的目录下以备使用,插件配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
通过以上配置,运行 mvn package
会将项目依赖的第三方 jar 全部拷贝到 target/lib 目录下。运行 jar 中的 main 方法有两种办法:
1、将所有的 jar 一个一个的列出来
java -cp target/lib:xx.jar:target/lib:yy.jar:prac-execjar-1.0.jar net.verytools.prac.Main
如果依赖的第三方 jar 包很多,那么这种操作简直令人窒息,好在还有第二种方案,即使用通配符
2、使用通配符
java -cp "target/lib/*:target/prac-execjar-1.0.jar" net.verytools.prac.Main
使用通配符的时候需要注意:target/lib/*
即可匹配 target/lib 目录下的所有 jar,千万不要画蛇添足使用 target/lib/*.jar
;另外一点,必须使用双引号将 -cp
的参数值括起来,否则不生效。
注意:在 windows 中需要使用分号分隔 jar,另外 windows 上的文件路径使用反斜杠,linux 中则使用的是斜杠。
java -cp "D:\path\to\lib\*" net.verytools.prac.Main
还有一点需要注意,-cp
和 -jar
这两个参数不能同时使用。
maven-assembly-plugin
使用该插件,可以将项目的所有内容以及第三方 jar 全都打包到一起成为一个 fat jar,只需要这一个 jar 便可以启动项目,是不是很 cool,配置方法如下:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>net.verytools.prac.Main</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>
运行 mvn package
打包项目,会在 target 目录下生成两个 jar:prac-execjar-1.0.jar 和 prac-execjar-1.0-jar-with-dependencies.jar, 第一个不包含第三方依赖,第二个是包含所有第三方依赖的 fat jar。只需要 fat jar 便可以启动项目:
java -jar prac-execjar-1.0-jar-with-dependencies.jar
该插件会将所有依赖的 JAR 包中的内容解压出来,并和我们项目的 class 文件放到一起。它只适用于依赖较少的项目,对于依赖较多的大型项目,可能会导致 Java 类名冲突问题。
maven-shade-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>
net.verytools.prac.Main
</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
该插件打包出来的 fat jar 又称之为 uber jar。该插件可以通过重定位类来解决冲突,另外当 JAR 包中存在具有相同名称的资源文件时,该插件还能合并资源文件。具体用法查看插件文档,以上配置展示了如何使用它来打包一个可执行的 uber jar。
ManifestResourceTransformer 用来修改 jar 中 MANIFEST.MF 文件,添加 mainClass,这样打出来才是可执行的 jar。
温馨提示:反馈需要登录