文章

Spring MVC 学习笔记:请求处理与参数绑定

更新于 2026/09/20牛耕田

暂存笔记,持续补充中。Spring MVC 是 Spring Boot Web 的底层骨架,理解它才能用好 @RestController。

一、核心组件与请求链路#

Spring MVC 是典型的前端控制器模式,所有请求都先到达 DispatcherServlet,再由它分发给具体组件。

浏览器 → DispatcherServlet → HandlerMapping → HandlerAdapter
→ Handler(Controller) → ViewResolver → View → 响应
组件职责
DispatcherServlet前端控制器,统一调度入口
HandlerMapping根据 URL 找到处理器(映射不等于处理器本身)
HandlerAdapter适配不同类型的处理器(注解式 / 传统接口式)
HandlerExceptionResolver统一异常处理
ViewResolver将逻辑视图名解析为具体 View
MultipartResolver文件上传解析
LocaleResolver / ThemeResolver国际化 / 主题

一次请求的完整流程:

  1. DispatcherServlet 收到请求,通过 HandlerMapping 得到 HandlerExecutionChain(含拦截器链)。
  2. 依次执行 preHandle。
  3. 由 HandlerAdapter 调用 Handler(即 Controller 方法)。
  4. 返回 ModelAndView,postHandle 执行。
  5. ViewResolver 解析视图并渲染。
  6. afterCompletion 执行。

RESTful 场景:使用 @ResponseBody(或 @RestController)时,返回的是 HttpMessageConverter 序列化后的 JSON,不经过 ViewResolver。

二、请求映射#

@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}") // 路径变量
public User get(@PathVariable Long id) { ... }
@PostMapping // 提交
public User create(@RequestBody User user) { ... }
@PutMapping("/{id}") // 全量更新
public User update(@PathVariable Long id, @RequestBody User user) { ... }
@DeleteMapping("/{id}") // 删除
public void delete(@PathVariable Long id) { ... }
}
  • 组合注解:@GetMapping = @RequestMapping(method = RequestMethod.GET)。
  • 路径匹配:支持 *(单层)、**(多层);Spring 6 默认改用 PathPatternParser,性能优于旧的 AntPathMatcher。
  • 多条件限定:可用 params、headers、consumes、produces 做更细粒度的映射。

三、参数绑定(高频考点)#

场景注解说明
查询字符串 ?a=1@RequestParamrequired=false 可设为可选
路径变量 /user/{id}@PathVariable用 {id} 占位
请求体 JSON@RequestBody由 HttpMessageConverter 反序列化
表单对象无注解(POJO)按字段名自动绑定
请求头@RequestHeader
Cookie@CookieValue
文件@RequestPart / MultipartFile
@PostMapping("/search")
public PageResult<User> search(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String keyword,
@RequestHeader("Authorization") String token) {
...
}

常见坑:application/json 请求体只能用 @RequestBody,用 @RequestParam 收不到;反之表单提交也不能用 @RequestBody。

四、返回值处理#

  • @ResponseBody / @RestController:返回值经 HttpMessageConverter 转 JSON。
  • 返回 ResponseEntity<T>:可自定义状态码与响应头。
@GetMapping("/{id}")
public ResponseEntity<User> get(@PathVariable Long id) {
User u = service.findById(id);
return u == null ? ResponseEntity.notFound().build()
: ResponseEntity.ok(u);
}

五、全局异常处理#

用 @RestControllerAdvice + @ExceptionHandler 统一收口,避免每个方法写 try-catch。

@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BizException.class)
public Result<Void> handleBiz(BizException e) {
return Result.fail(e.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValid(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(400, msg);
}
@ExceptionHandler(Exception.class)
public Result<Void> handleOther(Exception e) {
log.error("系统异常", e);
return Result.fail(500, "系统繁忙,请稍后再试");
}
}

注意:@ExceptionHandler(Exception.class) 兜底时不要把堆栈信息返回给前端,否则会泄露内部实现细节。

六、参数校验#

引入 spring-boot-starter-validation 后即可使用 Jakarta Bean Validation 注解。

public class UserCreateDTO {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度需在 3~20 之间")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
}
@PostMapping
public Result<Void> create(@Validated @RequestBody UserCreateDTO dto) { ... }
  • @Valid(JSR-303 标准)与 @Validated(Spring 扩展,支持分组校验)二选一。
  • 嵌套对象校验需在字段上加 @Valid 才会级联生效。

七、拦截器 vs 过滤器#

维度Filter(Servlet 规范)Interceptor(Spring MVC)
作用范围所有请求(含静态资源)仅 DispatcherServlet 处理的请求
能否拿到 Bean不易(容器外)可以(Spring 容器内)
能否拿到 Handler否可以
典型用途编码、跨域、日志埋点登录校验、权限、限流
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
if (req.getHeader("Token") == null) {
resp.setStatus(401);
return false; // 返回 false 即中断
}
return true;
}
}

顺序:Filter → preHandle → Controller → postHandle → afterCompletion。

八、小结#

  • Spring MVC = DispatcherServlet + 九大组件,核心是「映射 → 适配 → 执行 → 渲染」。
  • 参数绑定靠注解区分来源,JSON 用 @RequestBody,表单/查询用 @RequestParam。
  • 生产环境必备三件套:全局异常处理 + 参数校验 + 登录拦截器。
返回主页