前言:在打包Springboot项目成jar包时需要在pom.xml使用spring-boot-maven-plugin来增加Maven功能,在我的上一篇博客<<Maven生命周期和插件的那些事(2021版)>>中已经介绍过Maven和插件的关系,在此不再赘述,感兴趣的小伙伴可以点击链接了解下。那么到底spring-boot-maven插件到底增加了哪些功能并没有深入探讨,下面针对Maven的package命令,分使用和不适用spring-boot-maven插件两种情境下的控制台输出和jar包组成简单讨论下。
以下两张图的文字描述和控制台输出可以得出:运行mvn package命令时,使用spring-boot-maven插件的打包过程比没有使用spring-boot-maven插件多了一次repackage过程,下面简单记录下repackage到底干了哪些工作?
一、首先对比下打包的成果物:
可以发现使用spring-boot-maven-plugin插件的比没有使用的场景,多了一个以.original结尾的文件,且该文件的大小与没使用spring-boot-maven插件打包的jar文件大小一样。下面对这两个大小一样的文件解压缩,解压后内容如下,可以看到解压后的内容无论是大小还是目录结构以及目录下的内容都一样。
对此我们可以得出第一个结论:spring-boot-maven-plugin的package(goal)将Maven的package命令默认实现(jar:jar)打包的重命名为XXX.jar.original
二、下面开始分析由spring-boot-maven插件打包的jar包结构如下:
没有加repackage(goal)打出的包是这样的:
加了repackage(goal)是这样的:
BOOT-INF目录下有两个子目录:classes和lib目录。lib目录存放的是应用依赖的jar包,具体参照Maven的pom.xml中的依赖内容。classes目录下存放的是项目CLASS_PATH下的内容,包括应用代码和配置文件(比如application.yml等),可以理解为repackage将原始Maven打包的jar文件中的除META-INF以外的内容放置到该目录下打包。
META-INF目录下存放的是应用相关的元信息,比如JAR包的必要配置文件MANIFEST.MF和Maven的配置文件等。
org目录下放置的与springboot应用jar加载和启动相关的类,后期会有博客专门讲解springboot应用的启动过程,会重点分析spring-boot-loader的。
根据以上控制台日志输出以及有无spring-boot-maven插件下打包形成的jar包组成可以推断,spring-boot-maven插件的repackage(goal)有如下两个作用:
1、在原始Maven打包形成的jar包基础上,进行重新打包,新形成的jar包不但包含应用类文件和配置文件,而且还会包含应用所依赖的jar包以及Springboot启动相关类(loader等),以此来满足Springboot独立应用的特性;
2、将原始Maven打包的jar重命名为XXX.jar.original作为原始文件;
打包插件pom:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.7</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
注意:
1:pom中加入repackage打的是可执行的包,MANIFEST.MF有启动类,但是可执行的包不能作为依赖引入,引入这样的jar会报错找不到类。报错:com.oceansite.system.config.ShipImoConfig
2:pom中不加repackage打的是依赖包,不可执行,MANIFEST.MF中没有启动类,但是可以当作依赖jar包引入其他项目中。
3:打包插件版本应该和springboot版本一致,否则会报版本报错。如果子模块有引入其他模块。直接子模块打包会报错找不到这个依赖(因为会从仓库里去找),需要整个项目一起打包,才能打成功。
4:若依cloud 项目中,只需要的对应的模块的pom文件中加入打包插件就可以,比如:file,像models模块下就不需要(file是models模块下的子模块),因为只是起到文件夹的作用。而且pom文件的生效是由内而外的,如果本模块下pom没有引入,并在外层pom中找
5:如果你在没有主类的公共包的pom文件中强行加入repackage,打包时会报错:Unable to find main class