Jtoss Jtoss
首页
  • 数据结构与算法

    • 数据结构与算法 - 概述
    • 数据结构与算法 - 复杂度分析
    • 数据结构 - 线性表
    • 算法 - 常见排序算法
  • 代码规范

    • 代码简洁之道
    • 阿里巴巴开发手册
    • 谷歌Java编程风格指南
  • 设计模式

    • 编写高质量代码概述
    • 面向对象
    • 设计原则
    • 设计模式-创建型
    • 设计模式-结构型
    • 设计模式-行为型(上)
    • 设计模式-行为型(下)
    • 浅析框架源码中的设计模式
    • 业务框架实战案例
  • MySQL 基础

    • MySQL - 数据库设计规范
    • MySQL - 必知必会
  • MySQL 进阶

    • MySQL - 基础架构
    • MySQL - InnoDB存储引擎
    • MySQL - InnoDB缓冲池
    • MySQL - 事务与锁
    • MySQL - 索引
    • MySQL - 查询执行计划
    • MySQL - 性能优化
  • Redis 系列

    • Redis入门 - 基础相关
    • Redis进阶 - 数据结构
    • Redis进阶 - 持久化RDB和AOF
    • Redis进阶 - 事件机制
    • Redis进阶 - 事务
    • Redis进阶 - 高可用高可扩展
    • Redis进阶 - 缓存问题
    • Redis进阶 - 性能调优
  • Java 基础

    • Java 基础 - 知识点
    • Java 基础 - 面向对象
    • Java 基础 - Q/A
  • Java 进阶 - 集合框架

    • Java 集合框架详解
  • Java 进阶 - 多线程与并发

    • Java 并发 - 理论基础
    • Java 并发 - 线程基础
    • Java 并发 - 各种锁
    • Java 并发 - 关键字 volatile
    • Java 并发 - 关键字 synchronized
    • JUC - CAS与原子操作
    • JUC - 锁核心类AQS
    • JUC - 锁接口和类简介
    • JUC - 并发容器简介
    • JUC - 通信工具类
    • JUC - Fork-Join框架
    • JUC - 线程池
  • Java 进阶 - JVM

    • JVM - 概述
    • JVM - 类加载机制
    • JVM - 内存结构
    • JVM - 垃圾回收机制
    • JVM - 性能调优
  • Maven系列

    • Maven基础知识
    • Maven项目构建
    • Maven多模块配置
  • Spring 框架

    • Spring 框架 - 框架介绍
    • Spring 框架 - IOC详解
    • Spring 框架 - AOP详解
    • Spring 框架 - SpringMVC详解
  • Spring Boot 系列

    • Spring Boot - 开发入门
    • Spring Boot - 接口相关
  • Spring Cloud 系列
  • Mybatis 系列

    • Mybatis - 总体框架设计
    • Mybatis - 初始化基本过程
    • Mybatis - sqlSession执行过程
    • Mybatis - 插件机制
    • Mybatis - 事务管理机制
    • Mybatis - 缓存机制
  • 业务常见问题

    • Java 业务开发常见错误(一)
    • Java 业务开发常见错误(二)
    • Java 业务开发常见错误(三)
    • Java 业务开发常见错误(四)
    • Java 业务开发常见错误(五)
    • Java 业务开发常见错误(六)
  • IDEA系列

    • IDEA 2021开发环境配置
    • IDEA 快捷键
  • Git系列

    • git status中文乱码
  • 其他

    • Typora+Picgo 自动上传图片
    • hsdis 和 jitwatch
  • 实用技巧
  • 收藏
  • 摄影
  • 学习
  • 标签
  • 归档

Jason Huang

