目录
[Springboot fat jar](#Springboot fat jar)
Spring boot fat ja r
Springboot fat jar打包的时候可以把项目本身jar和所需依赖的jar包都打包到同一个spring fat jar中。而传统的jar包只包含项目本身自己的代码部分,运行时需要手动添加并指定依赖和配置应用服务器等。而 fat Jar 是一个自包含、可独立运行的jar文件。也就是 fat Jar = 应用代码 + 所有依赖 + 内嵌服务器 + 启动器。
优势
- 部署简单:一个jar文件搞定,无需安装 Tomcat
- 环境一致:开发、测试、生产环境完全一致
- 快速启动:java -jar 即可运行
- 微服务友好:适合容器化(Docker)方便快速部署。
- 快速启动:java -jar 即可运行
- 环境一致:开发、测试、生产环境完全一致
劣势
不方便增量替换jar,许多jar(如Spring自己的jar)都带有数字签名。替换后,签名文件(META-INF/*.SF, *.RSA)与内容不匹配,导致安全校验失败则jar启动失败。需要通过jar本身提供的命令进行替换内部依赖的jar包得操作,这样就比较麻烦。
为什么会有增量替换依赖jar这种需求?有的客户喜欢做增量升级,比如一个项目有30个jar,但是升级功能所需的代码部分只涉及5个jar包,所以客户就想只替换这个5个jar包完成服务升级。这样做的好处就是:jar包体积小方便内网或邮件传输(每次邮件到内网附件大小还有限制),代码改动范围的风险可控。
普通jar
普通jar打包的时候,当前项目包含启动器部分的代码会自行打包一个jar包内。而项目运行所需的依赖jar包会打到指定的位置,运行时通过java -cp 命令指定classpath去加载这些依赖的jar。
优势
这里能想到的优势就是方便快速替换增量的jar做版本迭代,jar包体积小方便内网传输,做到代码改动范围的风险可控。尤其是对大型多模块的maven项目来说,项目自身代码就有很多模块这种,可以考虑以这种方式打包。
劣势
个人感觉除了优势以外对比springboot fat jar就都是劣势了。
如何打包
比如我要将项目运行时除项目本身的jar以外的所需的依赖jar都打包到指定的位置,比如项目工作目录下的libs目录下,方式有以下两种。
maven-dependency-plugin 插件
XML
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>
runtime
</includeScope>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
//这里可以控制各种打包的过滤条件:详情请参考仓库位置:org\apache\maven\plugins\maven-dependency-plugin\版本\maven-dependency-plugin-xxx.jar!\META-INF\maven\plugin.xml
</configuration>
</execution>
</executions>
</plugin>
maven-assembly-plugin 插件
相比 maven-dependency-plugin 插件,maven-assembly-plugin 则更加灵活,不仅可以控制依赖的jar包,还可以控制单个文件、多个文件、以及目录等等。这样在打包的时候更加灵活。请参考之前的博文:https://blog.csdn.net/weixin_38357164/article/details/156639593?fromshare=blogdetail&sharetype=blogdetail&sharerId=156639593&sharerefer=PC&sharesource=weixin_38357164&sharefrom=from_link
代码例子如下:
XML
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>xxx</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/resources/assembly-xxx.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
然后在项目main/resources目录下创建assembly-xxx.xml文件。在文件中定义打包的逻辑,代码例子如下:
XML
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>hengShengBank</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>dir</format>
</formats>
<dependencySets>
<dependencySet>
<!--构建包时不包含项目自身的jar,也就是项目本身的jar单独打到默认的target目录下-->
<useProjectArtifact>false</useProjectArtifact>
<!--将scope为runtime的所有依赖包打到libs目录下-->
<outputDirectory>libs</outputDirectory>
<!--这里可以配置过滤条件-->
<excludes>
<exclude>依赖的groupId:依赖的artifactId</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
插件综合对比
| 特性 | maven-dependency-plugin | maven-assembly-plugin |
|---|---|---|
| 主要目的 | 管理依赖关系 | 创建分发包 |
| 输出格式 | 复制文件到目录 | ZIP, TAR, JAR, WAR等归档格式 |
| 包含内容 | 主要是依赖JAR | 依赖 + 项目构建输出 + 任意文件 |
| 使用场景 | 依赖分析、复制、解压 | 制作完整发布包、安装包 |
| 控制粒度 | 依赖级别控制 | 文件级别控制 |
| 典型任务 | copy-dependencies, unpack |
single, dir |
插件打包功能对比
| 打包特性 | maven-dependency-plugin | maven-assembly-plugin |
|---|---|---|
| 创建归档文件 | 只能复制文件 | 主要功能 |
| 多种格式支持 | ZIP, TAR, JAR等 | |
| 自定义目录结构 | 只能指定输出目录 | 完整目录结构控制 |
| 包含任意文件 | 只能处理依赖 | 通过fileSet支持 |
| 多模块打包 | 通过moduleSet支持 | |
| 文件权限设置 | 支持Unix/Windows权限 | |
| 文件过滤 | includes/excludes | 更强大的过滤选项 |
| 属性过滤 | 支持属性替换 |
后续会出一个maven插件详解的文章~敬请期待!
======================
喜欢求个关注,回归持续更新
======================