配置热部署devtools工具
文章目录
一:什么是热部署和热加载
热部署和热加载是在应用正在运行的时候,自动更新(重新加载或者替换class等)应用的一种能力。
严格意义上,我们需要区分下热部署和热加载, 对于Java项目而言:
- 热部署
- 在服务器运行时重新部署项目
- 它是直接重新加载整个应用,这种方式会释放内存,比热加载更加干净彻底,但同时也更费时间。
- 热加载
- 在在运行时重新加载class,从而升级应用。
- 热加载的实现原理主要依赖java的类加载机制,在实现方式可以概括为在容器启动的时候起一条后台线程,定时的检测类文件的时间戳变化,如果类的时间戳变掉了,则将类重新载入。
- 对比反射机制,反射是在运行时获取类信息,通过动态的调用来改变程序行为; 热加载则是在运行时通过重新加载改变类信息,直接改变程序行为
LiveLoad是提供浏览器客户端自动加载更新的工具,分为LiveLoad服务器和Liveload浏览器插件两部分;
devtools中已经集成了LiveLoad服务器,所以如果我们开发的是web应用,并且期望浏览器自动刷新, 这时候可以考虑LiveLoad.
同一时间只能运行一个LiveReload服务器。 开始应用程序之前,请确保没有其他LiveReload服务器正在运行。
如果从IDE启动多个应用程序,则只有第一个应用程序将支持LiveReload。
二:配置devtools实现热部署
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 可以防止将devtools依赖传递到其他模块中 -->
</dependency>
</dependencies>
1:IDEA配置
如果你使用IDEA开发工具,通常有如下两种方式:
方式一: 无任何配置时,手动触发重启更新(Ctrl+F9),也可以用
mvn compile
编译触发重启更新
方式二:IDEA需开启运行时编译,自动重启更新
2:yaml配置
spring:
devtools:
restart:
enabled: true #设置开启热部署
additional-paths: src/main/java #重启目录
exclude: WEB-INF/**
thymeleaf:
cache: false #使用Thymeleaf模板引擎,关闭缓存
三:进一步理解
1:devtool的原理?为何会自动重启?
为什么同样是重启应用,为什么不手动重启,而是建议使用spring-boot-devtools进行热部署重启?
spring-boot-devtools使用了两个类加载器ClassLoader
一个ClassLoader加载不会发生更改的类(第三方jar包),另一个ClassLoader(restart ClassLoader)加载会更改的类(自定义的类)。
后台启动一个文件监听线程,监测的目录中的文件发生变动时,原来的restart ClassLoader被丢弃,将会重新加载新的restart ClassLoader。
因为文件变动后,第三方jar包不再重新加载,只加载自定义的类,加载的类比较少,所以重启比较快。
这也是为什么,同样是重启应用,为什么不手动重启,建议使用spring-boot-devtools进行热部署重启。
在自动重启中有几点需要注意:
- 自动重启会记录日志的
spring:
devtools:
restart:
log-condition-evaluation-delta: false
- 排除一些不需要自动重启的资源
某些资源在更改时不一定需要触发重新启动。
默认情况下,改变资源/META-INF/maven,/META-INF/resources,/resources,/static,/public,或/templates不触发重新启动,但确会触发现场重装。
如果要自定义这些排除项,可以使用该spring.devtools.restart.exclude属性。
spring:
devtools:
restart:
exclude: "static/**,public/**"
- 自定义重启类加载器
重启功能是通过使用两个类加载器来实现的。对于大多数应用程序,这种方法效果很好。但是,它有时会导致类加载问题。
默认情况下,IDE 中的任何打开项目都使用“重启”类加载器加载,任何常规.jar文件都使用“基本”类加载器加载。
如果你处理一个多模块项目,并且不是每个模块都导入到你的 IDE 中,你可能需要自定义一些东西。
为此,你可以创建一个META-INF/spring-devtools.properties文件。
该spring-devtools.properties文件可以包含以restart.exclude和为前缀的属性restart.include。
该include元素是应该被拉高到“重启”的类加载器的项目,以及exclude要素是应该向下推入“Base”类加载器的项目
restart:
exclude:
companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
include:
projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
2:devtool是否会被打包进Jar
devtool原则上来说应该是只在开发调试的时候使用,而在生产环境运行jar包时是不需要的
默认情况下,不会被打包进JAR
3:devtool为何会默认禁用缓存选项
Spring Boot 支持的一些库使用缓存来提高性能。例如,模板引擎缓存已编译的模板以避免重复解析模板文件。
此外,Spring MVC 可以在提供静态资源时向响应添加 HTTP 缓存标头。
虽然缓存在生产中非常有益,但在开发过程中可能会适得其反,使你无法看到刚刚在应用程序中所做的更改。
出于这个原因, spring-boot-devtools 默认禁用缓存选项。
当然如果你不想被应用属性被spring-boot-devtools默认设置,可以通过spring.devtools.add-properties到false你application.yml中
4:给所有Springboot应用做全局的配置?
可以通过将spring-boot-devtools.yml文件添加到$HOME/.config/spring-boot
目录来配置全局 devtools 设置。
添加到这些文件的任何属性都适用于你机器上使用 devtools 的所有Spring Boot 应用程序。
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
5:如果我不用devtool,还有什么选择
evtool本身基于重启方式,这种仍然不是真正的热替换方案,JRebel才是(它是收费的)
开发调试最重要的还是一种权衡
- 自动重启的开销如果和手动重启没有什么太大差别,那么还不如手动重启(按需重启)
- 多数情况下,如果是方法内部的修改或者静态资源的修改,在IDEA中是可以通过Rebuild(Ctrl + Shift + F9)进行热更的