新手解决Whitelabel Error Page NoResourceFoundException: No static resource for request ‘/’报错的一则案例
Contents
一 报错重现和故障说明
在我自己动手实践「Spring in Action sixth edition」的第2个章节的过程中,编写了一个简单的Controller,然后用IDEA启动了Spring工程之后,浏览器访问 :http://localhost:8080/
遇到下述错误:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Jul 21 08:37:48 CST 2026
There was an unexpected error (type=Not Found, status=404).
No static resource .
org.springframework.web.servlet.resource.NoResourceFoundException: No static resource for request '/'.
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:527)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:50)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1000)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:892)
...

我的Controller代码如下:
package com.knockatdatabase.tacocloud;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(method = RequestMethod.GET,value = "/")
public class HomeController {
public String home() {
return "home";
}
}
但是,当我把代码改写为:
//写法2
package com.knockatdatabase.tacocloud;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(method = RequestMethod.GET,value = "/")
public class HomeController {
@GetMapping(value = "/")
public String home() {
return "home";
}
}
或者
//写法3
package com.knockatdatabase.tacocloud;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping(value = "/")
public String home() {
return "home";
}
}
程序都可以运行正常,不报错。

二 错误分析
对于新手而言,这可能需要花费一些时间。于是,把问题交给了Gemini,给出了一针见血的解释和说明:
造成问题的根源,是SpringMVC的注解解析机制,尤其是既有类级别「class-level」又有方法级别「method-level」混合使用作路由映射的场景时,容易出现一些和我们预期不一致的报错。
如果只把路由写在类上,方法上不写路由时,Spring是不会把这个方法识别为Web请求处理器的。就如同第一种写法。
1 第一种写法:只在类上写注解为啥会报错
SpringMVC的RequestMappingHandlerMapping在注册路由时,会先扫描带有@Controller的类,然后到该类中去找那些带有@RequestMapping或者@GetMapping的方法。此时,HomeController类上虽然有@Controller注解,但是该类中没有任何满足条件的方法,于是SpringMVC认为这是1个普普通通的方法,压根儿不会把它当做Web请求的接口。最终,请求的根路径/这个URL,没有绑定到任何控制器方法上。Spring认为这不是一个动态请求,而是查找一个静态资源,于是会到项目的静态路径static下去查找名为index.html或者是名为/的静态资源,结果呢,没有找到该资源,最终抛出了:
ue Jul 21 08:37:48 CST 2026
There was an unexpected error (type=Not Found, status=404).
No static resource .
org.springframework.web.servlet.resource.NoResourceFoundException: No static resource for request '/'.
再进一步,当我创建对应的文件 src/main/resources/static/index.html 时,程序则可以继续运行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我的路径在
<h1>欢迎来到 Taco Cloud!</h1>
<div style="background-color: #f0f0f0; padding: 15px; border-radius: 5px;">
<p><strong>当前完整的 URL:</strong> <span id="full-url"></span></p>
<p><strong>当前访问的相对路径:</strong> <span id="path-name"></span></p>
</div>
<script>
// 获取浏览器当前地址并渲染到页面
document.getElementById('full-url').innerText = window.location.href;
document.getElementById('path-name').innerText = window.location.pathname;
// 同时也在控制台打印一份
console.log("网页绝对 URL: " + window.location.href);
console.log("网页路径: " + window.location.pathname);
</script>
</body>
</html>

2 第2种写法:类和方法上都写注解,为啥不报错
当我们在类和方法上同时都写有注解时,SpringMVC在解析时,会拼接URL。类注解地址+方法注解地址。而本例中,类和方法上都写成了根路径,最后会拼接成http://localhost:8080//。SpringMVC在此时,会自动去掉一个根路径/的URL。home()方法被成功识别到,并直接返回了名为home的view。
3 第3种写法:只在方法上写注解,为啥也不报错
这是Spring开发中最推荐、最简洁的写法。类级别上不设置基准路径,直接由方法级别的@GetMapping(value=”/”)来统领全局。Spring识别到该方法并且绑定到根路径。
三 SpringMVC最佳实践小结
在编写SpringMVC控制器时,通常遵循这个铁律:方法上必须有路由注解,它才会被作为一个可达的Web接口。
- 类级别的注解@RequestMapping:通常用于定义公共前缀。例如:处理订单的控制器,可以在类上写@RequestMapping(”/orders/”);
- 方法上的注解,如则处理具体的动作,如@GetMapping(”/detail”),最终匹配成“/orders/detail”;
- 对于类似查看主页这样的根路径,只需要直接写在方法注解上即可,@GetMapping(”/”),这样代码可读性好,简洁也不会引起歧义。


