在开发项目过程中,当修改了某些代码后需要本地验证时,需要重启本地服务进行验证,启动这个
项目,如果项目庞大的话还是需要较长时间的,
spring
开发团队为我们带来了一个插件:
spring-boot devtools
,很好的解决了本地验证缓慢的问题。
一. 热部署实现演示
(一)添加spring-boot-devtools热部署依赖启动器
在
Spring Boot
项目进行热部署测试之前,需要先在项目的
pom.xml
文件中添加
spring-boot-devtools
热部署依赖启动器
:
<!-- 引入热部署依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
由于使用的是
IDEA
开发工具,添加热部署依赖后可能没有任何效果,接下来还需要针对
IDEA
开发
工具进行热部署相关的功能设置
(二)IDEA工具热部署设置
选择
IDEA
工具界面的【
File
】
->
【
Settings
】选项,打开
Compiler
面板设置页面
![](https://img-blog.csdnimg.cn/3dc29a9b84c449b6897a890e11c56cb4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
选择
Build
下的
Compiler
选项,在右侧勾选
“Build project automatically”
选项将项目设置为自动编
译,单击【
Apply
】
→
【
OK
】按钮保存设置
在项目任意页面中使用组合快捷键
“Ctrl+Shift+Alt+/”
打开
Maintenance
选项框,选中并打开
Registry
页面,具体如图
1-17
所示
![](https://img-blog.csdnimg.cn/4f19a89de887423abe0971ecf74aa8a4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
列表中找到
“compiler.automake.allow.when.app.running”
,将该选项后的
Value
值勾选,用于指
定
IDEA
工具在程序运行过程中自动编译,最后单击【
Close
】按钮完成设置
二. 热部署原理分析
该原理其实很好说明,就是我们在编辑器上启动项目,然后改动相关的代码,然后编辑器自动触发编译替换掉历史的
.class
文件后,项目检测到有文件变更后会重启
srpring-boot
项目。
可以看看官网的触发描述:
![](https://img-blog.csdnimg.cn/466b23cf5f8c4d49acaa37381b9b6006.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
可以看到,我们引入了插件后,插件会监控我们
classpath
的资源变化,当
classpath
有变化后,会触发重启
![](https://img-blog.csdnimg.cn/9748cca3530b43419c6517c12245dd54.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
这里提到了,该插件重启快速的原因:这里对类加载采用了两种类加载器,对于第三方
jar
包采用
baseclassloader
来加载,对于开发人员自己开发的代码则使用
restartClassLoader
来进行加载,这使得比停
掉服务重启要快的多,因为使用插件只是重启开发人员编写的代码部分。
验证:
package com.lagou.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;
@Component
public class Devtools implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(Devtools.class);
@Override
public void afterPropertiesSet() throws Exception {
log.info("guava-jar classLoader: " + DispatcherServlet.class.getClassLoader().toString());
log.info("Devtools ClassLoader11: " + this.getClass().getClassLoader().toString());
}
}
这边先去除
spring-boot-devtools
插件,跑下工程:
![](https://img-blog.csdnimg.cn/45707f6250314b62a75ad49797625dd8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
可以看到,
DispatcherServlet
(第三方
jar
包)和
Devtools(
自己编写的类
)
使用的都是
AppClassLoader加载的。
我们现在加上插件,然后执行下代码:
![](https://img-blog.csdnimg.cn/11517e620bbf43b9af8a56e1ebc0f03b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
发现第三方的
jar
包的类加载器确实是使用的系统的类加载器,而我们自己写的代码的类加载器为
RestartClassLoader
,并且每次重启,类加载器的实例都会改变。
![](https://img-blog.csdnimg.cn/f5ea5b33fe214694891ff7e78f944592.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZW50ZXJwYw==,size_20,color_FFFFFF,t_70,g_se,x_16)
修改代码前
.png
修改代码后.png
上图为代码修改前后类文件的变更。
三. 排除资源
某些资源在更改后不一定需要触发重新启动。例如,
Thymeleaf
模板可以就地编辑。默认情况下,改变资源
/META
-
INF/maven
,
/META
-
INF/resources
,
/resources
,
/static
,
/public
,
或
/templates
不触发重新启动,但确会触发现场重装。如果要自定义这些排除项,则可以使用该
spring.devtools.restart.exclude
属性。例如,仅排除
/static
,
/public
您将设置以下属性:
spring.devtools.restart.exclude=static/**,public/**