Skip to content

开发者工具 (Developer Tools)

Spring Boot 包含了一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot-devtools 模块可以包含在任何项目中,以提供额外的开发时特性。

1. 引入依赖

要引入 devtools 支持,请将模块依赖添加到你的构建文件中:

xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<optional>true</optional>
	</dependency>
</dependencies>
gradle
dependencies {
	developmentOnly("org.springframework.boot:spring-boot-devtools")
}

注意

在多模块项目中,Devtools 可能会导致类加载问题。请参阅诊断类加载问题以了解详情。

提示

  1. 可选依赖:将依赖标记为可选(Maven)或使用 developmentOnly(Gradle)可以防止 devtools 传递到使用该项目的其他模块。
  2. 生产禁用:打包好的应用程序(如 java -jar 或从特殊加载器启动)会自动禁用 devtools。如果需要在特定环境下强制启用重启,可以使用系统属性 -Dspring.devtools.restart.enabled=true

2. 诊断类加载问题

重启功能是通过使用两个类加载器实现的。对于大多数应用程序,这种方法运行良好。但是,它有时会导致类加载问题,特别是在多模块项目中。

要诊断类加载问题是否确实由 devtools 引起,请尝试禁用重启。如果禁用后问题解决,你可能需要自定义重启类加载器以包含你的整个项目。

3. 属性默认值

Spring Boot 支持的几个库使用缓存来提高性能。例如,模板引擎会缓存解析后的模板。虽然这在生产中很有用,但在开发中会导致你看不到实时修改。

spring-boot-devtools 默认会禁用这些缓存选项,并应用一些感知的开发配置:

属性名称默认值
management.tracing.sampling.probability1.0
server.servlet.jsp.init-parameters.developmenttrue
server.servlet.session.persistenttrue
spring.docker.compose.readiness.waitonly-if-started
spring.freemarker.cachefalse
spring.graphql.graphiql.enabledtrue
spring.groovy.template.cachefalse
spring.h2.console.enabledtrue
spring.mustache.servlet.cachefalse
spring.mvc.log-resolved-exceptiontrue
spring.reactor.netty.shutdown-quiet-period0s
spring.template.provider.cachefalse
spring.thymeleaf.cachefalse
spring.web.error.include-binding-errorsalways
spring.web.error.include-messagealways
spring.web.error.include-stacktracealways
spring.web.resources.cache.period0
spring.web.resources.chain.cachefalse

::: note 提示 如果不希望应用这些默认值,可以在 application.properties 中设置 spring.devtools.add-properties=false。 :::

4. 自动重启 (Automatic Restart)

当类路径上的文件发生更改时,应用程序会自动重启。

4.1 触发重启

触发重启的唯一方法是更新类路径。文件必须重新编译才能被探测:

  • Eclipse: 保存文件即可。
  • IntelliJ IDEA: 手动点击 Build Project (Ctrl+F9)。
  • 构建插件: 运行 mvn compilegradle build

4.2 重启 vs 重载

  • Restart (重启):Spring Boot 使用两个类加载器。Base 类加载器加载不变的第三方库;Restart 类加载器加载正在开发的类。重启时只刷新后者,速度比普通启动快得多。
  • Reload (重载):如 JRebel 等技术,直接在内存中重写类定义,不重启 JVM,速度最快但也更复杂。

4.3 记录条件评估变化 (Logging Condition Delta)

默认情况下,每次重启时都会记录一份条件评估变化报告。这可以让你看到随着你更改代码(如添加 Bean 或修改属性),自动配置发生了哪些变化。 若要禁用此报告,可以设置:

properties
spring.devtools.restart.log-condition-evaluation-delta=false

4.4 排除资源

某些资源更改时不需要重启(如 Thymeleaf 模板)。默认情况下,/META-INF/maven, /META-INF/resources, /resources, /static, /public, 或 /templates 中的更改不会触发重启,但会触发 LiveReload

自定义排除路径:

