本文介绍dev-tools 在日常开发中的基本使用以及原理讲解,dev-tools 可以通过热加载的方式实现应用的自动重启以及和浏览器配合使用,实现热更新后页面的自动刷新,提升开发效率,早点下班,少拿996福报

基本环境:

springboot 2.x ,java 8, idea/eclipse

一,自动重启以及与实现原理

1.引入依赖
<dependencies>
  <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
  </dependency>
</dependencies>
2.devtools 实现应用的自动重启

devtools 可以对classpath 下的所有文件进行监控,当classpath下面的文件发现改变时,进行自动重启,

  • idea触发自动重启的条件为,
    Build -> Build Project
  • eclipse 触发自动重启的条件
    保存代码

有没有觉得这里的自动重启没有那么自动,我也这么觉得,因为需要手动触发 Build 才可以,自动重启,原理在后面解释

静态文件修改不需要自动重启的,可以通过如下参数设置,排斥自动加载

spring.devtools.restart.exclude=static/,public/

如果你使用的是 maven 或者gradle 自动重启, 需要将参数 forking 设置为enabled, devTools依赖于应用程序上下文的shutdown钩子来在重启期间关闭它。如果禁用了shutdown钩子,它就不能正常工作 (SpringApplication.setRegisterShutdownHook(false))

3.dev-tools 热加载实现原理:

Restart 技术(自动重启)采用了两个类加载器实现,对于有的class是不会被改变的,比如第三方依赖jar,这部分class被加载到一个 base 类加载器中,对你自己日常开发的class文件则被加载到另外一个 restart类加载器中。重启的时候,直接销毁掉restart类加载器,重新创建一个新的restart类加载器,从而实现快速重启的功能,因为 base 类加载器中的类没有发生改变,加载一次就好了

如果您发现重新启动对您的应用程序来说不够快,或者遇到类加载问题,您可以考虑ZeroTurnaround 公司的重加载技术
JRebel。这些方法是在加载类时重写它们,使它们更易于重新加载

当你使用java -jar 形式运行一个springboot 项目时 dev-tools 将被自动禁用(dev-tools根据使用的类加载器来判断是否启用,springboot以jar启动时使用的是自定义类加载器),你也可以通过系统参数进行启用,这时dev-tools 将忽略你所使用的类加载器类型:

-Dspring.devtools.restart.enabled=true

如上方式,将启动 dev-tools, dev-tools 适合在开发环境下使用,不建议在生产中启用。springboot 很多组件都提供了缓存的功能,比如 template engines, 缓存已经编译好的模板,避免了重复解析模板文件,spring mvc 也缓存了请求头信息,用来提升访问静态文件的性能, 缓存是个很好的设计,但是如果用在开发环境,会比较容易出错,写bug将变得更简单。 在开发环境,可以通过spirng-boot-devtools 配置禁用缓存。

当然,带缓存的一般都会有特定的设置可以进行禁用比如 thymeleaf, 提供了 spring.thymeleaf.cache 缓存开关,spring-boot-devtools模块不需要手动设置这些属性,而是自动应用合理的开发时配置,

更完整的默认值设置在这个文件下面:
默认值设置

二,页面自动刷新

页面自动刷新需要和浏览器插件配合使用,比如chrome 浏览器需要安装 LiveReload,需要将插件启用,如下图

springboot 一直重复启动_自动重启

浏览器插件装好后,启动springboot 项目,修改完静态文件,然后触发重新编译,页面将自动刷新,触发重新编译,不同的编译器,不同的方式,和上面的自动重启是一样的

  • idea触发自动重启的条件为,
    Build -> Build Project
  • eclipse 触发自动重启的条件
    保存代码

我们以Idea为例, 引入了dev-tools 插件的 SpringBoot 项目启动时,会同时启动一个 liveReload server 服务(这个服务为后端服务与前端浏览器插件进行交互的 websocket 服务),可以通过以下日志验证

springboot 一直重复启动_springboot 一直重复启动_02


修改文件后,重新编译项目,如下图

springboot 一直重复启动_类加载器_03


重新编译后,前端页面自动刷新,通过网络监控可以看到,这个是一个websocket协议通知触发的自动刷新

springboot 一直重复启动_自动重启_04