开发者工具
Spring Boot 包含一组额外的工具,可以使应用程序开发体验更加愉快。
spring-boot-devtools
模块可以包含在任何项目中,以提供额外的开发时功能。
要包含 devtools 支持,请将模块依赖项添加到你的构建中,如下面的 Maven 和 Gradle 清单所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
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 配置。
|
属性默认值
Spring Boot 支持的几个库使用缓存来提高性能。 例如,模板引擎缓存编译后的模板以避免重复解析模板文件。 此外,Spring MVC 可以在提供静态资源时为响应添加 HTTP 缓存头。
虽然缓存在生产环境中非常有益,但在开发过程中可能会适得其反,阻止你看到刚刚在应用程序中进行的更改。 因此,spring-boot-devtools 默认禁用缓存选项。
缓存选项通常通过 application.properties
文件中的设置进行配置。
例如,Thymeleaf 提供 spring.thymeleaf.cache
属性。
spring-boot-devtools
模块会自动应用合理的开发时配置,而不是需要手动设置这些属性。
下表列出了所有应用的属性:
Name | Default Value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
如果你不希望应用属性默认值,可以在 application.properties 中将 spring.devtools.add-properties 设置为 false 。
|
因为在开发 Spring MVC 和 Spring WebFlux 应用程序时需要更多关于 Web 请求的信息,开发者工具建议你为 web
日志组启用 DEBUG
日志记录。
这将为你提供有关传入请求、处理它的处理器、响应结果和其他详细信息的信息。
如果你希望记录所有请求详细信息(包括潜在的敏感信息),可以打开 spring.mvc.log-request-details
或 spring.codec.log-request-details
配置属性。
自动重启
使用 spring-boot-devtools
的应用程序会在类路径上的文件发生更改时自动重启。
这在 IDE 中工作时是一个有用的功能,因为它为代码更改提供了非常快速的反馈循环。
默认情况下,会监视指向目录的类路径上的任何条目。
请注意,某些资源(如静态资源和视图模板)不需要重启应用程序。
如果你使用 Maven 或 Gradle 通过构建插件重启,必须将 forking 设置为 enabled 。
如果你禁用 forking,devtools 使用的隔离应用程序类加载器将不会被创建,重启将无法正常工作。
|
自动重启与 LiveReload 配合使用效果很好。 有关详细信息,请参阅 LiveReload 部分。 如果你使用 JRebel,则禁用自动重启以支持动态类重载。 其他 devtools 功能(如 LiveReload 和属性覆盖)仍然可以使用。 |
DevTools 依赖于应用程序上下文的关闭钩子来在重启期间关闭它。
如果你禁用了关闭钩子(SpringApplication.setRegisterShutdownHook(false) ),它将无法正常工作。
|
DevTools 需要自定义 ResourceLoader 由 ApplicationContext 使用。
如果你的应用程序已经提供了一个,它将被包装。
不支持直接覆盖 ApplicationContext 上的 getResource 方法。
|
使用 AspectJ 织入时不支持自动重启。 |
记录条件评估中的更改
默认情况下,每次应用程序重启时,都会记录一个显示条件评估增量的报告。 该报告显示当你进行更改(如添加或删除 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.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 Eclipse 和 IntelliJ IDEA (Ultimate Edition) 都具有此类支持。
使用 Spring Tools,你可以使用控制台视图中的"重载"按钮(只要你的 trigger-file
名为 .reloadtrigger
)。
对于 IntelliJ IDEA,你可以按照 其文档中的说明操作。
自定义重启类加载器
如前面在 重启与重载 部分所述,重启功能是通过使用两个类加载器实现的。
如果这导致问题,你可以使用 spring.devtools.restart.enabled
系统属性诊断问题,如果应用程序在关闭重启的情况下工作,你可能需要自定义哪些内容由哪个类加载器加载。
默认情况下,IDE 中任何打开的项目都使用"重启"类加载器加载,任何常规 .jar
文件都使用"基础"类加载器加载。
如果你使用 mvn spring-boot:run
或 gradle bootRun
,情况也是如此:包含你的 @SpringBootApplication
的项目使用"重启"类加载器加载,其他所有内容都使用"基础"类加载器加载。
启动应用程序时,类路径会打印在控制台上,这可以帮助识别任何有问题的条目。
反射使用的类,特别是注解,可以在启动时加载到父(固定)类加载器中,然后才加载使用它们的应用程序类,这可能导致 Spring 在应用程序中无法检测到它们。
你可以通过创建 META-INF/spring-devtools.properties
文件来指示 Spring Boot 使用不同的类加载器加载项目的部分内容。
spring-devtools.properties
文件可以包含以 restart.exclude
和 restart.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 设置:
-
spring-boot-devtools.properties
-
spring-boot-devtools.yaml
-
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 文件中不支持配置文件。 在 |
配置文件系统监视器
FileSystemWatcher
通过以特定时间间隔轮询类更改,然后等待预定义的静默期以确保没有更多更改来工作。
由于 Spring Boot 完全依赖 IDE 来编译和将文件复制到 Spring Boot 可以读取它们的位置,你可能会发现有时某些更改在 devtools 重启应用程序时没有反映出来。
如果你经常观察到此类问题,请尝试增加 spring.devtools.restart.poll-interval
和 spring.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.host 和 spring.devtools.remote.proxy.port 属性。
|
远程更新
远程客户端以与 本地重启相同的方式监视你的应用程序类路径以查找更改。 任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重启。 如果你迭代使用云服务的功能,而你在本地没有该服务,这会很有帮助。 通常,远程更新和重启比完整的重建和部署周期快得多。
在较慢的开发环境中,可能会发生静默期不够的情况,并且类中的更改可能会分批进行。 在第一批类更改上传后,服务器会重启。 下一批无法发送到应用程序,因为服务器正在重启。
这通常表现为 RemoteSpringApplication
日志中关于无法上传某些类的警告,以及随后的重试。
但它也可能导致应用程序代码不一致,并在第一批更改上传后无法重启。
如果你经常观察到此类问题,请尝试增加 spring.devtools.restart.poll-interval
和 spring.devtools.restart.quiet-period
参数以适应你的开发环境的值。
有关配置这些属性的信息,请参阅 配置文件系统监视器 部分。
只有在远程客户端运行时才会监视文件。 如果你在启动远程客户端之前更改文件,它不会被推送到远程服务器。 |