properties
spring.devtools.restart.exclude=static/**,public/**
yaml
spring:
  devtools:
    restart:
      exclude: "static/**,public/**"

4.5 监控额外路径

如果你希望在修改不在类路径上的文件时也触发重启,可以使用 spring.devtools.restart.additional-paths 属性:

properties
spring.devtools.restart.additional-paths=src/main/python

4.6 禁用重启

如果需要彻底禁用重启支持:

java
public static void main(String[] args) {
	System.setProperty("spring.devtools.restart.enabled", "false");
	SpringApplication.run(MyApplication.class, args);
}
kotlin
fun main(args: Array<String>) {
	System.setProperty("spring.devtools.restart.enabled", "false")
	runApplication<MyApplication>(*args)
}

4.7 使用触发文件

如果你希望在特定时刻才触发重启,可以设置一个“触发文件”:

properties
spring.devtools.restart.trigger-file=.reloadtrigger
yaml
spring:
  devtools:
    restart:
      trigger-file: ".reloadtrigger"

只有当你修改类路径下的 .reloadtrigger 文件时,重启才会开始。

4.8 自定义重启类加载器

如果你发现某些 JAR 需要在重启类加载器中加载,可以创建 META-INF/spring-devtools.properties

properties
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]/(build|bin|out|target)/

4.9 已知限制 (Known Limitations)

重启功能在反序列化使用标准 ObjectInputStream 加载的对象时可能存在问题。如果你需要反序列化数据,可能需要结合 Thread.currentThread().getContextClassLoader() 使用 Spring 的 ConfigurableObjectInputStream

5. 即时刷新 (LiveReload)

DevTools 包含一个嵌入式 LiveReload 服务器。当资源发生变化时,它会通知浏览器扩展刷新页面。

  • 请在浏览器商店搜索并安装 "LiveReload" 扩展。
  • 只有开启了自动重启,LiveReload 才会工作。
  • 同一时间只能运行一个 LiveReload 服务器。

6. 全局设置

你可以在用户主目录下的 $HOME/.config/spring-boot 创建 spring-boot-devtools.properties 来应用全局配置。这对你机器上的所有 Spring Boot 项目都生效。

配置分析

如果重启过于频繁或探测不准,可以调整轮询间隔和静默期:

properties
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
yaml
spring:
  devtools:
    restart:
      poll-interval: "2s"
      quiet-period: "1s"

7. 远程应用 (Remote Applications)

你可以在远程服务器上使用 DevTools 功能(如远程重启)。

安全警告

远程支持必须显式配置秘密令牌,且严禁在生产环境启用

  1. 启用:在远程包中包含 devtools 并设置秘密:
    yaml
    spring:
      devtools:
        remote:
          secret: "my-strong-secret"
  2. 连接:在 IDE 中运行 RemoteSpringApplication,并传入远程 URL。

补充教学

1. IntelliJ IDEA 的“自动编译”设置陷阱

在 IDEA 中,如果不进行以下两项配置,DevTools 可能看起来“不起作用”:

  1. 自动构建Settings -> Build, Execution, Deployment -> Compiler -> 勾选 Build project automatically
  2. 运行中构建Settings -> Advanced Settings -> 勾选 Allow auto-make to start even if developed application is currently running

    注意:在 2021 年以前的版本中,这个选项在 Registry 中(Ctrl+Shift+Alt+/ -> Registry -> compiler.automake.allow.when.app.running)。

2. 为什么有时重启后 Session 还在?

DevTools 默认启用了 server.servlet.session.persistent=true(见属性表)。这意味着它会尝试在重启间隙持久化 HTTP Session。如果你不需要这个特性,或者它导致了序列化报错(比如你的 Session 属性没实现 Serializable),可以手动将其设为 false

3. 如何解决类加载导致的 ClassCastException?

由于 Base 加载器和 Restart 加载器同时存在,如果同一个类在两个加载器中各有一份,就会报错。通常发生在你使用了反射或某些底层的序列化库时。 方案:通过 META-INF/spring-devtools.properties 中的 restart.includerestart.exclude 将相关 Jar 强制划归到一个加载器下。

Based on Spring Framework.