开发者工具

Spring Boot 包含一组额外的工具,可以使应用程序开发体验更加愉快。 spring-boot-devtools 模块可以包含在任何项目中,以提供额外的开发时功能。 要包含 devtools 支持,请将模块依赖项添加到你的构建中,如下面的 Maven 和 Gradle 清单所示:

Maven
<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 可能会导致类加载问题,特别是在多模块项目中。 诊断类加载问题 解释了如何诊断和解决这些问题。
当运行完全打包的应用程序时,开发者工具会自动禁用。 如果你的应用程序是从 java -jar 启动的,或者是从特殊的类加载器启动的,那么它被视为"生产应用程序"。 你可以使用 spring.devtools.restart.enabled 系统属性来控制此行为。 要启用 devtools,无论用于启动应用程序的类加载器是什么,都设置 -Dspring.devtools.restart.enabled=true 系统属性。 这不得在生产环境中完成,因为运行 devtools 存在安全风险。 要禁用 devtools,请排除依赖项或设置 -Dspring.devtools.restart.enabled=false 系统属性。
在 Maven 中将依赖项标记为可选或在 Gradle 中使用 developmentOnly 配置(如上所示)可以防止 devtools 被传递性地应用到使用你的项目的其他模块。
默认情况下,重新打包的归档文件不包含 devtools。 如果你想使用 某些远程 devtools 功能,你需要包含它。 使用 Maven 插件时,将 excludeDevtools 属性设置为 false。 使用 Gradle 插件时,配置任务的类路径以包含 developmentOnly 配置

诊断类加载问题

重启与重载 部分所述,重启功能是通过使用两个类加载器实现的。 对于大多数应用程序,这种方法效果很好。 但是,有时可能会导致类加载问题,特别是在多模块项目中。

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

属性默认值

Spring Boot 支持的几个库使用缓存来提高性能。 例如,模板引擎缓存编译后的模板以避免重复解析模板文件。 此外,Spring MVC 可以在提供静态资源时为响应添加 HTTP 缓存头。

虽然缓存在生产环境中非常有益,但在开发过程中可能会适得其反,阻止你看到刚刚在应用程序中进行的更改。 因此,spring-boot-devtools 默认禁用缓存选项。

缓存选项通常通过 application.properties 文件中的设置进行配置。 例如,Thymeleaf 提供 spring.thymeleaf.cache 属性。 spring-boot-devtools 模块会自动应用合理的开发时配置,而不是需要手动设置这些属性。

下表列出了所有应用的属性:

Name Default Value

server.error.include-binding-errors

always

server.error.include-message

always

server.error.include-stacktrace

always

server.servlet.jsp.init-parameters.development

true

server.servlet.session.persistent

true

spring.docker.compose.readiness.wait

only-if-started

spring.freemarker.cache

false

spring.graphql.graphiql.enabled

true

spring.groovy.template.cache

false

spring.h2.console.enabled

true

spring.mustache.servlet.cache

false

spring.mvc.log-resolved-exception

true

spring.reactor.netty.shutdown-quiet-period

0s

spring.template.provider.cache

false

spring.thymeleaf.cache

false

spring.web.resources.cache.period

0

spring.web.resources.chain.cache

false

如果你不希望应用属性默认值,可以在 application.properties 中将 spring.devtools.add-properties 设置为 false

因为在开发 Spring MVC 和 Spring WebFlux 应用程序时需要更多关于 Web 请求的信息,开发者工具建议你为 web 日志组启用 DEBUG 日志记录。 这将为你提供有关传入请求、处理它的处理器、响应结果和其他详细信息的信息。 如果你希望记录所有请求详细信息(包括潜在的敏感信息),可以打开 spring.mvc.log-request-detailsspring.codec.log-request-details 配置属性。

自动重启

使用 spring-boot-devtools 的应用程序会在类路径上的文件发生更改时自动重启。 这在 IDE 中工作时是一个有用的功能,因为它为代码更改提供了非常快速的反馈循环。 默认情况下,会监视指向目录的类路径上的任何条目。 请注意,某些资源(如静态资源和视图模板)不需要重启应用程序

触发重启

由于 DevTools 监视类路径资源,触发重启的唯一方法是更新类路径。 无论你使用的是 IDE 还是构建插件之一,都必须重新编译修改后的文件才能触发重启。 导致类路径更新的方式取决于你使用的工具:

  • 在 Eclipse 中,保存修改后的文件会导致类路径更新并触发重启。

  • 在 IntelliJ IDEA 中,构建项目(Build -> Build Project)具有相同的效果。

  • 如果使用构建插件,运行 mvn compile(Maven)或 gradle build(Gradle)将触发重启。

