概述
热加载,也叫开发者模式,即在本地开发时,改动代码后,不需要重启应用程序,就可以快速验证改动效果的模式。本文不考虑使用Eclipse等其他IDE,只考虑IDEA。熟练掌握IDEA的热加载,可以大大提供编码效率,不加班,腾出时间学习。
方案
此处给出结论,本人使用IDEA自带的热加载,并配置好Mybatis Mapper热加载(如果项目用到的话)。其他方案,知道有这么个东西。
IDEA
使用IDEA自带的热加载功能-Debug模式,点击编辑 configuration,修改如下配置:
优点:简单,无需装任何插件;
缺点:无法对配置文件,Mybatis mapper xml,Controller接口方法新增,命名改变,POJO新增字段进行热加载,使用范围有限。
Mybatis mapper
参考Mybatis系列之mapper.xml实现热加载HotSwap
spring-boot-devtools
SB项目中添加spring-boot-devtools
依赖即可实现页面和代码的热加载:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
控制台输出:
[restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
优点:作用范围广,系统的任何变动包括配置文件修改、方法名称变化都能覆盖;
缺点:采用文件变化后重启的策略来实现,节省手动点击重启的时间,提高实效性,在体验上会稍差。
原理:
没有采用热加载的方式,而是一种较快的重启方式。Spring Boot通过使用两个类加载器来提供重启技术:
- 不改变的类(如第三方jar)被加载到 base 类加载器中;
- 经常处于开发状态的类被加载到 restart 类加载器中。
当应用重启时,restart 类加载器将被丢弃,并重新创建一个新的。这意味着应用重启比冷启动要快得多,因为省去 base 类加载器的处理步骤,并且可以直接使用。
如果您觉得重启还不够快,或者遇到类加载问题,您可以考虑如 的 JRebel 等工具。他们是通过在加载类时重写类来加快重新加载。
spring-boot-devtools
默认关闭模版缓存,使用这种方式不用单独配置关闭模版缓存。
DevTools在重启过程中依赖于applicationContext的shutdownHook,如果设置SpringApplication.setRegisterShutdownHook(false)
,则自动重启将不起作用。
HotSwap
IDEA的插件。除安装插件外,还需要安装个什么DCEVM。
没怎么用。
模板热加载
在SB中,模板引擎的页面默认是开启缓存的。修改页面的内容后刷新页面是得不到修改后的页面的,在application.properties
中关闭模版引擎的缓存:
spring.thymeleaf.cache=false
spring.freemarker.cache=false
spring.groovy.template.cache=false
spring.velocity.cache=false
在Spring Boot集成Thymeleaf时,spring.thymeleaf.cache
属性设置为false可以禁用模板引擎编译的缓存结果。
现在,devtools会自动帮你做到这些,禁用所有模板的缓存,参考DevToolsPropertyDefaultsPostProcessor
Spring Loaded
此种方式与Debug模式类似,适用范围有限,但是不依赖于Debug模式启动,通过Spring Loaded库文件启动,即可在正常模式下进行实时热部署。此种需要在 run configuration 中进行配置。
JRebel
ZeroTurnAround公司的产品,另外还有一个XRebel。通过在加载类时重写类来加快重新加载。
参考IDEA使用插件JRebel热部署失败的问题排查
引申
减少控制台打印输出
如果项目使用logback,则加入如下配置信息:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- <property resource="application.properties" /> -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level][%thread]:%logger{50} [%method:%line] %msg%n</pattern>
</encoder>
</appender>
<appender name="KafkaAppender" class="com.ppdai.logclient.logback.KafkaAppender">
<layout>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</layout>
<manualStart>true</manualStart>
</appender>
<!-- 下面配置一些第三方包的日志过滤级别,用于避免刷屏 -->
<logger name="org.apache" level="WARN"/>
<logger name="org.mongodb" level="WARN"/>
<logger name="com.alibaba" level="WARN"/>
<logger name="org.springframework" level="WARN"/>
</configuration>
一定程度上可以加速项目重启时间。
当然加上Spring Boot embedded fat jar的大小,也可以加快应用启动。
热部署、热加载、热更新
热更新是游戏专用词。
Java热部署与Java热加载的联系和区别
联系
- 不重启服务器编译/部署项目
- 基于Java的类加载器实现
区别
- 部署方式
热部署在服务器运行时重新部署项目
热加载在运行时重新加载class - 实现原理
热部署直接重新加载整个应用
热加载在运行时重新加载class - 使用场景
热部署更多的是在生产环境使用
热加载则更多的实在开发环境使用 - 安全性
热加载几乎没有安全性,直接修改Java虚拟机中的字节码文件,难以监控和控制;热加载有个通俗的名字就是开发者模式。