Spring MVC:@RequestParam 注解详解

Spring MVC @RequestParam 注解详解

适用范围:Spring MVC / Spring Boot Web(@RestController / @Controller)

@RequestParam 用于把 HTTP 请求中的"请求参数(query string / 表单字段)"绑定到控制器方法的参数上。

  • 常见参数来源:
    • URL 查询参数:/api/list?current=1&pageSize=10
    • 表单提交(application/x-www-form-urlencoded 或 multipart/form-data)
    • multipart/form-data 中的普通字段与文件字段(文件字段通常用 MultipartFile 接收)

它解决的问题是:让你不用手动从 HttpServletRequest 里取参数,而是通过声明式方式直接拿到类型安全的 Java 参数。

演示(对比写法):

不使用 @RequestParam(手动取参):

java 复制代码
@PostMapping("/list")
public String list(HttpServletRequest request) {
    // URL: /list?current=1&pageSize=10
    String current = request.getParameter("current");
    String pageSize = request.getParameter("pageSize");
    return "current=" + current + ", pageSize=" + pageSize;
}

1. 基本用法

1.1 绑定同名参数

java 复制代码
@PostMapping("/list")
public BaseResponse<?> list(
        @RequestParam int current,
        @RequestParam int pageSize) {
    // ...
}

请求示例:

  • POST /admin/knowledge/list?current=1&pageSize=10
  • 或表单:current=1&pageSize=10

Spring 会将字符串参数自动转换为 int。

1.2 指定参数名

java 复制代码
public String foo(@RequestParam("user_id") Long userId) {
    return "ok";
}

表示从请求参数 user_id 取值,绑定到 Java 参数 userId。


2. 常用属性说明

@RequestParam 常见属性:

2.1 value / name

  • value 与 name 互为别名,都是请求参数名。
java 复制代码
@RequestParam("name") String name
@RequestParam(name = "name") String name

2.2 required

  • 默认:true(必传)
  • 若请求中没有该参数:
    • required=true:抛异常(常见为 400 Bad Request)
    • required=false:参数为 null(或对基本类型需配合 defaultValue/改用包装类型)

示例:

java 复制代码
@RequestParam(value = "name", required = false) String name

2.3 defaultValue

  • 为参数提供默认值。
  • 一旦设置了 defaultValue,即使 required=true 也不会因为缺失而报错(会使用默认值)。

示例:

java 复制代码
@RequestParam(defaultValue = "1") int current,
@RequestParam(defaultValue = "10") int pageSize

3. 与 @RequestBody 的区别(非常重要)

  • @RequestParam:取 请求参数
    • query string:?a=1&b=2
    • 表单字段:a=1&b=2
    • multipart 表单字段
  • @RequestBody:取 请求体 body ,通常是 JSON
    • Content-Type: application/json
    • body:{"a":1,"b":2}

何时用哪个?

  • 传分页、过滤条件(简单字段)→ 常用 @RequestParam
  • 传复杂对象/列表 JSON → 常用 @RequestBody
  • 上传文件 → 常用 @RequestParam MultipartFile file

4. 实际例子解读

4.1 单文件上传 + 可选名称

java 复制代码
@PostMapping("/upload")
public BaseResponse<KnowledgeDocument> uploadDocument(
        @RequestParam("file") MultipartFile file,
        @RequestParam(value = "name", required = false) String name) {
    // ...
}

含义:

  • file:必传,来自 multipart 的文件字段名 file
  • name:可不传,来自 multipart 的普通字段 name

请求示例(multipart/form-data):

  • 表单字段:name=xxx
  • 文件字段:file=<选择文件>

4.2 分页与过滤条件

java 复制代码
@PostMapping("/list")
public BaseResponse<Page<KnowledgeDocument>> listDocuments(
        @RequestParam(defaultValue = "1") int current,
        @RequestParam(defaultValue = "10") int pageSize,
        @RequestParam(value = "name", required = false) String name,
        @RequestParam(value = "type", required = false) String type) {
    // ...
}

含义:

  • current:默认第 1 页
  • pageSize:默认每页 10 条
  • name/type:可选过滤条件,没传就是 null

4.3 多文件上传

java 复制代码
@PostMapping("/batch-upload")
public BaseResponse<BatchUploadResultVO> batchUploadDocuments(
        @RequestParam("files") MultipartFile[] files,
        @RequestParam(value = "names", required = false) List<String> names) {
    // ...
}

含义:

  • files:必传,multipart 中字段名 files,可上传多个文件(MultipartFile[])
  • names:可选,可传多个同名字段形成列表,例如:
    • names=文档1&names=文档2&names=文档3

5. 常见坑与建议

  1. 基本类型与 required=false

    • int current 无法为 null,如果你写 required=false 但不传,会报错。
    • 解决:
      • 用包装类型:Integer current
      • 或设置 defaultValue
  2. 参数名不一致导致绑定失败

    • 前端传的是 page_size,后端写的是 pageSize,会取不到。
    • 解决:显式指定:@RequestParam("page_size") int pageSize。
  3. @RequestParam 不适用于 JSON body

    • 如果前端 Content-Type: application/json,参数在 body 里,必须用 @RequestBody(或对象接收)。
  4. 文件上传必须是 multipart

    • MultipartFile 只有在 multipart/form-data 下才会被正确解析。
相关推荐
聚美智数2 小时前
智能结构化识别-图片结构解析-图像结构化解析-照片结构化解析
android·java·数据库
十年Java程序媛3 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
我是人✓3 小时前
SpringBoot静态资源映射揭秘
java·spring boot·后端
土豆.exe3 小时前
nf_tables 的 verdict 被读了两次:一个十年未闭合的位域错配
java·数据库·网络安全·缓存
小坏讲微服务4 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
kunicoding5 小时前
多线程编程核心概念详解:从线程基础到并发安全
java·jvm·安全
snow@li5 小时前
SpringBoot:核心注解全景梳理 / @xxx 叫“注解”(Annotation)
java·spring
devilnumber5 小时前
避坑_IDEA 提取方法(Extract Method)工具
java·ide·intellij-idea
鬼手点金5 小时前
Agent 的学习机制:后训练、上下文学习与外部化学习
java·人工智能·git·学习·自动化·nanogpt
小陈不好吃6 小时前
equals 与 hashCode 的契约关系:从 HashMap 到 Lombok 注解
java·hashmap·lombok