白頁不是 bug,是「沒匹配到 Controller」的症狀。Spring MVC 找不到能處理請求的方法,就把請求丟給
/error,預設的BasicErrorController接手後渲染出這段白頁。排查別盯著/error,該回去查包結構、註解和映射路徑。
Issue & Env(案發現場與環境)
- 現象:瀏覽器訪問某個接口或頁面,返回一段空白錯誤頁,而不是預期內容。
- 環境:Spring Boot 2.x / 3.x,
spring-boot-starter-web,內嵌 Tomcat。預設開啟 Whitelabel 錯誤頁。
StackTrace(堆疊日誌)
瀏覽器裡顯示的是 HTML,不是例外堆疊:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Not Found, status=404).
也可能是 500 或 405:
There was an unexpected error (type=Internal Server Error, status=500).
關鍵在 type=Not Found, status=404:它說明你的請求本身返回了 404,白頁只是這個錯誤的預設渲染。
打開 DEBUG 日誌後,服務端會打印完整的轉發鏈:
2026-09-03 10:15:32.108 DEBUG 12345 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/hello", parameters={}
2026-09-03 10:15:32.110 DEBUG 12345 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
2026-09-03 10:15:32.111 DEBUG 12345 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : ERROR "/error", parameters={}
2026-09-03 10:15:32.115 DEBUG 12345 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK
如果開啟了 server.error.include-stacktrace=always,控制台能看到被吞掉的例外:
org.springframework.web.servlet.NoHandlerFoundException: No handler found for GET /hello
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1086)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:152)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:462)
Reproduce(復現程式碼)
最常見的一種:主類在 com.example 包,Controller 卻放到這個包之外。
// 主类:com.example.Application
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 放错位置:com.controller.HelloController,不在 com.example 包下
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "ok";
}
}
啟動後訪問 http://localhost:8080/hello,返回的就是 Whitelabel 404 頁。
Root Cause(根因分析)
主類上的 @SpringBootApplication 隱含了 @ComponentScan,掃描範圍預設是主類所在包及其子包。Controller 一旦放到這個包之外,就不會被註冊成 bean,@GetMapping 的映射也就沒進路由表。
請求進來後,DispatcherServlet 用 HandlerMapping 去找能處理這個 URL 的處理器。找不到,就轉發到錯誤路徑 /error。Spring Boot 自動註冊的 BasicErrorController 正好映射在 /error 上,接手後按 Accept 頭返回 HTML,就是那個 Whitelabel 頁面。所以報錯文案裡那句「no explicit mapping for /error」會誤導人——真正沒被映射的是你請求的那個 URL,不是 /error。
除了包結構,還有幾類常見原因:
- 用了
@Component而不是@Controller/@RestController,類成了 bean,但方法沒暴露成 HTTP 映射。 - URL 或 HTTP 方法寫錯,比如接口是
POST,你偏用GET訪問。 - 用原生
@WebServlet寫 Servlet,Spring Boot 預設不掃它,除非加@ServletComponentScan。
The Fix(解決方案)
先定位是哪種。開 DEBUG 日誌能在啟動時看到所有註冊的映射,一眼判斷你的接口在不在:
logging.level.org.springframework.web=DEBUG
包結構放錯,就把 Controller 挪回主類包下,或在主類顯式擴大掃描範圍:
@SpringBootApplication(scanBasePackages = "com.example")
public class Application { }
註解用錯就改回 @RestController;方法錯了就改 @GetMapping / @PostMapping;用了 @WebServlet 就加 @ServletComponentScan 或直接改寫 Spring MVC Controller。
想徹底告別白頁,加一個全局例外處理或自定義錯誤視圖。只想關掉它,設 server.error.whitelabel.enabled=false,但那樣只會露出 Tomcat 預設錯誤頁,不如自己接管 /error。
