SpringBoot瘦身打包部署

一、前言

最近做的项目由于引入第三方库导致在运行mvn clean package 打jar时,编译出来的 Jar 包很大(服务器多达500MB)。

二、瘦身前的Jar包

SpringBoot编译出来的Jar包中,磁盘占用大的,是一些外部依赖库(jar包),例如:

进入项目工程根目录,执行 mvn clean package命令,得到的Jar包目录结构如下:

img

整个Jar包 524 MB(可以通过解压软件查看,会发现基本都是lib下的依赖包占用)

img

三、解决方法

步骤1: 正常编译JAR包,解压出lib文件夹

POM文件如下:

​
​
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>

进入项目根目录,执行命令: mvn clean package

将编译后的Jar包解压,拷贝 BOOT-INF 目录下的lib文件夹 到目标路径;

步骤2: 修改pom.xml配置,编译出不带 lib 文件夹的Jar包

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><layout>ZIP</layout><includes><include><groupId>nothing</groupId><artifactId>nothing</artifactId></include></includes></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>

配置完成后,再次执行编译:mvn clean package

生成的 Jar 包体积明显变小(还有175KB),如下所示, 外部的 jar 包已经不会被引入了:

img

img

步骤3: 运行编译后的Jar包

将 步骤1 解压出来的lib文件夹、步骤2编译的jar包放在同一个目录, 运行下面命令:

java -Dloader.path=/path/to/lib -jar /path/to/springboot-jsp-0.0.1-SNAPSHOT.jar

备注:

将/path/to/改成实际的路径。
-Dloader.path=lib文件夹路径
最终目录文件结构是:

├── lib #lib文件夹

└── springboot-jsp-0.0.1-SNAPSHOT.jar

说明

1、通常,一个工程项目架构确定后,引入的jar包基本上不会变,改变的大部分是业务逻辑;

2、后面如果需要变更业务逻辑,只需要轻量地编译工程,大大提高项目部署的效率。

四、特殊处理

1、以上步骤打包去除所有依赖包,如果想引入内部编译的依赖包可以通过includes属性进行添加,利用引用了内部的dubbo可以通过如下配置

img

配置完成后,再次执行编译:mvn clean package

结构如下:

img

2、如果引入内部包过多,也可以通过excludeGroupIds属性去掉不变的依赖包。

img

为什么瘦身打包:Spring Boot把整个项目打包成一个可运行的Jar包(即所谓的Fat Jar),导致了这个Jar包很大(通常有40M+)。如今迭代发布时常有的事情,每次都上传一个如此庞大的文件,会浪费很多时间
瘦身打包好处:springboot瘦身打包就是把工程依赖jar提取到外部进行引用,这样每次上传到服务器的文件只有十几KB

springboot瘦身打包步骤:

(1)首先备份原先的依赖(在项目的pom.xml同级目录执行命令):mvn dependency:copy-dependencies -DoutputDirectory=lib(在每个微服务下生成lib文件夹)
(2)在pom.xml中去除依赖,然后执行mvn clean package -Dmaven.test.skip=true生成jar包
(3)删除jar包中lib下的依赖jar(避免引用重复)
(4)启动jar包:java -Dloader.path=“…/lib/” -jar ErurekaService-0.0.1-SNAPSHOT-exec.jar




正常打包部署的方式

打包完jar包很大,每次上传jar包到服务器的时候都要很久。为什么呢?也许我们只是创建了一个最基本的SpirngBoot项目,也许我们只是写了三四行代码,最后生成的jar包大小也大的离谱,足足有17M,原因在于生成的可执行jar不仅包含编译之后的类,还包含了程序运行所依赖的jar包,而这大部分占比就是这些jar包。

我们通过压缩软件查看生成jar包中的内容:

slimming.jar # 17M- BOOT-INF- classes # 存放编译后的class文件 - lib # 运行需要的依赖  - classpath.idx- META-INF # 存放应用相关的辕信息,如MANIFEST.MF- org #存放Springboot相关的class文件

我们可以明显看到,导致jar包体积那么大的罪魁祸首就是这个lib,且往往我们很少改动这些依赖,频繁改动的往往是一些代码中的逻辑,因此,瘦身的思路就在于:将lib从jar中抽离出来,只需上传一次lib,其他部分的体积就微不足道了,就能够实现秒传。

瘦身部署

拿到lib目录

按照原先的maven配置方式,在target目录下生成jar。

    <build><finalName>slimming</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
