SpringBoot热部署插件原理分析及实战演练
目录
1、关于热部署(Hot Deploy)产生的背景
1)热部署出现前
2)热部署出现后
2、spring-boot-devtools插件原理
1)解决变更文件自动加载到JVM中
2)spring-boot-devtools重启速度比手动重启快
3、关于LiveLoad工具
4、application.yml配置devtools
5、IDEA中设置自动编译(扩展内容)
6、实战演练
1)pom.xml配置
2) application.yml配置
SpringBoot热部署工具devtools官方文档地址:https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.devtools。
以下内容建议在本地开发调试时使用,生产环境勿用,避免出现网路安全隐患,只有在严格受信任的网络环境下才可启用。热部署工具本身的目的是用于提升开发效率,所以我们优先考虑本地开发这种场景。
1、关于热部署(Hot Deploy)产生的背景
1)热部署出现前
在没有使用热部署的情况下,一个稍微大点的项目启动就要七八秒甚至十几秒的启动时间,当然这取决于你的机器性能,不过毫无疑问,不管你的机器性能如何强大,也耗不过日益增长的项目体量,所以迫切需要无需重新启动项目也能将代码的增加修改同步到服务器的手段。
在实际开发中,我们修改某些代码逻辑功能或页面都需要重启应用,这无形中降低了开发效率。如果当我们修改代码后,服务能自动重启加载新修改的内容,而不需要重启应用,这样是不是就能大幅提高我们开发的效率呢?
这时,就出现了热部署模式。
2)热部署出现后
众所周知,热部署是在服务运行时会重新部署项目,它所针对的是容器或者整个应用,这种方式会释放内存,比热加载更加干净彻底,但同时也更费时间。若部署了新的资源或者修改了一些代码,需要在不停机的情况下的重新加载整个应用。
其原理是加载整个应用程序,包括运行需要使用到的各种文件,比如 Jar 包,JS 或者 CSS 或者 html 等静态文件或者一些配置文件等。以 Tomcat 为例,它首先校验是否开启了热部署,并且发生了修改,它有一个后台线程,定期进行 reload 检测,如果检测需要重新部署,即热部署,则先停止,然后启动,这期间会清理 session,清空内存。
那在今天我们要聊的主角spring-boot-devtools作为一款知名的热部署插件,它是如何优化的热部署方式的呢?请继续往下看。
2、spring-boot-devtools插件原理
虽然devtool工具配置简单且容易上手,但是很少有人理解其底层实现原理;为什么这么说呢?这就像我们使用每一个技术,一定有选择这个技术的理由,那就是它的诸多优点吸引了你,所以你才选择了它。
所以,在我们使用这个工具前,需要做到知其然知其所以然。否则可能仅仅是知道它能做热部署而已。
我们可以先来设想下,如果让你设计热插拔插件,你会怎么做?大致需要满足的几个要求如下,
1)代码修改完后,无需手动重启,立即(或很快)能看到修改后的效果。
2)如果是Java语言,如何将源码转换为Java中的字节码,并将其加载到JVM中?需要有具体技术实现方案。
3)还要保证自动部署比手动重启快,否则热部署就毫无意义可言了。
那在spring-boot-devtools中,是如何满足以上3个特点的呢?
1)解决变更文件自动加载到JVM中
当我们使用编译器启动项目后,在编译器上修改了代码后,编译器会将最新的代码编译成新的.class文件放到classpath下;而引入的spring-boot-devtools插件,插件会监控classpath下的资源,当classpath下的资源改变后,插件会触发重启;spring-boot-devtools使用了两个类加载器ClassLoader,一个ClassLoader加载不会发生更改的类(第三方jar包),另一个ClassLoader(restart ClassLoader)加载会更改的类(自定义的类)。后台启动一个文件监听线程(File Watcher),监测的目录中的文件发生变动时, 原来的restart ClassLoader被丢弃,将会重新加载新的restart ClassLoader。
2)spring-boot-devtools重启速度比手动重启快
我们自己启动的时候,是加载项目中所有的文件(自己编写的文件 + 所有项目依赖的jar);而加入了spring-boot-devtools插件依赖后,我们自己编写的文件的类加载器为org.springframework.boot.devtools.restart.classloader.RestartClassLoader,是这个工具包自定义的类加载器, 项目依赖的jar使用的是JDK中的类加载器(AppClassLoader\ExtClassLoader\引导类加载器)、在插件触发的重启中,只会使用RestartClassLoader来进行加载(即:只加载我们自己编写的文件部分)。从1)可知,文件变动后,第三方jar包不再重新加载,只加载自定义的类,加载的类比较少,所以重启比较快。这也是为什么,同样是重启应用,为什么不手动重启,建议使用spring-boot-devtools进行热部署重启。
3、关于LiveLoad工具
在spring-boot-devtols包中,我们发现有这样一个包: livereload。那这个包是干什么的呢?
在查阅一些资料后发现,LiveLoad是提供浏览器客户端自动加载更新的一种工具,它分为LiveLoad服务器和Liveload浏览器插件两部分;而在spring-boot-devtools中已经集成了LiveLoad服务器,所以如果我们开发的是web应用,并且期望浏览器自动刷新, 这时候可以考虑LiveLoad。
需要注意的是, 同一时间只能运行一个LiveReload服务器。开始应用程序之前,请确保没有其他LiveReload服务器正在运行。如果从IDE启动多个应用程序,则只有第一个应用程序将支持LiveReload。
4、application.yml配置devtools
spring:devtools:restart:enabled: true #设置开启热部署additional-paths: src/main/java #重启目录exclude: WEB-INF/**thymeleaf:cache: false #使用Thymeleaf模板引擎,关闭缓存
5、IDEA中设置自动编译(扩展内容)
如果使用的是IDEA开发,需开启IDEA运行时编译,然后自动重启更新;
配置路径:File->Setting->Build,Execution,Deployment->Compile
勾选选项:Make project automatically。
6、实战演练
该热部署插件在实际使用中会有一些小问题,明明已经重启,但没有生效,这种情况下,手动重启一下程序;特别是分布式开发,比如dubbo开发框架,有点问题,需要手动重启,修改完毕后,需要选中项目,在Build选项中选择Build Module。
1)pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--引入SpringBoot Parent依赖--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.7</version><relativePath/> <!-- lookup parent from repository --></parent><!--当前项目的GAV坐标--><groupId>com.xintu.demo</groupId><artifactId>springboot</artifactId><version>0.0.1-SNAPSHOT</version><!--maven项目名称,可以删除--><name>SpringBootCase</name><!--maven项目描述,可以删除--><description>Demo project for Spring Boot</description><!--maven属性配置,可以在其它地方通过${}方式进行引用--><properties><java.version>11</java.version></properties><dependencies><!--引入mybatis jar--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency><!--引入mysql jar--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency><!--SpringBoot框架web项目起步依赖,通过该依赖自动关联其它依赖,不需要我们一个一个去添加了--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--SpringBoot框架的测试起步依赖,例如:junit测试,如果不需要的话可以删除--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- SpringBoot 热部署插件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> <!-- 可以防止将devtools依赖传递到其他模块中 --></dependency></dependencies><build><plugins><!--SpringBoot提供的打包编译等插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--==========mybatis代码生成插件配置==========--><plugin><!--插件坐标--><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.5</version><!--插件依赖--><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency></dependencies><!--插件配置--><configuration><!--指定配置文件位置--><configurationFile>src/main/resources/generatorConfig.xml</configurationFile><verbose>true</verbose><overwrite>true</overwrite></configuration></plugin></plugins></build></project>
2) application.yml配置
#spring:
# profiles:
# active: test #激活对应环境配置,以测试环境为例
server:port: 8888 # 设置内嵌Tomcat端口号servlet:context-path: /springbootcase # 设置项目上下文根路径,这个在请求访问的时候需要用到test:site: 35xintu.com #测试站点user: xintu #测试用户spring:datasource: # mysql相关配置url: jdbc:mysql://localhost:3306/xintu?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456devtools:restart:enabled: true #设置开启热部署additional-paths: src/main/java #重启目录exclude: WEB-INF/** #排除一些不需要自动重启的资源log-condition-evaluation-delta: false #关闭在什么情况下重启的日志记录,需要时可以打开thymeleaf:cache: false #使用Thymeleaf模板引擎,关闭缓存#在application.yml配置文件中指定映射文件的位置,这个配置只有接口和映射文件不在同一个包的情况下,才需要指定:
mybatis:mapper-locations: classpath:mapper/*.xml
3)修改内容,查看允许效果。
时间对比,
总结:当然spring-boot-devtools除了前面提到的修改日志关闭、关闭thymeleaf缓存、排除加载目录外,还可以自定义重启类加载器、远程调试等特性,大家感兴趣可以自行研究。
相关文章:

SpringBoot热部署插件原理分析及实战演练
目录 1、关于热部署(Hot Deploy)产生的背景 1)热部署出现前 2)热部署出现后 2、spring-boot-devtools插件原理 1)解决变更文件自动加载到JVM中 2)spring-boot-devtools重启速度比手动重启快 3、关于…...

【C++ 入坑指南】(10)函数
文章目录 简介定义实例函数的分文件编写 简介 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定…...

P2233 [HNOI2002]公交车路线
题目描述 在长沙城新建的环城公路上一共有 8 个公交站,分别为 A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另外一个公交站往往要换几次车,例如从公交站 A 到公交站 D,你就至少需要…...
java入门-W11(K168-K182)网络编程
1. 网络编程入门 1.1 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统…...

距离6月18日DAMA-CDGA/CDGP认证考试还有31天,报名从速
6月18日DAMA-CDGA/CDGP数据治理认证考试开放报名中! 考试开放地区:北京、上海、广州、深圳、长沙、呼和浩特、杭州、南京、济南、成都、西安。其他地区凑人数中… DAMA-CDGA/CDGP数据治理认证班进行中,报名从速! DAMA认证为数据管…...
PO、VO、DAO、BO、DTO、POJO区分
一 分层领域模型规约: DO(Data Object):此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。BO(Business Object):业务对象,由 Service 层输出的封装…...

MobPush Flutter平台插件
集成准备 注册账号 使用PushSDK之前,需要先在MobTech官网注册开发者账号,并获取MobTech提供的AppKey和AppSecret,详情可以点击查看注册流程 MobPush后台配置 注册MobTech账号后,需要在MobTech后台进行相关信息的配置ÿ…...
机器学习面试题库:K-means
一、简述K-means算法的原理及工作流程? 原理: K-means是一个无监督的聚类算法。它的主要目的是对同一组数据对象进行分类。其原理是基于样本间的相似性来聚类分析的,即将所有样本分为K个簇,使得同一个簇间中样本相似性最高&#…...

Linux:文本三剑客之awk
Linux:文本三剑客之awk 一、awk编辑器1.1 awk概述1.2 awk工作原理1.3 awk与sed的区别 二、awk的应用2.1 命令格式2.2 awk常见的内建变量(可直接用) 三、awk使用3.1 按行输出文本3.2 按字段输出文本3.3 通过管道、双引号调用 Shell 命令 一、a…...

如何借助Kafka持久化存储K8S事件数据?
大家应该对 Kubernetes Events 并不陌生,特别是当你使用 kubectl describe 命令或 Event API 资源来了解集群中的故障时。 $ kubectl get events15m Warning FailedCreate …...

一种基于非均匀分簇和建立簇间路由的算法的无线传感器网络路由协议(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨💻4 Matlab代码 💥1 概述 本文准备了一种路由方法,该方法使传感器通过有效地使用能量将数据从发送方加载到接收器,因为它在 LEAC…...

usb摄像头驱动打印信息
usb摄像头驱动打印信息 文章目录 usb摄像头驱动打印信息 在ubuntu中接入罗技c920摄像头打印的信息如下: [ 100.873222] usb 3-2: new high-speed USB device number 5 using xhci_hcd [ 101.230728] usb 3-2: New USB device found, idVendor046d, idProduct08e5 …...
银行半结构化和无领导群面注意事项
银行可以同时报考多家,因此部分同学也积累了不少宝贵的面试“失败”经验。今天小编就来给大家说说半结构化和无领导群面的注意事项,从如信银行考试中心了解到的整理如下: 一、半结构化面试注意事项: 半结构化面试更侧重于了解考生…...

今天公司来了个拿 30K 出来的测试,算是见识到了基础的天花板
今天上班开早会就是新人见面仪式,听说来了个很厉害的大佬,年纪还不大,是上家公司离职过来的,薪资已经达到中高等水平,很多人都好奇不已,能拿到这个薪资应该人不简单,果然,自我介绍的…...

SSM整合(单元测试、结果封装、异常处理)
文章目录 1,SSM整合1.1 流程分析1.2 整合配置步骤1:创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步…...

C++ list
C list 📟作者主页:慢热的陕西人 🌴专栏链接:C 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 本博客主要内容介绍了C中list和相关接口的使用 Clist C listⅠ. li…...

【JavaScript】ES6新特性(2)
5. 字符串扩展 5.1 includes函数 判断字符串中是否存在指定字符 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name&q…...

CST-FSS/周期谐振单元的仿真
引言 这几天要仿真超表面,上下求索CST有关相关内容的教程,视频倒是有不少,不过发现很多人忽略了官方帮助文档。本文以官方帮助文档为基础,写一个有关使用CST实现FSS/超表面这类周期结构的笔记。 官方帮助文档 CST有关FSS的内容使用了一个金属谐振圆环作为例子,这是由于…...

重新理解RocketMQ Commit Log存储协议
最近突然感觉:很多软件、硬件在设计上是有root reason的,不是by desgin如此,而是解决了那时、那个场景的那个需求。一旦了解后,就会感觉在和设计者对话,了解他们的思路,学习他们的方法,思维同屏…...

ROS 开发环境搭建(虚拟机版本)(一)
相关工具,以及镜像(以后有用) 链接:https://pan.baidu.com/s/1xgtp-XGFFNCACV_-0TJO2A 提取码:ar1w 1. 下载vm虚拟机(我选择的官方最新的vm虚拟机),安装好 2.安装百度网盘里面的…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...