前言
上一章节中,壹哥 带各位学会了配置自定义的Web端口与项目根目录,今天我们再来看看其他的一些小花样。
在开发阶段,我们编写完代码后,就得需要点击启动按钮,重启项目后才能看到更新后的内容,每次都这么操作,就会就得有点麻烦,那能不能让项目随着代码的更新而自动重启呢? 既然有了这样的需求,SpringBoot就很暖心的给我们提供了这样的功能。今天我们就来看看SpringBoot中的另一个小花样配置---实现SpringBoot项目的热加载。
注意
网上也有不少教程把该功能称为热部署,我觉得叫做热加载更准确点!
一. SpringBoot热加载简介
在SpringBoot中实现热加载相对来说是比较简单的,跟着我一步步实现吧。
1. 概述
Spring Boot为开发者提供了一个名为spring-boot-devtools的额外工具模块,使得Spring Boot应用可以支持热加载功能,以便提高开发者的开发效率,无需我们再手动重启Spring Boot应用,这提升了Spring Boot应用的开发体验。
spring-boot-devtools模块可以被引入到任何SpringBoot项目中,并提供了development-time特性。
2. 热加载原理
spring-boot-devtools之所以可以实现热加载,主要是基于以下原理机制。
热部署和热加载的底层都是基于类加载器实现的,热加载是服务器监听class等文件的改变,然后对改变的文件进行局部加载,所以不会删除session,也不会释放内存。热部署就是全局部署,会清空session以及释放内存。
所以只要我们的项目中使用了spring-boot-devtools插件,如果发现classpath下的java文件有了变动,我们的项目就会自动重启,这样我们就可以很快就能看到代码改变后的效果了。
3. 排除资源
默认情况下,classpath下任何指向文件夹的实体类都会被监控,但是一些资源的修改,尤其是静态的assets,视图模板的改变并不会触发重启应用。具体的,比如更改/META-INF/maven,/META-INF/resources ,/resources,/static,/public 或/templates下的资源不会触发重启,而是触发livereload。
所以我们可以使用spring.devtools.restart.exclude属性,来自定义重启排除规则。比如,为了只排除/static和/public,我们可以这样设置:
spring.devtools.restart.exclude=static/**,public/**
注意:
如果你想保留默认属性,并添加其他的排除规则,可以使用spring.devtools.restart.additional-exclude属性作为代替。
4. livereload简介
在devtools模块中包含一个嵌入的livereload服务器,可以在资源变化时用来触发浏览器刷新。
livereload 通过引入的脚本livereload.js,在 livereload 服务和浏览器之间建立了一个 WebSocket 连接。每当监测到文件的变动,livereload 服务就会向浏览器发送一个信号,浏览器收到信号后就刷新页面,实现了实时刷新的效果。每次启动时,需要点击对应的图标,如下图所示。
我们的浏览器需要在livereload.com网站下载安装扩展插件。Chrome浏览器在应用商店安装livereload插件后,在要自动刷新的页面点击对应的图标,启动应用后更新页面内容或者css等都会触发页面自动刷新。当然这个插件可以安装,也可以不安装。
5. 触发重启的条件
由于DevTools监控的是classpath下的资源,所以唯一触发重启的条件就是更新classpath。引起classpath更新的方式依赖于你使用的IDE工具。如果是在Eclipse里,保存一个修改的文件就会引起classpath的更新,并触发重启。如果是在IntelliJ IDEA中,构建工程(Build → Make Project)也会达到同样的效果。
当判定classpath下实体的改变是否会触发重启时,DevTools自动忽略以下工程:spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-starter。
注意:
我们也可以通过支持的构建工具(比如,Maven和Gradle)来启动应用,只要开启fork功能,因为DevTools需要一个隔离的应用类加载器执行正确的操作。Gradle默认支持该行为,按照以下配置可强制Maven插件fork进程:
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork><!-- 如果没有该配置,devtools不会生效 --></configuration></plugin></plugins></build>
6. Restart vs Reload的原理及区别
Spring Boot提供的重启技术是通过使用两个类加载器实现的。没有发生变化的类(比如那些第三方jars)会被加载进一个基础(basic) classloader里面,正在开发的类会加载进一个重启(restart) classloader里面。当应用重启时,restart类加载器会被丢弃,并创建一个新的。这种方式意味着应用重启通常比冷启动(cold starts) 快很多,因为基础类加载器已经可用,并且populated(意思是基础类加载器加载的类比较多)。
如果发现重启对于你的应用来说不够快,或遇到类加载的问题,那可以考虑reload技术,比如JRebel。这些技术是通过重写它们加载过的类来实现的,而Spring Loaded则提供了另一种实现方案,但是很多框架都不支持它,也得不到商业支持。
二. 配置实现热加载
上面的内容主要是给大家普及了Spring Boot热加载的触发条件和实现原理,接下来咱们还是来点干货,看看在代码中到底该怎么配置才能实现热加载。
1. pom.xml配置文件
首先我们要在pom.xml文件中添加热加载的依赖包和插件,并进行必要的配置,代码如下。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork><!-- 如果没有该配置,devtools不会生效 --></configuration></plugin></plugins></build>
2. yml配置
然后我们还要在application.yml文件中进行如下配置,当然如果你的配置文件是application.properties也可以,就是注意格式即可。
devtools livereload enabled true #是否支持livereload port35729 restart enabled true #是否支持热加载
3. 开启自动构建项目功能
接下来我们需要打开Intellij IDE的项目自动构建功能,请按照如下配置开启。
File-Settings-Compiler-Build project automatically
4. 配置Registry
接下来我们还有配置Registry,在这里勾选其中的一个功能,配置如下:
ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running
5. 安装livereload插件(可选)
我们可以选择安装一个浏览器上运行的livereload插件。在chrome浏览器中下载livereload插件,将其安装到chrome扩展程序中,并选中允许访问文件网址。
6. 测试
以上的配置设置完毕之后,我们就可以进行热加载功能的测试了,看看我们的配置是否有效。你可以随意编写一个Controller,效果如下:
7. 修改类内容
接着我们随便修改一下Java类中的内容,在正常情况下,就会发现代码修改后,我们的IDE控制台就会输出如下内容,表示我们的项目正在进行自动重启。
8. 修改配置文件
上面修改的是类内容,接着我们修改一下项目中的配置文件,比如application.yml或application.properties里的内容,正常情况下,会发现项目也会进行重启,这里我就不再截图展示了。
9. 修改静态文件(html、css等)
那么如果我们修改的是静态文件,html/css等,正常情况下,项目不会自动重启。但是因为我们在浏览器中安装了livereload插件,会触发调用livereload,浏览器会自动刷新,显示出我们修改后的最新内容。
10. 禁用重启
虽然这个热加载看起来蛮帅的,但是一旦我们真的用起来,其实也很操蛋,因为只要我们编写任一行代码,程序就自动重启。你想想,你哪还有心情写代码,刚写一行,程序啪就重启了,所以这个热加载其实就是挺鸡肋的一个功能,如果你不想用了怎么办呢?
如果我们不想使用这个重启特性了,可以通过‘spring.devtools.restart.enabled’
属性来禁用。通常情况下可以在application.properties文件中设置(依旧会初始化重启类加载器,但它不会监控文件变化)。
如果需要彻底禁用重启功能,比如,不能跟某个特殊库一块工作,我们可以在调用SpringApplication.run(…)之前设置一个系统属性,如下:
publicstaticvoidmain(String[] args) { System.setProperty("spring.devtools.restart.enabled", "false"); SpringApplication.run(MyApp.class, args); }
结语
至此,壹哥 就带各位了解了一下SpringBoot项目的热加载功能的实现及其底层原理。但是今天的内容,我个人感觉真的很鸡肋,反正我自己写代码时不使用这玩意,太操蛋了。有的小伙伴会问,那你写这个教程干嘛?没别的意思,就是炫技,就是任性,hiahia。感兴趣的小伙伴可以自行设置。
今日小作业:
请在自己的项目中配置热加载,感受热加载的用途,然后再禁用掉。