白页不是 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。
