文章目录
- 指定版本
- 生成可执行 Jar
- 准备依赖,并指定依赖位置
- 自动下载依赖的 Jar 文件
- 打包时排除文件
- 与其他常用打包插件比较
本文是对 maven-jar-plugin
常用配置的介绍,更详细的学习请参照 Apache Maven JAR Plugin 官方文档
这是 maven 生命周期 package
阶段的默认打包插件,当不想对该插件进行自定义配置时,就不用在 pom.xml
中主动声明该插件。通常主动声明的插件想与生命周期绑定时需要进行一些配置,但这个插件不需要,其默认绑定 package
阶段
该插件不会将项目中引入的依赖打进最终的 Jar 文件
指定版本
当想指定 maven-jar-plugin
的版本时,就必须在 pom.xml
中主动声明该插件:
<build>
<plugins>
<!-- 主动声明插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
生成可执行 Jar
想通过 java -jar
命令运行 Jar 文件,就必须在 Jar 文件内的 META-INF\MANIFEST.MF
中指定入口类
通过 maven-jar-plugin
的默认配置生成 Jar 文件,其 META-INF\MANIFEST.MF
的内容为:
Manifest-Version: 1.0
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0
通过上面内容可以看到,maven-jar-plugin
的默认配置生成的 Jar 文件,其 META-INF\MANIFEST.MF
中是没有入口类的,所以无法直接运行,这种 Jar 文件的使用场景一般都是当作工具包让其他项目引用
如果想生成可执行的 Jar 文件,就必须在 pom.xml
中指明入口类,假设入口类是 App.java
,那么配置如下:
<build>
<plugins>
<!-- 主动声明插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<!-- 对插件进行个性化配置 -->
<configuration>
<archive>
<manifest>
<!-- 将入口类添加到 MANIFEST.MF 中 -->
<mainClass>com.ares5k.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
通过 mvn package
运行上面配置后,生成的 MANIFEST.MF
中多了入口类信息,内容如下:
Manifest-Version: 1.0
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0
Main-Class: com.ares5k.App
准备依赖,并指定依赖位置
文章最开始已经说过,通过 maven-jar-plugin
生成 Jar 文件时,不会将依赖包函进去
当项目中使用依赖时,如果想让最终生成的 Jar 文件可以成功运行,就需要我们提前准备好所有依赖的 Jar 文件,并放到一个固定的位置,然后在配置 maven-jar-plugin
时,指定依赖的位置,这样,当生成的 Jar 文件运行时就会到我们指定的位置中找依赖
示例,假设项目中依赖了 commons-lang3
1. 假设未来项目部署目录结构如下:
2.假设 app 存放我们生成的 Jar 文件:
3. 假设 lib 存放我们提前准备好的项目依赖的 Jar 文件:
4. 基于以上设想的未来目录结构,我们可以进行如下配置,注意,配置依赖的存放路径时,要以生成的 Jar 文件的最终存放目录(app 目录)为参照点,以相对路径的方式指定依赖的存放目录(lib 目录),这样配置后,在 app 目录下通过 java -jar 文件名
就可以正确运行程序:
<dependencies>
<!-- 依赖 commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- 主动声明插件 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<!-- 对插件进行个性化配置 -->
<configuration>
<archive>
<manifest>
<!-- 将入口类添加到 MANIFEST.MF 中 -->
<mainClass>com.ares5k.App</mainClass>
<!-- 将项目的依赖信息添加到 MANIFEST.MF 中 -->
<addClasspath>true</addClasspath>
<!-- 将依赖的存放位置添加到 MANIFEST.MF 中-->
<classpathPrefix>../lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
5. 上述配置生成的 MANIFEST.MF
中多了依赖的信息:
Manifest-Version: 1.0
Class-Path: ../lib/commons-lang3-3.12.0.jar
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0
Main-Class: com.ares5k.App
自动下载依赖的 Jar 文件
当项目中依赖比较多时,自己准备依赖 Jar 文件就很繁琐,我们可以借助 maven-dependency-plugin
插件自动帮我们下载依赖的 Jar 文件,推荐将该插件绑定到生命周期上,如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<!-- 绑定生命周期 -->
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<!-- 设置依赖的存放路径 -->
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
上面的配置在执行 mvn package
后就会自动把我们的依赖文件下载下来,不再需要自己一个个的准备了
打包时排除文件
排除文件时可以直接指定文件名,也可以通过通配符的方式排除所有满足规则的文件,设置排除文件路径时要以${project.build.outputDirectory}
为基准,默认是在 target/classes
内
<plugins>
<plugin>
<!-- 主动声明插件 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<!-- 对插件进行个性化配置 -->
<configuration>
<!-- 不想包函到 Jar 中的文件 -->
<excludes>
<!-- 直接指明要排除的文件 -->
<exclude>com/ares5k/App.class</exclude>
<exclude>env.properties</exclude>
<!-- 用通配符指定要排除的文件 -->
<exclude>com/ares5k/App.*</exclude>
<exclude>*.*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
与其他常用打包插件比较
除了 Maven 默认的 maven-jar-plugin
之外,常用的打包插件还有 maven-shade-plugin
和 spring-boot-maven-plugin
,使用方法在我其他文章中也有记录,在此将它们作一个简单的比较
maven-jar-plugin
maven 生命周期中 package
阶段的默认插件,不管是否在 pom.xml
中主动声明,也不管是否有其他的 package
阶段插件被绑定,其在 package
阶段都会被最先执行
使用 maven-jar-plugin
打包时,不会将依赖的 Jar 包添加到生成的项目 Jar 包中,所以当项目中使用依赖时,需要自己准备依赖的 Jar 包,这样 maven-jar-plugin
打出的项目 Jar 包才能被成功运行
spring-boot-maven-plugin
spring-boot-maven-plugin
是 Spring 提供的一个 Maven 打包插件,可以通过 maven 的插件命令运行,但是一般习惯将它与 maven 生命周期绑定,然后通过 maven 生命周期命令运行,它的特点是可以将项目中依赖的 Jar 包添加到最终生成的项目 Jar 包中
spring-boot-maven-plugin
主要是对 maven-jar-plugin
生成的项目 Jar 包进行二次打包,并将项目依赖的 Jar 包添加进项目的 Jar 包中
maven-shade-plugin
maven-shade-plugin
也可以将项目的依赖打进最终的项目 Jar 包中,但是其与 spring-boot-maven-plugin
不同的是,spring-boot-maven-plugin
是直接将依赖的 Jar 包放进项目的 Jar 包中,而 maven-shade-plugin
则是将依赖的 Jar 包解压,然后将解压后的文件放进最终的项目 Jar 包中
maven-shade-plugin
将依赖的 Jar 包解压后添加到项目的 Jar 包中的做法,为 maven-shade-plugin
带来了另一个重要的功能 <重命名>,因为将依赖的 Jar 包解压后都是以文件形式存在,所以 maven-shade-plugin
支持对对依赖的某个具体文件进行重命名,maven-shade-plugin
在重命名时,不只是将文件名字修改,连我们项目中对其引用的地方都会一同修改
重命名的做法可以避免版本冲突,想详细了解的可以参考我 maven-shade-plugin
的文章