$ mvn clean package

拿到BOOT-INF/lib目录。

改变默认的打包方式

    <build><finalName>slimming</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><!-- 指定项目的启动类 --><mainClass>com.hyh.SpringBootSlimmingApplication</mainClass><!-- 指定打包方式为ZIP --><layout>ZIP</layout><includes><!-- 如果有自己的依赖jar,可以再此导入 --><include><groupId>nothing</groupId><artifactId>nothing</artifactId></include></includes></configuration><executions><execution><goals><!-- 剔除其他的依赖,只保留最简单的结构 --><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>

再次打包

$ mvn clean package

此时,/target目录下的slimming.jar已经从18000K变成121K。

上传lib和jar

- lib
- slimming.jar
$ nohup java -Dloader.path=./lib -jar slimming.jar $
  • Dloader.path:告知项目运行依赖的jar包在哪。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XShell直接拖拽文件到服务器,不使用Xftp等文件上传工具

很多情况下&#xff0c;我们使用 Xshell 工具时&#xff0c;如果遇到文件的上传和下载会不可避免的要用到另外一个工具 Xftp&#xff0c;但是频繁的使用 Xftp 会比较麻烦&#xff0c;那么有没有一种更加直接简单的方法呢&#xff1f; 当我们所需要上传的文件比较小的时候&…

System.getProperty()方法获取系统变量

今天在阅读JDBC的DriverManager类源码时&#xff0c;看到了这么一句代码&#xff1a; System.getProperty(“jdbc.drivers”)&#xff1b;getProperty()这个方法是获取指定键指示的系统属性的&#xff0c;也就是说上面的代码获取的是jdbc.drivers这个属性。我写了个测试测试输…

局部变量为什么必须赋值才可以使用

在java内存模型中规定&#xff0c;一个新的变量只能在主存中初始化&#xff0c;不允许在工作内存中直接使用一个未被初始化的变量。 工作内存可以理解为局部变量定义的内存区域&#xff0c;也就是线程的工作内存。所谓局部变量就是线程私有的不共享的空间。 类加载准备阶段 类变…

Java 赋值 “=” 讲解

前言 我们从接触java第一天&#xff0c;就是到 是赋值的意思&#xff0c;把等号右边结果的值&#xff0c;赋给等号左边的变量&#xff0c;那具体是怎样赋值呢&#xff1f;你有了解过吗&#xff1f; 1.0版本 大家都知道&#xff0c;java中有 8大基本类型&#xff0c;对于基本…

Linux 系统管理命令:时间、进程、网络、磁盘、关机重启等 top命令用法详解

