MVC 常用注解大总结与常见坑

学完 21–38 章,注解已经铺了一地。这一章把它们按职责归类做一次总复习,再集中清点最容易踩的坑。

注解全家桶速查

分组注解一句话作用
控制器@Controller / @RestController类声明:控制器 / 控制器+全类响应体
映射@RequestMapping 及 @GetMapping/@PostMapping/@PutMapping/@DeleteMapping/@PatchMapping把 HTTP 方法与路径绑定到方法
参数@RequestParam / @PathVariable / @RequestHeader / @CookieValue从查询串/路径/头/Cookie 取值
请求体@RequestBody / @RequestPart反序列化请求体 / multipart 的某个 part
模型@ModelAttribute / @SessionAttributes / @SessionAttribute模型属性 / 会话暂存模型 / 读会话
响应@ResponseBody / ResponseEntity / @ResponseStatus写响应体 / 状态+头+体 / 固定状态码
校验@Valid / @Validated触发 Bean Validation / 支持分组
异常@ExceptionHandler / @ControllerAdvice / @RestControllerAdvice局部/全局异常转响应
跨域@CrossOrigin放开单个接口的跨域限制

常见坑 No.1:String 返回值被当成视图名

在 @Controller 里返回 "OK" 会去解析视图 → 404 或视图解析异常。想返回文本/JSON 必须 @ResponseBody 或用 @RestController。

常见坑 No.2:@RequestParam 依赖参数名推断

不写 value 时按方法形参名匹配,需要 javac -parameters 或调试信息;否则解析失败。结论:显式写全 name,别赌编译开关。

常见坑 No.3:@RequestBody 的幺蛾子

  • 一个方法只能有一个 @RequestBody。
  • JSON 缺字段对不上 → HttpMessageNotReadableException(400)。
  • 想收 JSON 又想收表单字段,别同时用 @RequestBody + @RequestParam 混搭(@RequestBody 独占请求体),改用 DTO + 字段或 @RequestPart。
  • LocalDate/LocalDateTime 反序列化:依赖 jackson-datatype-jsr310 并配好格式,默认格式不是你想要的。

常见坑 No.4:BindingResult 必须紧跟被校验参数

@Valid DTO 后面隔了别的参数再接 BindingResult → IllegalStateException(框架要求紧跟,见第 26 章)。

常见坑 No.5:映射歧义与 404/405/406/415

现象原因与排查
启动报 Ambiguous mapping两个方法映射到同一 URL+方法
请求 404URL 没匹配:查路径变量、方法注解、前缀 @RequestMapping
方法对但请求方法不对 → 405GET 调了 POST 接口
produces 不满足 Accept → 406客户端要的格式你没声明/不能产
consumes 不满足 Content-Type → 415客户端发的内容类型你没收

常见坑 No.6:静态资源被控制器「吃掉」

DispatcherServlet 映射 / 后,/css/app.css 若没配资源映射会 404;若控制器写了 @GetMapping("/") 又会抢走静态资源。给静态资源独立前缀(/static/)+ addResourceHandlers 是常规解法(第 32 章)。

常见坑 No.7:@DateTimeFormat 与 JSON 是两套机制

@DateTimeFormat 只作用于表单/参数绑定格式化;JSON 序列化由 Jackson 控制(@JsonFormat/JavaTimeModule)。混用会导致「表单没问题、JSON 报错」。

常见坑 No.8:参数解析顺序与类型错误的表现

方法参数按「参数解析器逐个试」的顺序处理,解析失败多数表现为 400(类型不匹配)而非 500;500 通常意味着解析器内部异常或 NPE,注意区分。多参数时把 @RequestParam 等标注参数与 Model、BindingResult 的位置写规整(BindingResult 规则见坑 No.4),代码可读性也更好。

常见坑 No.9:中文乱码与响应头

字符编码问题大多出在容器/过滤器层(CharacterEncodingFilter 要放在最前),而不是控制器;序列化中文乱码检查 Jackson 的编码与 Content-Type 里的 charset。

常见坑 No.10:异常被吞

在控制器里 try/catch 吞掉异常只返回 null,前端拿到 200 + null 很难排查。让异常抛给 @RestControllerAdvice 统一处理,日志在 advice 里记。

复习建议

对照「注解全家桶」表自查:每个注解能不能说出它写在类上还是方法上、参数上还是返回值上?标注位置的错位(如把 @RequestParam 放类上)是新手报错主因。遇到怪问题先打印 andDo(print()) 看真实请求响应,再对着上面十坑逐个排除。

注解是 Spring MVC 的「语法」,映射、解析、响应、异常四套注解各管一段。写之前先想清楚数据从哪来(参数注解)、结果往哪去(响应注解)、出错谁来接(异常注解),坑自然就绕开了。

笔记加载中…