研究这个问题之前我们需要讨论下Spring Boot项目的打包方式。
Spring Boot打包的方式
Spring Boot默认的打包方式为fat jar,即项目的依赖jar包也会被包含在Spring Boot项目的jar包当中。Spring Boot项目的jar包结构如图所示:
如图所示,所有依赖jar包位于BOOT-INF/lib目录下。
Spring Boot默认fat jar的打包方式好处是比较多的。项目最终生成仅仅是一个文件,基本上不依赖运行环境,极大地方便了部署和上线操作。
可是这种方便的fat jar方式并不适用于各种场景。比方说我们需要将依赖的jar包独立出来,不放入最终项目的jar文件内,该怎么操作呢?
Spring Boot 依赖分离打包
这种打包方式也有专门的英语名词:thin jar。下面介绍两种thin jar的打包方式。
IDE直接分开打包
下面以Intellij IDEA为例,讲一下如何以thin jar方式打包。
打开Project Structure -> Artifacts .点击“+” -> JAR -> Empty
name起名为dep,Type选择Other。在右下方选择所有的Maven依赖包,右键选择 Put into Output Root.
同上,再次创建一个artifact,选择jar -> Empty . name 设置为project,type为jar。右下方Available Elements右键点击'Demo' compile output,选择 Put into Output Root.
配置完打包方式之后我们可以进行打包操作了。方法为点击Build菜单 -> Build Projects. Build刚刚创建的两个artifact。最终成品位于项目的out目录。
接下来问题来了,我们自定义的打包方式破坏了Spring Boot fat jar固有的结构无法直接运行了。为了解决这个问题,我们需要使用java -cp命令运行项目,手工指定classpath和main函数入口。
完整的shell脚本如下:
run.sh
# 项目的jar文件名称
libPath=package.jar
# 依赖包的位置
for jar in lib/*.jar
do
libPath=${libPath}:${jar}
done
echo ${libPath}
# main 函数的全名
java -cp ${libPath} com.paultech.MainClass
使用Spring Boot Thin Launcher
为了避免使用繁琐的shell脚本运行项目,我们可以使用Spring Boot Thin Launcher来打包Spring Boot项目。该工具的GitHub地址为:https://github.com/dsyer/spring-boot-thin-launcher
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<!-- 加入该配置,使用maven package,依赖jar不会打包在项目最终jar文件内 -->
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.12.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<!-- 加入该配置,maven package执行时会在target目录整理好依赖包 -->
<plugin>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-maven-plugin</artifactId>
<version>1.0.12.RELEASE</version>
<executions>
<execution>
<!-- Download the dependencies at build time -->
<id>resolve</id>
<goals>
<goal>resolve</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>
</plugins>
整理好的依赖包所在的目录为target/thin/root/repository
我们仍然可以使用java -jar 命令启动项目。
如果启动时需要指定依赖包的目录,可以使用如下命令:
java -Dthin.root=path/to/lib -jar spring-boot-app.jar
将path/to/lib 替换为依赖包所在的目录。
本博客为作者原创,欢迎大家参与讨论和批评指正。如需转载请注明出处。
参考资料
Spring Boot Reference. https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/
Spring Boot Thin Launcher. https://github.com/dsyer/spring-boot-thin-launcher