开发者工具 (Developer Tools)
Spring Boot 包含了一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot-devtools 模块可以包含在任何项目中,以提供额外的开发时特性。
1. 引入依赖
要引入 devtools 支持,请将模块依赖添加到你的构建文件中:
<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 可能会导致类加载问题。请参阅诊断类加载问题以了解详情。
提示
- 可选依赖:将依赖标记为可选(Maven)或使用
developmentOnly(Gradle)可以防止 devtools 传递到使用该项目的其他模块。 - 生产禁用:打包好的应用程序(如
java -jar或从特殊加载器启动)会自动禁用 devtools。如果需要在特定环境下强制启用重启,可以使用系统属性-Dspring.devtools.restart.enabled=true。
2. 诊断类加载问题
重启功能是通过使用两个类加载器实现的。对于大多数应用程序,这种方法运行良好。但是,它有时会导致类加载问题,特别是在多模块项目中。
要诊断类加载问题是否确实由 devtools 引起,请尝试禁用重启。如果禁用后问题解决,你可能需要自定义重启类加载器以包含你的整个项目。
3. 属性默认值
Spring Boot 支持的几个库使用缓存来提高性能。例如,模板引擎会缓存解析后的模板。虽然这在生产中很有用,但在开发中会导致你看不到实时修改。
spring-boot-devtools 默认会禁用这些缓存选项,并应用一些感知的开发配置:
| 属性名称 | 默认值 |
|---|---|
management.tracing.sampling.probability | 1.0 |
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.error.include-binding-errors | always |
spring.web.error.include-message | always |
spring.web.error.include-stacktrace | always |
spring.web.resources.cache.period | 0 |
spring.web.resources.chain.cache | false |
::: note 提示 如果不希望应用这些默认值,可以在 application.properties 中设置 spring.devtools.add-properties=false。 :::
4. 自动重启 (Automatic Restart)
当类路径上的文件发生更改时,应用程序会自动重启。
4.1 触发重启
触发重启的唯一方法是更新类路径。文件必须重新编译才能被探测:
- Eclipse: 保存文件即可。
- IntelliJ IDEA: 手动点击
Build Project(Ctrl+F9)。 - 构建插件: 运行
mvn compile或gradle build。
4.2 重启 vs 重载
- Restart (重启):Spring Boot 使用两个类加载器。Base 类加载器加载不变的第三方库;Restart 类加载器加载正在开发的类。重启时只刷新后者,速度比普通启动快得多。
- Reload (重载):如 JRebel 等技术,直接在内存中重写类定义,不重启 JVM,速度最快但也更复杂。
4.3 记录条件评估变化 (Logging Condition Delta)
默认情况下,每次重启时都会记录一份条件评估变化报告。这可以让你看到随着你更改代码(如添加 Bean 或修改属性),自动配置发生了哪些变化。 若要禁用此报告,可以设置:
spring.devtools.restart.log-condition-evaluation-delta=false4.4 排除资源
某些资源更改时不需要重启(如 Thymeleaf 模板)。默认情况下,/META-INF/maven, /META-INF/resources, /resources, /static, /public, 或 /templates 中的更改不会触发重启,但会触发 LiveReload。
自定义排除路径:
spring.devtools.restart.exclude=static/**,public/**spring:
devtools:
restart:
exclude: "static/**,public/**"4.5 监控额外路径
如果你希望在修改不在类路径上的文件时也触发重启,可以使用 spring.devtools.restart.additional-paths 属性:
spring.devtools.restart.additional-paths=src/main/python4.6 禁用重启
如果需要彻底禁用重启支持:
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApplication.class, args);
}fun main(args: Array<String>) {
System.setProperty("spring.devtools.restart.enabled", "false")
runApplication<MyApplication>(*args)
}4.7 使用触发文件
如果你希望在特定时刻才触发重启,可以设置一个“触发文件”:
spring.devtools.restart.trigger-file=.reloadtriggerspring:
devtools:
restart:
trigger-file: ".reloadtrigger"只有当你修改类路径下的 .reloadtrigger 文件时,重启才会开始。
4.8 自定义重启类加载器
如果你发现某些 JAR 需要在重启类加载器中加载,可以创建 META-INF/spring-devtools.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 项目都生效。
配置分析
如果重启过于频繁或探测不准,可以调整轮询间隔和静默期:
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1sspring:
devtools:
restart:
poll-interval: "2s"
quiet-period: "1s"7. 远程应用 (Remote Applications)
你可以在远程服务器上使用 DevTools 功能(如远程重启)。
安全警告
远程支持必须显式配置秘密令牌,且严禁在生产环境启用。
- 启用:在远程包中包含 devtools 并设置秘密:yaml
spring: devtools: remote: secret: "my-strong-secret" - 连接:在 IDE 中运行
RemoteSpringApplication,并传入远程 URL。
补充教学
1. IntelliJ IDEA 的“自动编译”设置陷阱
在 IDEA 中,如果不进行以下两项配置,DevTools 可能看起来“不起作用”:
- 自动构建:
Settings->Build, Execution, Deployment->Compiler-> 勾选Build project automatically。 - 运行中构建:
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.include 或 restart.exclude 将相关 Jar 强制划归到一个加载器下。