Spring MVC 接收请求参数的核心

的核Spring MVC 接收请求参数心是通过注解绑定请求中的数据(URL 路径、请求头、请求体、表单、查询参数等)到控制器方法的参数上,不同注解适配不同的参数来源场景。以下是全场景的注解分类、使用方式和核心注意事项,覆盖日常开发 99% 的场景:

一、核心注解总览(按参数来源分类)

注解 作用场景 核心说明
@RequestParam 获取 URL 查询参数 / 表单参数(application/x-www-form-urlencoded) 绑定单个参数,支持必填、默认值、参数名映射
@PathVariable 获取 URL 路径中的占位符参数(RESTful 风格) 绑定路径中的动态值(如 /user/{id} 中的 id
@RequestBody 获取请求体中的 JSON/XML 数据(application/json) 绑定请求体到 Java 对象,仅能在方法中用一次
@RequestHeader 获取 HTTP 请求头中的参数 绑定单个请求头(如 Content-TypeToken
@CookieValue 获取客户端 Cookie 中的值 绑定指定名称的 Cookie 值
@ModelAttribute 绑定请求参数到 JavaBean(表单 / 查询参数) 自动封装多个参数到实体类,支持级联属性
@RequestPart 接收文件上传 / 复杂请求体(multipart/form-data) 绑定文件或 JSON 格式的 Part 数据(替代@RequestParam处理文件)
无注解(默认绑定) 简单类型参数(与请求参数名一致) 仅适用于参数名与请求参数名完全匹配的简单场景(不推荐,可读性差)

二、详细使用示例(附场景说明)

1. @RequestParam:查询参数 / 表单参数(最常用)

适用于 GET 请求的 URL 查询参数(?name=xxx&age=18)、POST 表单提交(application/x-www-form-urlencoded)。

复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ParamController {

    // 基础用法:绑定单个查询参数
    @GetMapping("/user/query")
    public String queryUser(
        // name:请求参数名(与URL中的参数名一致)
        // required:是否必填(默认true,不传则报400错误)
        // defaultValue:默认值(仅当required=false时生效)
        @RequestParam(name = "name", required = false, defaultValue = "匿名") String username,
        @RequestParam("age") Integer userAge // 简写:name可省略,默认取参数名
    ) {
        return "用户名:" + username + ",年龄:" + userAge;
    }

    // 接收多个同名参数(如 ?hobby=篮球&hobby=足球)
    @GetMapping("/user/hobby")
    public String queryHobby(@RequestParam List<String> hobby) {
        return "爱好:" + String.join(",", hobby);
    }
}

请求示例

复制代码
GET /user/query?name=张三&age=20 → 用户名:张三,年龄:20
GET /user/query?age=20 → 用户名:匿名,年龄:20(使用默认值)
GET /user/hobby?hobby=篮球&hobby=足球 → 爱好:篮球,足球
2. @PathVariable:RESTful 路径参数

适用于 URL 路径中的动态占位符(如 /user/123 中的 123 是用户 ID),RESTful 风格必备。

复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RestControllerDemo {

    // 单个路径参数
    @GetMapping("/user/{id}")
    public String getUserById(@PathVariable("id") Long userId) {
        return "用户ID:" + userId;
    }

    // 多个路径参数 + 非必选(Spring 5.3+支持)
    @GetMapping("/order/{orderId}/item/{itemId}")
    public String getOrderItem(
        @PathVariable Long orderId, // 简写:参数名与占位符一致时,可省略括号内的名称
        @PathVariable(required = false) Long itemId // 非必选(需确保URL匹配,如 /order/123/item/ 或 /order/123/item)
    ) {
        return "订单ID:" + orderId + ",商品ID:" + itemId;
    }
}

请求示例

复制代码
GET /user/123 → 用户ID:123
GET /order/456/item/789 → 订单ID:456,商品ID:789
GET /order/456/item → 订单ID:456,商品ID:null(非必选)
3. @RequestBody:请求体 JSON/XML 参数

适用于 POST/PUT 请求的请求体(application/json 格式),是前后端分离的核心注解。

复制代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

// 实体类
class User {
    private String name;
    private Integer age;
    // getter/setter省略
}

@RestController
public class JsonController {

    // 绑定JSON请求体到Java对象
    @PostMapping("/user/save")
    public String saveUser(@RequestBody User user) {
        return "保存用户:" + user.getName() + ",年龄:" + user.getAge();
    }

    // 绑定原始JSON字符串
    @PostMapping("/user/raw")
    public String rawJson(@RequestBody String jsonStr) {
        return "原始JSON:" + jsonStr;
    }
}

请求示例(Postman/Apifox):

  • 请求方法:POST

  • Content-Type:application/json

  • 请求体:

    复制代码
    {
      "name": "李四",
      "age": 25
    }
  • 响应:保存用户:李四,年龄:25

⚠️ 注意:

  • 一个方法中只能有一个 @RequestBody(请求体只能解析一次);
  • 若请求体为空且 required=true(默认),会报 400 错误;
  • 需确保项目引入 JSON 解析依赖(如 jackson-databind,Spring Boot 已内置)。
4. @RequestHeader:请求头参数

适用于获取 HTTP 请求头中的数据(如 Token、Content-Type、User-Agent 等)。

复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HeaderController {

    // 获取单个请求头
    @GetMapping("/header/token")
    public String getToken(@RequestHeader("Authorization") String token) {
        return "Token:" + token;
    }

    // 获取所有请求头
    @GetMapping("/header/all")
    public String getAllHeaders(@RequestHeader java.util.Map<String, String> headers) {
        return "请求头:" + headers.toString();
    }
}

请求示例

复制代码
GET /header/token
Header:Authorization: Bearer 123456 → 响应:Token:Bearer 123456
5. @CookieValue:Cookie 参数

适用于获取客户端携带的 Cookie 值(如登录态、用户标识)。

复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CookieController {

    @GetMapping("/cookie/user")
    public String getCookie(
        @CookieValue(value = "userId", required = false, defaultValue = "0") String userId
    ) {
        return "Cookie中的用户ID:" + userId;
    }
}

请求示例

复制代码
GET /cookie/user
Cookie:userId=789 → 响应:Cookie中的用户ID:789
6. @ModelAttribute:绑定到 JavaBean(表单 / 查询参数)

适用于多个请求参数自动封装到实体类(替代多个 @RequestParam),支持级联属性(如 user.address.province)。

复制代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;

// 实体类(支持级联)
class UserForm {
    private String name;
    private Integer age;
    private Address address; // 级联属性
    // getter/setter省略
}

class Address {
    private String province;
    private String city;
    // getter/setter省略
}

@RestController
public class FormController {

    // 绑定表单参数到UserForm
    @PostMapping("/user/form")
    public String submitForm(@ModelAttribute UserForm userForm) {
        return "用户:" + userForm.getName() + 
               ",地址:" + userForm.getAddress().getProvince() + "-" + userForm.getAddress().getCity();
    }
}

请求示例(表单提交):

  • 请求方法:POST
  • Content-Type:application/x-www-form-urlencoded
  • 参数:name=王五&age=30&address.province=广东&address.city=深圳
  • 响应:用户:王五,地址:广东-深圳

⚠️ 注意:@ModelAttribute 可省略,直接写实体类参数(Spring 会自动绑定),效果一致。

7. @RequestPart:文件上传 / 复杂 Part 参数

适用于 multipart/form-data 类型的请求(文件上传、混合表单 + JSON),替代 @RequestParam 处理文件。

复制代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class FileController {

    // 单文件上传
    @PostMapping("/file/upload")
    public String uploadFile(
        @RequestPart("file") MultipartFile file, // 绑定文件
        @RequestPart("desc") String description // 绑定普通表单参数
    ) {
        return "文件名:" + file.getOriginalFilename() + ",描述:" + description;
    }

    // 多文件上传 + JSON参数混合
    @PostMapping("/file/batch")
    public String batchUpload(
        @RequestPart("files") MultipartFile[] files,
        @RequestPart("user") User user // 绑定JSON格式的Part参数(Content-Type: application/json)
    ) {
        return "上传文件数:" + files.length + ",用户:" + user.getName();
    }
}

请求示例(文件上传):

  • 请求方法:POST
  • Content-Type:multipart/form-data
  • 表单项:
    • file:选择本地文件(如 test.txt)
    • desc:测试文件
  • 响应:文件名:test.txt,描述:测试文件
8. 无注解默认绑定

当参数名与请求参数名完全一致时,可省略注解,Spring 会自动绑定(简单场景可用,不推荐复杂场景,可读性差)。

复制代码
@GetMapping("/user/simple")
public String simpleParam(String name, Integer age) {
    return "用户名:" + name + ",年龄:" + age;
}

请求示例

复制代码
GET /user/simple?name=赵六&age=35 → 用户名:赵六,年龄:35

三、特殊场景处理

1. 日期类型参数绑定

Spring MVC 默认不支持 yyyy-MM-dd 等自定义日期格式,需配置转换器或注解指定格式:

复制代码
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;

@RestController
public class DateController {

    // 方式1:@DateTimeFormat指定格式
    @GetMapping("/date/query")
    public String queryDate(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date createTime) {
        return "创建时间:" + createTime;
    }

    // 方式2:全局配置日期转换器(推荐,避免每个参数加注解)
    // 配置类中注册Converter:
    // @Bean
    // public Converter<String, Date> dateConverter() {
    //     return new Converter<>() {
    //         @Override
    //         public Date convert(String source) {
    //             return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    //         }
    //     };
    // }
}
2. 数组 / 集合参数绑定
  • 数组:直接用数组类型接收(如 String[] hobby);

  • List:必须用 @RequestParam 注解(Spring 无法直接绑定无注解的 List);

  • Map:用 @RequestParam Map<String, String> 接收所有查询参数 / 表单参数。

    @GetMapping("/param/collection")
    public String collectionParam(
    String[] hobby, // 数组
    @RequestParam List<String> tags, // List必须加@RequestParam
    @RequestParam Map<String, String> allParams // 所有参数
    ) {
    return "爱好:" + Arrays.toString(hobby) + ",标签:" + tags + ",所有参数:" + allParams;
    }

四、常见问题与避坑指南

  1. 参数名不匹配

    • 原因:注解中 name/value 与请求参数名不一致;
    • 解决:核对参数名,或开启 Spring MVC 的参数名匹配(Spring Boot 默认开启)。
  2. @RequestBody 报 415 Unsupported Media Type

    • 原因:请求头 Content-Type 不是 application/json,或未引入 JSON 解析依赖;
    • 解决:设置正确的 Content-Type,确保项目有 jackson-databind 依赖。
  3. @PathVariable 报 404

    • 原因:URL 路径与 @GetMapping 中的路径模板不匹配(如占位符数量不一致);
    • 解决:核对 URL 和路径模板(如 /user/{id} 对应 /user/123,而非 /user?id=123)。
  4. 日期参数绑定报 400

    • 原因:日期格式不匹配,Spring 无法解析;
    • 解决:用 @DateTimeFormat 或全局日期转换器。
  5. 文件上传报 413 Request Entity Too Large

    • 原因:上传文件大小超过 Spring / 服务器限制;

    • 解决:配置文件大小限制(Spring Boot):

      复制代码
      spring:
        servlet:
          multipart:
            max-file-size: 10MB # 单个文件大小
            max-request-size: 50MB # 总请求大小

五、总结

场景 推荐注解 核心注意事项
URL 查询参数 / 表单参数 @RequestParam 注意必填性、默认值,List 需显式注解
RESTful 路径参数 @PathVariable 路径模板与 URL 匹配,非必选需 Spring 5.3+
JSON 请求体 @RequestBody 仅能使用一次,Content-Type 需为 application/json
请求头 / Cookie @RequestHeader/@CookieValue 注意参数名与头 / Cookie 名一致
文件上传 /multipart 请求 @RequestPart 替代 @RequestParam,支持文件和 JSON 混合
多参数封装到实体类 @ModelAttribute 支持级联属性,可省略注解

核心原则:显式注解优于隐式绑定,复杂场景优先使用对应注解(如 JSON 用 @RequestBody,路径参数用 @PathVariable),提升代码可读性和可维护性。

相关推荐
guslegend2 小时前
SpringBoot源码剖析
java
爱笑的眼睛112 小时前
FastAPI 路由系统深度探索:超越基础 CRUD 的高级模式与架构实践
java·人工智能·python·ai
武子康3 小时前
Java-193 Spymemcached 深入解析:线程模型、Sharding 与序列化实践全拆解
java·开发语言·redis·缓存·系统架构·memcached·guava
韩凡3 小时前
HashMap的理解与结构
java·开发语言·哈希算法
hhzz3 小时前
Spring Boot整合Activiti的项目中实现抄送功能
java·spring boot·后端
初心灬3 小时前
Java 对接coze工作流
java
代衡_Monster4 小时前
通过位运算实现Java逻辑的包含关系
java·java-ee
毕设源码-朱学姐4 小时前
【开题答辩全过程】以 基于Java的失物招领系统设计与实现为例,包含答辩的问题和答案
java·开发语言