開發過程中頻繁重啟應用極大降低效率。Spring Boot DevTools 通過雙類加載器機制實現毫秒級熱重啟,並支持靜態資源、模板、屬性文件的即時生效。本文詳解 DevTools 核心原理、Maven 配置細節、Thymeleaf 整合、排除規則與常見坑點。
DevTools 將類路徑劃分為兩個邏輯層級,由兩個類加載器分別加載:
target/classes、配置文件、模板等)。重啟時丟棄舊實例、創建新實例加載變更後的類。這就是為什麼 DevTools 重啟極快:只需重新加載業務代碼,核心依賴複用現有 Base ClassLoader 已加載的類。
<dependencies>
<!-- Thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- DevTools 熱部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 關鍵:防止傳遞性依賴 -->
</dependency>
</dependencies>
optional=true 確保依賴 DevTools 的項目不會自動繼承該依賴,避免生產環境誤引入。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork> <!-- 關鍵:啟用 fork 模式,否則 DevTools 不生效 -->
</configuration>
</plugin>
原理:fork=true 使插件在獨立 JVM 進程中運行應用,DevTools 才能監控類文件變更並觸發 Restart ClassLoader 重建。fork=false(默認)時類加載器結構不支持熱重啟。
# application.properties
spring.thymeleaf.cache=false # 關閉模板緩存,修改即時生效(DevTools 會自動設置)
DevTools 啟用時會自動設置 spring.thymeleaf.cache=false、spring.freemarker.cache=false 等,無需手動配置。
| 文件類型 | 行為 | 說明 |
|---|---|---|
類文件 (.class) |
觸發完全重啟 | Restart ClassLoader 重建,上下文刷新,Bean 重新初始化 |
屬性文件 (.properties/.yml) |
觸發完全重啟 | 配置變更需上下文刷新生效 |
模板文件 (.html/.ftl) |
觸發完全重啟 | 配合 cache=false 實現即時預覽 |
靜態資源 (static/, public/, resources/, META-INF/resources) |
不重啟,LiveReload 瀏覽器自動刷新 | 內嵌 LiveReload Server 推送變更通知 |
# application.properties
# 1. 完全覆蓋默認排除目錄(僅排除 static、public)
spring.devtools.restart.exclude=static/**,public/**
# 2. 在默認基礎上追加排除(推薦)
spring.devtools.restart.additional-exclude=mybatis/**,generated/**
# 3. 監聽非 classpath 目錄(如外部配置目錄)
spring.devtools.restart.additional-paths=/opt/config/,file:///D:/external-config/
<script src="https://localhost:35729/livereload.js"></script>@Controller
@RequestMapping("/thymeleaf")
public class ThymeleafController {
@GetMapping("/greeting")
public String greeting(@RequestParam(defaultValue = "world") String name, Model model) {
model.addAttribute("xname", name);
return "greet"; // 解析為 templates/greet.html
}
@GetMapping("/ajax")
@ResponseBody
public String ajax(@RequestParam String username) {
return "Hello, " + username + "! (AJAX)";
}
}
<!-- templates/greet.html -->
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Thymeleaf Demo</title>
<link th:href="@{/bootstrap/css/bootstrap.min.css}" rel="stylesheet"/>
</head>
<body>
<div class="panel panel-primary">
<div class="panel-heading">歡迎</div>
<div class="panel-body" th:text="${xname}"></div>
</div>
<div id="ajaxResult"></div>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:inline="javascript">
$(function() {
$.get("/thymeleaf/ajax", {username: "DevTools"}, function(text) {
$("#ajaxResult").text(text);
});
});
</script>
</body>
</html>
Settings → Build, Execution, Deployment → Compiler → Build project automatically;Eclipse 默認自動構建。fork=true、optional=true、項目是否為模塊化(多模塊需在啟動模塊配置)。java -jar 或 spring.profiles.active=prod 會自動禁用,但建議打包時排除:<excludeDevtools>true</excludeDevtools> (Spring Boot 2.3+)。spring.devtools.restart.exclude 排除相關 JAR。optional=true + fork=true + spring.thymeleaf.cache=false善用 DevTools,讓「修改-保存-驗證」循環縮短至秒級,顯著提升開發體驗與產出效率。