后端程序猿
首页
  • 数据结构与算法

    • 数据结构与算法 - 概述
    • 数据结构与算法 - 复杂度分析
    • 数据结构 - 线性表
    • 算法 - 常见排序算法
  • 代码规范

    • 代码简洁之道
    • 阿里巴巴开发手册
    • 谷歌Java编程风格指南
  • 设计模式

    • 编写高质量代码概述
    • 面向对象
    • 设计原则
    • 设计模式-创建型
    • 设计模式-结构型
    • 设计模式-行为型(上)
    • 设计模式-行为型(下)
    • 浅析框架源码中的设计模式
    • 业务框架实战案例
  • MySQL 基础

    • MySQL - 数据库设计规范
    • MySQL - 必知必会
  • MySQL 进阶

    • MySQL - 基础架构
    • MySQL - InnoDB存储引擎
    • MySQL - InnoDB缓冲池
    • MySQL - 事务与锁
    • MySQL - 索引
    • MySQL - 查询执行计划
    • MySQL - 性能优化
  • Redis 系列

    • Redis入门 - 基础相关
    • Redis进阶 - 数据结构
    • Redis进阶 - 持久化RDB和AOF
    • Redis进阶 - 事件机制
    • Redis进阶 - 事务
    • Redis进阶 - 高可用高可扩展
    • Redis进阶 - 缓存问题
    • Redis进阶 - 性能调优
  • Java 基础

    • Java 基础 - 知识点
    • Java 基础 - 面向对象
    • Java 基础 - Q/A
  • Java 进阶 - 集合框架

    • Java 集合框架详解
  • Java 进阶 - 多线程与并发

    • Java 并发 - 理论基础
    • Java 并发 - 线程基础
    • Java 并发 - 各种锁
    • Java 并发 - 关键字 volatile
    • Java 并发 - 关键字 synchronized
    • JUC - CAS与原子操作
    • JUC - 锁核心类AQS
    • JUC - 锁接口和类简介
    • JUC - 并发容器简介
    • JUC - 通信工具类
    • JUC - Fork-Join框架
    • JUC - 线程池
  • Java 进阶 - JVM

    • JVM - 概述
    • JVM - 类加载机制
    • JVM - 内存结构
    • JVM - 垃圾回收机制
    • JVM - 性能调优
  • Maven系列

    • Maven基础知识
    • Maven项目构建
    • Maven多模块配置
  • Spring 框架

    • Spring 框架 - 框架介绍
    • Spring 框架 - IOC详解
    • Spring 框架 - AOP详解
    • Spring 框架 - SpringMVC详解
  • Spring Boot 系列

    • Spring Boot - 开发入门
    • Spring Boot - 接口相关
  • Spring Cloud 系列
  • Mybatis 系列

    • Mybatis - 总体框架设计
    • Mybatis - 初始化基本过程
    • Mybatis - sqlSession执行过程
    • Mybatis - 插件机制
    • Mybatis - 事务管理机制
    • Mybatis - 缓存机制
  • 业务常见问题

    • Java 业务开发常见错误(一)
    • Java 业务开发常见错误(二)
    • Java 业务开发常见错误(三)
    • Java 业务开发常见错误(四)
    • Java 业务开发常见错误(五)
    • Java 业务开发常见错误(六)
  • IDEA系列

    • IDEA 2021开发环境配置
    • IDEA 快捷键
  • Git系列

    • git status中文乱码
  • 其他

    • Typora+Picgo 自动上传图片
    • hsdis 和 jitwatch
  • 实用技巧
  • 收藏
  • 摄影
  • 学习
  • 标签
  • 归档
  • Maven系列

  • Spring 框架

  • Spring Boot

    • SpringBoot - Logback
    • SpringBoot - 热部署
      • 引入
        • 什么是热部署和热加载?
      • 配置devtools实现热部署
        • POM配置
        • application.yml配置
        • IDEA配置
        • 简单测试
        • devtools原理
      • 如果不用devtools,还有什么选择?
      • JRebel实现热部署
        • 安装插件
        • 激活插件
        • 使用插件
    • SpringBoot - 常用注解
    • SpringBoot - 接口统一返回格式
    • SpringBoot - 接口参数校验
    • SpringBoot - 接口文档之Swagger
    • SpringBoot - 接口文档之Smart-Doc
    • SpringBoot - 接口版本
  • Spring Cloud

  • Spring
  • Spring Boot
Jason
目录

SpringBoot - 热部署

# SpringBoot - 热部署

# 引入

平时使用SpringBoot开发应用时,修改代码后需要重新启动才能生效。如果你的应用足够大的话,启动可能需要好几分钟。有没有什么办法可以加速启动过程,让我们开发应用代码更高效呢?下面介绍两个热部署工具,一个是SpringBoot官方的热部署工具spring-boot-devtools实现修改完代码后快速自动重启应用;另一个是JRebel 实现修改完代码后快速热加载变更的类,无需重启应用。

# 什么是热部署和热加载?

热部署和热加载是在应用正在运行的时候,自动更新(重新加载或者替换class等)应用的一种能力。(PS:spring-boot-devtools提供的方案也是要重启的,只是无需手动重启能实现自动加载而已。)

