Mongoose House Technical Edition

Spring Boot DevTools简介

做 Java Web 开发恐怕最麻烦的就是修改 Java 代码后需要重新启动服务器,修改 HTML、CSS、Javascript 后需要刷新浏览器。去年下半年 Pivotal 团队发布的 Spring Boot 1.3 中加入了一个新的模块 spring-boot-devtools,旨在为程序员节省开发时间,提高开发效率。

目前 Spring Boot 1.3 中的 DevTools 主要提供四个功能,其中的自动重启(Automatic Restart)功能可以在每次修改完 Java 代码后不用再重新启动服务器,即时刷新(Live Reload)功能可以在 HTML、CSS、Javascript 等资源被修改后自动刷新浏览器。

一、简介

Spring Boot 是 Pivotal 团队为了简化 Spring 应用的初始搭建以及开发过程于 2013 年推出的一个基于 Spring Framework 的全新的框架。Spring Boot 社区发展很快,在两年多的时间里,围绕 Spring Boot 已经形成了一套生态系统,譬如 Spring Cloud 可以为 Spring Boot 应用提供丰富的 PaaS 服务(PaaS 是云计算架构中的一层,旨在为 SaaS 应用提供云环境所必需的服务,Spring Cloud 是 Spring 家族中的一个面向云计算的子项目,它提供了很多 Cloud Foudry 中的 PaaS 层的实现,Cloud Foundry 是 Pivotal 团队的云服务平台)。

去年(2015)六月份,Spring Boot 迎来了它的 1.3 版本,在这个版本中加入了被称为 spring-boot-devtools 的模块,此模块的目的是降低 Spring Boot 应用的开发强度,提高开发效率。在目前发布的 Spring Boot DevTools 中,主要提供了四个功能:

  1. 禁止缓存
  2. 自动重启
  3. 即时刷新
  4. 远程调试

1.1. 禁止缓存

当我们在 Spring Boot 应用中加入 DevTools 模块后,DevTools 模块会自动设置主流模板引擎的缓存为 false。方便之处在于,开发时加入 DevTools 模块,则自动禁止页面缓存,便于调试;上生产后,去掉 DevTools 模块则自动打开页面缓存。

目前包含的模板引擎有 thymeleaf、freemarker 等,完整列表参考类 DevToolsPropertyDefaultsPostProcessor 的实现。

1.2. 自动重启

当我们在 Spring Boot 应用中加入 DevTools 模块后,所有在 classpath 下类文件的改变都会触发 class loader 重新装载。和以前修改完 Java 代码重启服务器相比较,使用 DevTools 节省了重新起停服务器的时间,减少了每次调试中的等待时间。事实上,如果工程不是太大几乎感觉不到类被重新加载过。

另外,也可以通过设置系统变量 spring.devtools.restart.enabled 的值为 false 来禁止使用自动重启功能,设置系统变量 spring.devtools.restart.trigger-file 的值为某个特定文件,来避免过于频繁的触发类加载。譬如,当工程较大的时候,只有被指定的文件改变时才触发类加载。

更详细的说明可以参考 Spring Boot DevTools 的帮助文档

1.3. 即时刷新

当我们在 Spring Boot 应用中加入 DevTools 模块后,所有服务器上资源文件,如 HTML、CSS、Javascript 等的改变都会触发浏览器刷新。这样就使得我们不用每次都去点浏览器的刷新按钮或者按键盘上的F5

实现这点其实是通过一种叫 LiveReload 的协议完成的。Spring Boot DevTools 提供一个LiveReload 服务器,用来监视服务器资源的改变,浏览器上需要安装一个 LiveReload 客户端。以 Chrome 为例,在应用商店可以找到免费的 LiveReload 插件。

1.4. 远程调试

在现代开发中,我们更多的是使用 Docker 这样的容器来运行应用,而非直接在本地运行调试。Spring Boot DevTools 基于 jdwp 支持远程调试。

远程调试和本地调试一样,调试过程中也支持自动重启功能。当本地的类改变后,例如,修改了Java代码后,DevTools 会监视到这变化,把改变的类文件上传到远程服务器端,并重新加载。所以看起来,远程调试和本地调试一样,过程是透明的。