文章目录系统管理常用命令1. 日期1.1 查看日历: cal1.2 查看/设置时间: date2. 进程2.1 查看进程信息: ps2.2 动态显示进程信息: top2.3 终止进程: kill2.4 服务的管理: service3. 网络3.1 网卡信息查询与配置: ifconfig3.2 检测远程主机连通性: ping3.3 查看网络状态(监听端口…

Java8中计算时间的四种方式及区别Period、Duration、ChronoUnit、Until 时间区间Duration的简单使用

一.简述 在Java8中&#xff0c;我们可以使用以下类来计算日期时间差异&#xff1a; 1.Period 2.Duration 3.ChronoUnit二.Period类 Period类计算只有年、月、日 计算的是LocalDate两个时间间隔的年月日 public static void main(String[] args) {LocalDate startTime Loc…

[JAVA基础] 成员变量和局部变量(一看就懂的总结归纳篇)

引言 成员变量和局部变量在每种编程语言中都有涉及&#xff0c;如果之前了解过其他语言的成员变量或者局部变量&#xff0c;那么在学习java中的成员变量和局部变量时可以看看有那些联系和不同&#xff0c;这一块的东西也不能说难&#xff0c;如果第一次接触可能会感觉有点乱&a…

【Java多线程】内存模型JMM—主内存与工作内存分析

文章目录JAVA内存模型JVM主内存与工作内存描述JVM内存间交互规则JVM先行发生原则内存交互基本操作的 3 个特性原子性(Atomicity)可见性(Visibility)有序性(Ordering)上述内存模型与Java多线程之间的问题JAVA内存模型 共享变量&#xff1a;如果一个变量在多个线程的工作内存中都…

SpringBoot配置MyBatis的sql执行超时时间(mysql)

当某些sql因为不知名原因堵塞时&#xff0c;为了不影响后台服务运行&#xff0c;想要给sql增加执行时间限制&#xff0c;超时后就抛异常&#xff0c;保证后台线程不会因为sql堵塞而堵塞。 方法一 yml全局配置&#xff1a;单数据源可以&#xff0c;多数据源时会失效 方法二 j…

HTTP协议中的302,303状态码

之前也只知道302,303是请求重定向,但是当被问到302,303的具体区别是什么的时候我有点迷,现在就为了加强记忆,来了解下具体情况: 302是http1.0的内容&#xff0c;303是http1.1的内容。301和302本来在规范中是不允许重定向时改变请求方法的&#xff08;将POST改为GET&#xff09…

Spring自带工具类(断言、ObjectUtils、FileCopyUtils、ResourceUtils、StreamUtils、ReflectionUtils、AopUtils、AopCont)

文章目录断言对象、数组、集合文件、资源、IO 流反射、AOP断言 断言是一个逻辑判断&#xff0c;用于检查不应该发生的情况Assert 关键字在 JDK1.4 中引入&#xff0c;可通过 JVM 参数-enableassertions开启SpringBoot 中提供了 Assert 断言工具类&#xff0c;通常用于数据合法…

Arrays.asList踩坑——引发的Exception in thread “main“ java.lang.UnsupportedOperationException

Exception in thread “main” java.lang.UnsupportedOperationException 如果你尝试修改Arrays.asList方法生产的List&#xff0c;那么就会报这个错误 public static void main(String[] args) {Integer[] arr new Integer[]{7,8,9};List<Integer> list Arrays.asLi…

GIS算法:JAVA拓扑套件JTS

常用可以用于GIS数据处理和空间计算的java包有geotool和jts。 相对来说&#xff0c;geotool功能更全面&#xff0c;还可以用于数据转换、瓦片地图发布、栅格影像分析等&#xff0c;jts只能进行基本的数据处理和空间计算。 但大多数情况下jts就完全够用了。 geotool的官网&am…

Java本地远程服务器debug调试详解

日常我们debug是经常用的&#xff0c;但是本地还好说&#xff0c;远程debug就有点难度&#xff0c;而且有时候必须要在预演&#xff0c;测试环境的服务器去debug&#xff0c;举个例子&#xff0c;需要https&#xff0c;公网&#xff0c;域名之类的&#xff0c;测试服务器这些有…

Linux “ll“ 命令详解

“ls -l” “ls -al” ll 用来查询当前目录下文件及目录的详情 1.第一位文件类型 普通文件 &#xff0c; d 目录文件&#xff0c;I 链接文件&#xff0c;p 管理文件&#xff0c; b 块设备文件&#xff0c; c 字符设备文件&#xff0c; s 套接字文件 2.文件属性 第一部分表示文…

SpringBoot项目jar发布获取jar包所在目录路径

//第一种File path new File(ResourceUtils.getURL("classpath:").getPath());if(!path.exists()) path new File("");System.out.println(path.getAbsolutePath());//第二种System.out.println(System.getProperty("user.dir"));//第三种Stri…

路径classpath,classpath*,以及file:

./ 当前目录 …/上一层目录 /是根目录 1. classpath : 类路径&#xff0c;指的是编译后的字节码文件存储路径&#xff0c;一般为target目录下的classes目录&#xff08;java项目&#xff09;&#xff0c;在web项目中指的是WEB-INF下的classes目录。实际上&#xff0c;两者其实…

到底什么时候该使用MQ?

一、缘起 一切脱离业务的架构设计与新技术引入都是耍流氓。 引入一个技术之前&#xff0c;首先应该解答的问题是&#xff0c;这个技术解决什么问题。 就像微服务分层架构之前&#xff0c;应该首先回答&#xff0c;为什么要引入微服务&#xff0c;微服务究竟解决什么问题&…

Java中ByteArrayInputStream和ByteArrayOutputStream用法详解

Java中ByteArrayInputStream和ByteArrayOutputStream用法详解 这篇文章主要介绍了Java中ByteArrayInputStream和ByteArrayOutputStream用法详解&#xff0c; ByteArrayInputStream 的内部额外的定义了一个计数器&#xff0c;它被用来跟踪 read() 方法要读取的下一个字节 Byte…

Java中的Base64详解

详解Java中的Base64原理跟用法 简介 ​ Base64编码&#xff0c;是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法。它通常用作存储、传输一些二进制数据编码方法, 也是MIME&#xff08;多用途互联网邮件扩展&#xff0c;主要用…