如果你使用 Maven 或 Gradle 通过构建插件重启,必须将 forking 设置为 enabled。 如果你禁用 forking,devtools 使用的隔离应用程序类加载器将不会被创建,重启将无法正常工作。
自动重启与 LiveReload 配合使用效果很好。 有关详细信息,请参阅 LiveReload 部分。 如果你使用 JRebel,则禁用自动重启以支持动态类重载。 其他 devtools 功能(如 LiveReload 和属性覆盖)仍然可以使用。
DevTools 依赖于应用程序上下文的关闭钩子来在重启期间关闭它。 如果你禁用了关闭钩子(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。
DevTools 需要自定义 ResourceLoaderApplicationContext 使用。 如果你的应用程序已经提供了一个,它将被包装。 不支持直接覆盖 ApplicationContext 上的 getResource 方法。
使用 AspectJ 织入时不支持自动重启。
重启与重载

Spring Boot 提供的重启技术通过使用两个类加载器工作。 不会更改的类(例如,来自第三方 jar 的类)被加载到 base 类加载器中。 你正在积极开发的类被加载到 restart 类加载器中。 当应用程序重启时,restart 类加载器被丢弃并创建一个新的。 这种方法意味着应用程序重启通常比"冷启动"快得多,因为 base 类加载器已经可用并已填充。

如果你发现重启对你的应用程序来说不够快,或者遇到类加载问题,你可以考虑使用 JRebel 等重载技术。 这些技术通过在加载时重写类来使它们更适合重载。

记录条件评估中的更改

默认情况下,每次应用程序重启时,都会记录一个显示条件评估增量的报告。 该报告显示当你进行更改(如添加或删除 bean 以及设置配置属性)时,应用程序的自动配置的更改。

要禁用报告的日志记录,请设置以下属性:

  • Properties

  • YAML

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

排除资源

某些资源在更改时不一定需要触发重启。 例如,Thymeleaf 模板可以就地编辑。 默认情况下,更改 /META-INF/maven/META-INF/resources/resources/static/public/templates 中的资源不会触发重启,但会触发 实时重载。 如果你想自定义这些排除项,可以使用 spring.devtools.restart.exclude 属性。 例如,要仅排除 /static/public,你可以设置以下属性:

  • Properties

  • YAML

spring.devtools.restart.exclude=static/**,public/**
spring:
  devtools:
    restart:
      exclude: "static/**,public/**"
如果你想保留这些默认值并_添加_其他排除项,请改用 spring.devtools.restart.additional-exclude 属性。

监视其他路径

你可能希望应用程序在更改不在类路径上的文件时重启或重载。 为此,使用 spring.devtools.restart.additional-paths 属性配置要监视更改的其他路径。 你可以使用 spring.devtools.restart.exclude 属性 前面描述来控制附加路径下的更改是触发完全重启还是 实时重载

禁用重启

如果你不想使用重启功能,可以使用 spring.devtools.restart.enabled 属性禁用它。 在大多数情况下,你可以在 application.properties 中设置此属性(这样做仍然会初始化重启类加载器,但它不会监视文件更改)。

如果你需要_完全_禁用重启支持(例如,因为它不能与特定库一起工作),你需要在调用 SpringApplication.run(…​) 之前将 spring.devtools.restart.enabled System 属性设置为 false,如下例所示:

  • Java

  • Kotlin

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

	public static void main(String[] args) {
		System.setProperty("spring.devtools.restart.enabled", "false");
		SpringApplication.run(MyApplication.class, args);
	}

}
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
object MyApplication {

	@JvmStatic
	fun main(args: Array<String>) {
		System.setProperty("spring.devtools.restart.enabled", "false")
		SpringApplication.run(MyApplication::class.java, *args)
	}

}

使用触发文件

如果你使用的 IDE 持续编译更改的文件,你可能更希望仅在特定时间触发重启。 为此,你可以使用"触发文件",这是一个特殊的文件,当你想要实际触发重启检查时必须修改它。

对文件的任何更新都会触发检查,但只有在 Devtools 检测到有事情要做时才会实际发生重启。

要使用触发文件,请将 spring.devtools.restart.trigger-file 属性设置为触发文件的名称(不包括任何路径)。 触发文件必须出现在你的类路径上的某个位置。

例如,如果你的项目具有以下结构:

src
+- main
   +- resources
      +- .reloadtrigger

那么你的 trigger-file 属性将是:

  • Properties

  • YAML

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

现在,只有在更新 src/main/resources/.reloadtrigger 时才会发生重启。

你可能希望将 spring.devtools.restart.trigger-file 设置为 全局设置,以便所有项目都以相同的方式运行。

一些 IDE 具有可以让你无需手动更新触发文件的功能。 Spring Tools for EclipseIntelliJ IDEA (Ultimate Edition) 都具有此类支持。 使用 Spring Tools,你可以使用控制台视图中的"重载"按钮(只要你的 trigger-file 名为 .reloadtrigger)。 对于 IntelliJ IDEA,你可以按照 其文档中的说明操作。

自定义重启类加载器

如前面在 重启与重载 部分所述,重启功能是通过使用两个类加载器实现的。 如果这导致问题,你可以使用 spring.devtools.restart.enabled 系统属性诊断问题,如果应用程序在关闭重启的情况下工作,你可能需要自定义哪些内容由哪个类加载器加载。

默认情况下,IDE 中任何打开的项目都使用"重启"类加载器加载,任何常规 .jar 文件都使用"基础"类加载器加载。 如果你使用 mvn spring-boot:rungradle bootRun,情况也是如此:包含你的 @SpringBootApplication 的项目使用"重启"类加载器加载,其他所有内容都使用"基础"类加载器加载。 启动应用程序时,类路径会打印在控制台上,这可以帮助识别任何有问题的条目。 反射使用的类,特别是注解,可以在启动时加载到父(固定)类加载器中,然后才加载使用它们的应用程序类,这可能导致 Spring 在应用程序中无法检测到它们。

你可以通过创建 META-INF/spring-devtools.properties 文件来指示 Spring Boot 使用不同的类加载器加载项目的部分内容。 spring-devtools.properties 文件可以包含以 restart.excluderestart.include 为前缀的属性。 include 元素是应该拉入"重启"类加载器的项目,exclude 元素是应该推入"基础"类加载器的项目。 属性的值是应用于启动时传递给 JVM 的类路径的正则表达式模式。 以下是一个示例,其中一些本地类文件被排除,一些额外的库被包含在重启类加载器中:

restart:
  exclude:
    companycommonlibs: "/mycorp-common-[\\w\\d-\\.]/(build|bin|out|target)/"
  include:
    projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
所有属性键必须是唯一的。 只要属性以 restart.include.restart.exclude. 开头,它就被考虑在内。
从类路径加载所有 META-INF/spring-devtools.properties。 你可以在项目内部或项目使用的库中打包文件。 不能使用系统属性,只能使用属性文件。

已知限制

重启功能不能很好地与使用标准 ObjectInputStream 反序列化的对象一起工作。 如果你需要反序列化数据,你可能需要使用 Spring 的 ConfigurableObjectInputStream 结合 Thread.currentThread().getContextClassLoader()

不幸的是,一些第三方库在不考虑上下文类加载器的情况下进行反序列化。 如果你发现这样的问题,你需要向原始作者请求修复。

LiveReload

spring-boot-devtools 模块包含一个嵌入式 LiveReload 服务器,可用于在资源更改时触发浏览器刷新。 LiveReload 浏览器扩展可以免费用于 Chrome、Firefox 和 Safari。 你可以通过在所选浏览器的市场或商店中搜索"LiveReload"来找到这些扩展。

如果你不希望在应用程序运行时启动 LiveReload 服务器,可以将 spring.devtools.livereload.enabled 属性设置为 false

你一次只能运行一个 LiveReload 服务器。 在启动应用程序之前,确保没有其他 LiveReload 服务器正在运行。 如果你从 IDE 启动多个应用程序,只有第一个具有 LiveReload 支持。
要在文件更改时触发 LiveReload,必须启用 自动重启

全局设置

你可以通过将以下任何文件添加到 $HOME/.config/spring-boot 目录来配置全局 devtools 设置:

  1. spring-boot-devtools.properties

  2. spring-boot-devtools.yaml

  3. spring-boot-devtools.yml

添加到这些文件中的任何属性都适用于使用 devtools 的机器上的_所有_ Spring Boot 应用程序。 例如,要配置重启以始终使用 触发文件,你可以将以下属性添加到你的 spring-boot-devtools 文件中:

  • Properties

  • YAML

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

默认情况下,$HOME 是用户的主目录。 要自定义此位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。

如果在 $HOME/.config/spring-boot 中找不到 devtools 配置文件,则会在 $HOME 目录的根目录中搜索 .spring-boot-devtools.properties 文件。 这允许你与不支持 $HOME/.config/spring-boot 位置的旧版本 Spring Boot 上的应用程序共享 devtools 全局配置。

devtools 属性/yaml 文件中不支持配置文件。

.spring-boot-devtools.properties 中激活的任何配置文件都不会影响 特定配置文件的加载。 不支持特定配置文件名(形式为 spring-boot-devtools-<profile>.properties)和 YAML 和 Properties 文件中的 spring.config.activate.on-profile 文档。

配置文件系统监视器

FileSystemWatcher 通过以特定时间间隔轮询类更改,然后等待预定义的静默期以确保没有更多更改来工作。 由于 Spring Boot 完全依赖 IDE 来编译和将文件复制到 Spring Boot 可以读取它们的位置,你可能会发现有时某些更改在 devtools 重启应用程序时没有反映出来。 如果你经常观察到此类问题,请尝试增加 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数以适应你的开发环境的值:

  • Properties

  • YAML

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

现在每 2 秒轮询一次受监视的类路径目录以查找更改,并保持 1 秒的静默期以确保没有额外的类更改。

远程应用程序

Spring Boot 开发者工具不仅限于本地开发。 你还可以在远程运行应用程序时使用多个功能。 远程支持是可选的,因为启用它可能存在安全风险。 它应该只在受信任的网络上运行或使用 SSL 保护时启用。 如果这两个选项都不可用,你不应该使用 DevTools 的远程支持。 你永远不应该在生产部署上启用支持。

要启用它,你需要确保 devtools 包含在重新打包的归档文件中,如下所示:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<excludeDevtools>false</excludeDevtools>
			</configuration>
		</plugin>
	</plugins>
</build>

然后你需要设置 spring.devtools.remote.secret 属性。 与任何重要的密码或密钥一样,该值应该是唯一的和强大的,不能被猜测或暴力破解。

远程 devtools 支持分为两部分:接受连接的服务器端端点和你在 IDE 中运行的客户端应用程序。 当设置 spring.devtools.remote.secret 属性时,服务器组件会自动启用。 客户端组件必须手动启动。

Spring WebFlux 应用程序不支持远程 devtools。

运行远程客户端应用程序

远程客户端应用程序设计为在 IDE 中运行。 你需要使用与你要连接的远程项目相同的类路径运行 RemoteSpringApplication。 应用程序的唯一必需参数是它连接到的远程 URL。

例如,如果你使用 Eclipse 或 Spring Tools,并且你有一个名为 my-app 的项目已部署到 Cloud Foundry,你将执行以下操作:

  • Run 菜单中选择 Run Configurations…​

  • 创建一个新的 Java Application "启动配置"。

  • 浏览 my-app 项目。

  • 使用 RemoteSpringApplication 作为主类。

  • https://myapp.cfapps.io 添加到 Program arguments(或你的远程 URL 是什么)。

正在运行的远程客户端可能类似于以下清单:

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote ::  (v3.4.6)

2025-05-26T11:11:59.413+08:00  INFO 457 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v3.4.6 using Java 21.0.7 with PID 457 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.4.6/spring-boot-devtools-3.4.6.jar started by myuser in /opt/apps/)
2025-05-26T11:11:59.416+08:00  INFO 457 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to 1 default profile: "default"
2025-05-26T11:11:59.492+08:00  INFO 457 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2025-05-26T11:11:59.500+08:00  INFO 457 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.212 seconds (process running for 0.316)
由于远程客户端使用与实际应用程序相同的类路径,它可以直接读取应用程序属性。 这就是 spring.devtools.remote.secret 属性的读取方式,并传递给服务器进行身份验证。
始终建议使用 https:// 作为连接协议,以便加密流量并且密码不会被截获。
如果你需要使用代理来访问远程应用程序,请配置 spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port 属性。

远程更新

远程客户端以与 本地重启相同的方式监视你的应用程序类路径以查找更改。 任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重启。 如果你迭代使用云服务的功能,而你在本地没有该服务,这会很有帮助。 通常,远程更新和重启比完整的重建和部署周期快得多。

在较慢的开发环境中,可能会发生静默期不够的情况,并且类中的更改可能会分批进行。 在第一批类更改上传后,服务器会重启。 下一批无法发送到应用程序,因为服务器正在重启。

这通常表现为 RemoteSpringApplication 日志中关于无法上传某些类的警告,以及随后的重试。 但它也可能导致应用程序代码不一致,并在第一批更改上传后无法重启。 如果你经常观察到此类问题,请尝试增加 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数以适应你的开发环境的值。 有关配置这些属性的信息,请参阅 配置文件系统监视器 部分。

只有在远程客户端运行时才会监视文件。 如果你在启动远程客户端之前更改文件,它不会被推送到远程服务器。