上周五,实习生小赵瘫在椅子上,一脸绝望:

“小马哥,我接口写好了,路径也对,为啥一访问就 404?我都检查 10 遍了,@GetMapping("/user") 没错啊!”

我走过去一看,笑了:“兄弟,你是不是把 Controller 放在 com.controller 包下,而主启动类在 com.example.demo?”

他愣住:“啊?这也有关系?”

“当然有!Spring Boot 的 404,90% 不是路径写错,而是类根本没被扫描到!

今天,我就带你一次性搞懂 Spring Boot 路径映射的 3 大误区,从此告别“玄学 404”!

🔥 一、先看错误长啥样(附模拟截图)

你访问 http://localhost:8080/user,浏览器显示:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Oct 16 15:30:22 CST 2025
There was an unexpected error (type=Not Found, status=404).

📌 关键点
不是报错日志,而是“空白 404” —— 说明 Spring 根本没找到你的 Controller!

🤔 二、为什么会出现 404?—— 本质是“Controller 没注册”

很多人以为:只要写了 @RestController,Spring 就能自动识别。
错!前提是:这个类必须被 Spring 扫描到!

Spring Boot 默认只扫描 主启动类所在包及其子包

❌ 错误结构示例:

com.example.demo
  └── DemoApplication.java  // 主启动类

com.controller               // ❌ 在 demo 外面!Spring 扫不到!
  └── UserController.java

→ 启动时,Spring 根本不知道 UserController 的存在 → 没有路径映射 → 404!

🛠️ 三、3 大常见误区 & 解决方案(附代码)

误区 1:Controller 不在主启动类的子包下(最常见!)

✅ 正确结构(推荐):
com.example.demo
  ├── DemoApplication.java
  └── controller
      └── UserController.java  // ✅ 在子包下,自动被扫描
Controller 代码:
package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/user")
    public String getUser() {
        return "Hello, User!";
    }
}

💡 黄金法则
所有业务代码(controller/service/dao)必须放在主启动类的子包下!

误区 2:忘了加 @RestController@Controller

❌ 错误写法:
// 没加任何注解!Spring 当它是普通类
public class UserController {
    @GetMapping("/user")
    public String getUser() {
        return "Hello";
    }
}

→ 启动不报错,但访问 404!

✅ 正确写法:
@RestController  // 👈 必须加!
public class UserController {
    @GetMapping("/user")
    public String getUser() {
        return "Hello";
    }
}

🔍 区别

  • @Controller:返回页面(需配合 Thymeleaf)
  • @RestController = @Controller + @ResponseBody直接返回 JSON/字符串

误区 3:路径拼接错误(类级别 + 方法级别)

Spring 的路径是 类路径 + 方法路径 拼起来的!

❌ 错误示例:
@RestController
@RequestMapping("/api")  // 类级别路径
public class UserController {

    @GetMapping("/user")   // 方法路径
    public String getUser() {
        return "OK";
    }
}

正确访问路径是:/api/user
→ 如果你访问 /user,当然 404!

✅ 检查技巧:

启动时看控制台日志:

Mapped "{[/api/user], methods=[GET]}" onto public java.lang.String ...

→ 这里明确告诉你映射的完整路径!

🔍 四、终极排查 checklist(收藏!)

遇到 404,按顺序检查:

  1. Controller 类是否在主启动类的子包下?
  2. 是否加了 @RestController@Controller
  3. 类上是否有 @RequestMapping?完整路径 = 类路径 + 方法路径
  4. 启动日志中是否打印了 Mapped "{[/xxx]}"
  5. 是否拼错了大小写?(Linux 服务器区分大小写!)

小技巧:启动后访问 http://localhost:8080/actuator/mappings(需开启 Actuator)
→ 查看所有已注册的路径映射!


💡 五、Bonus:如何手动指定扫描包?(不推荐,但要知道)

如果非要放外面(比如多模块项目),可以用 @ComponentScan

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.demo", "com.controller"})
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

但强烈建议别这么干! 跟着主启动类走,最安全、最清晰。

💬 六、写在最后

Spring Boot 的 404,从来不是“路径写错”,而是 “类没被 Spring 管理”

记住:

想被访问,先被扫描;想被扫描,先放对包。

下次再遇到 404,别慌,打开 checklist,30 秒定位问题!


互动时间
你被 404 坑过最离谱的一次是什么?是因为包路径?还是忘了注解?

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