严格意义上,我们需要区分下热部署和热加载, 对于Java项目而言:

  • 热部署
    • 在服务器运行时重新部署项目
    • 它是直接重新加载整个应用,这种方式会释放内存,比热加载更加干净彻底,但同时也更费时间。
  • 热加载
    • 在在运行时重新加载class,从而升级应用。
    • 热加载的实现原理主要依赖java的类加载机制,在实现方式可以概括为在容器启动的时候起一条后台线程,定时的检测类文件的时间戳变化,如果类的时间戳变掉了,则将类重新载入。
    • 对比反射机制,反射是在运行时获取类信息,通过动态的调用来改变程序行为; 热加载则是在运行时通过重新加载改变类信息,直接改变程序行为。

# 配置devtools实现热部署

# POM配置

添加spring-boot-devtools的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional> <!-- 可以防止将devtools依赖传递到其他模块中 -->
    </dependency>
</dependencies>
1
2
3
4
5
6
7

# application.yml配置

spring:
  devtools:
    restart:
      enabled: true  # 设置开启热部署
      additional-paths: src/main/java # 指定热部署的目录
      exclude: test/** # 指定目录不更新
1
2
3
4
5
6

# IDEA配置

方式一:无任何配置时,手动触发重启更新(cmd+F9)

springboot-devtools1

方式二: IDEA需开启运行时编译,自动重启更新(保存文件后触发)

IDEA设置中的 Build,Execution,Deployment->Compile,勾选:Build project automatically

springboot-devtools2

IDEA设置中的Advanced Setttings里面的第一个设置:

springboot-devtools3

# 简单测试

@RestController
public class DemoController {
    @GetMapping("/demo")
    public String demo() {
        String message = "hello";
        return message;
    }
}
1
2
3
4
5
6
7
8

启动项目后,使用的加载器变为了 restartedMain 了,说明热部署已经成功。

springboot-devtools4

浏览器访问接口地址输出字符串hello,修改字符串为hello world后保存文件或cmd+F9,刷新浏览器请求的接口可以看到输出变了(需要等一会,因为项目会自动重启一下)。

从实际场景考虑,其实不需要一直自动热部署,使用手动触发即可。

# devtools原理

spring-boot-devtools使用了两个类加载器ClassLoader,一个ClassLoader加载不会发生更改的类(第三方jar包),另一个ClassLoader(restart ClassLoader)加载会更改的类(自定义的类)。

后台启动一个文件监听线程(File Watcher),监测的目录中的文件发生变动时, 原来的restart ClassLoader被丢弃,将会重新加载新的restart ClassLoader。

因为文件变动后,第三方jar包不再重新加载,只加载自定义的类,加载的类比较少,所以重启比较快。这也是为什么,同样是重启应用,为什么不手动重启,建议使用spring-boot-devtools进行热部署重启。

# 如果不用devtools,还有什么选择?

在实际的开发过程中,一般去使用devtool工具, 因为:

  • devtool本身基于重启方式,这种仍然不是真正的热替换方案,JRebel才是(它是收费的,可通过代理破解,后面文章介绍)
  • 开发调试最重要的还是一种权衡
    • 自动重启的开销如果和手动重启没有什么太大差别,那么还不如手动重启(按需重启)
    • 多数情况下,如果是方法内部的修改或者静态资源的修改,在IDEA中是可以通过Rebuild(Ctrl + Shift + F9)进行热更的

# JRebel实现热部署

# 安装插件

springboot-jrebel2

# 激活插件

springboot-jrebel6

  • 步骤一:生成一个GUID:在线生成GUID地址 (opens new window)
  • 根据反向代理服务器地址拼接激活地址,服务器地址:https://jrebel.qekang.com/{你生成的GUID}

# 使用插件

将我们的项目使用JRebel进行管理项目,勾选上。

springboot-jrebel4

使用JRebel插件启动项目:

springboot-jrebel3

修改java文件后,手动触发编译:Shift+Cmd+F9 即可。

源码可见:https://github.com/hengwen/spring-demo/tree/main/sprintboothotdeploy

#Spring Boot#热部署
上次更新: 2024-08-19
SpringBoot - Logback
SpringBoot - 常用注解

← SpringBoot - Logback SpringBoot - 常用注解→

最近更新
01
开始
01-09
02
AI工具分享
01-09
03
AI 导读
01-07
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Jason Huang | 闽ICP备2025088096号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式