二、实战

本章我们实际操作,体验一下 Spring Boot DevTools 给开发者提供的便利。

2.1. 准备 Spring Boot 工程

【第一步】 从Spring网站下载对应操作系统版本的 Spring Tool Suite 并安装。

下载 Spring Tool Suite

【第二步】 启动 Spring Tool Suite,新建一个 Spring Starter Project。

新建 Spring Starter Project

【第三步】 填写项目信息。

填写项目信息

【第四步】 选择 Spring Boot 的版本和模块。简单起见,我们只选择 Web 和 DevTools 两个模块。因为 DevTools 是 Spring Boot 1.3 以后推出的功能,所以 Spring Boot 的版本要选择 1.3.0 以后的版本。

选择 Spring Boot 的版本和模块

点击完成(Finish)后,如果是第一次使用,Spring Tool Suite 会从 SPRING INITIALIZR 上下载项目模板,等待一会儿项目就建立好了。

【第五步】 选择“Run As Spring Boot Application”,可以看到工程已经可以运行了。

运行 Spring Boot Application

2.2. 自动重启

【第六步】 打开 DevToolsDemoApplication.java 文件,向其中添加一些代码,然后在浏览器中访问 http://localhost:8080,可以看到我们添加的代码成功运行了。

注意,这里没有重新启动服务器,服务器从刚才一直在运行着。

自动重启

如果看控制台的话,可以发现每次我们保存的时候,类都被重新加载了。

【第七步】 修改一下 DevToolsDemoApplication.java 文件,再刷新浏览器看看。可以发现修改后的结果反映在浏览器上。由此可以看出修改后台代码而无需重新启动服务器。

无需重启应用即可反映修改

2.3. 即时刷新

【第八步】 在体验即时刷新之前,我们首先需要给浏览器安装 LiveReload 插件。

安装 LiveReload插件

安装后,需要点击地址栏上的 LiveReload 图标,激活 LiveReload 功能。

【第九步】 现在我们再修改 DevToolsDemoApplication.java 并保存,会发现即便不刷新浏览器,我们修改的内容也会反映到浏览器上。

自动刷新

【第十步】 下面我们在 static 目录下建立一个名为 index.html 的 HTML 文件,再试验一下静态文件的 LiveReload 功能。

静态文件自动刷新

可以看到服务器的控制台没有变化,而浏览器自动显示出我们输入的内容。随着我们输入内容的变化,浏览器也实时响应我们输入的内容。

2.4. 远程调试和更新

【第十一步】 首先我们启动一台 Docker Machine 来模拟远程环境。如果没有安装 Docker 可以从 Docker 网站按提示一步一步安装 Docker Toolbox。

启动 Docker Machine

【第十二步】 接下来我们使用 mvn package 命令打包工程,并建立 Dockerfile。为了远程调试,我们需要打开 Java 虚拟机的 jdwp 服务。

制作 Docker 镜像

【第十三步】 将打包的 app 发布到 Docker 容器,在浏览器中测试,可以看到应用已经成功运行起来了。

运行 Docker 容器

【第十四步】 服务器端已经部署完毕,接下来我们需要把客户端也运行起来。

在 Spring Tool Suite 中,为了安全,需要在 application.properties 中加入密钥。

设置秘钥

然后启动客户端程序 org.springframework.boot.devtools.RemoteSpringApplication,参数设为远程服务器地址。参考Spring Boot DevTools的帮助手册

启动客户端调试程序

设置客户端调试程序参数

运行客户端调试程序后的控制台输出

【第十五步】 服务器端和客户端都部署好后,我们就可以像调试本地程序一样调试远程程序。

现在远程程序也支持自动重启和即时刷新功能。当我们在本地 Spring Tool Suite 中修改 Java 文件后,被修改后的类会自动上传到远程服务器上,并被远程服务器重新加载。

远程自动重启和刷新

【第十六步】 当我们启动 debug,则可以像调试本地程序一样调试远程应用。远程调试和更新这两个功能在我们将服务发布到云端时非常有用。避免了每次调试修改程序后还得打包重新发布的步骤,极大的减少了开发调试云应用的时间。

配置远程调试

启动远程调试