Spring MVC 参数映射学习笔记

在 Spring MVC 中,控制器(Controller)负责处理用户的请求并返回响应。一个核心任务就是接收和解析请求中的参数。Spring MVC 提供了多种灵活的方式来将请求参数绑定到控制器方法的参数上,这个过程称为参数映射。


1. 通过 HttpServletRequest 对象获取

这是最基础、最原始的方式,直接使用Servlet API来获取参数。

@RequestMapping("param01")
public Map<String, String[]> param01(HttpServletRequest request) {
    //1.获取请求参数
    Map<String, String[]> map = request.getParameterMap();
    return map;
}

注意事项:

  • 返回的Map<String, String[]>中,值是一个字符串数组,因为一个参数名可能对应多个值(例如,复选框)。
  • 需要手动进行类型转换,例如从String转换为IntegerDate
  • 这种方式与Servlet API耦合度较高,在纯粹的Spring MVC开发中不常用,但在需要访问底层请求对象(如获取请求头、Session等)时仍然很有用。

常用使用场景:

  • 需要获取所有请求参数,但参数名不确定时。
  • 需要访问除了请求参数之外的其他请求信息,如请求头(Header)、Cookies 或会话(Session)。
  • 在一些遗留代码或需要与Servlet API进行深度交互的特定场景下使用。

2. 方法参数直接映射

Spring MVC 可以自动将请求参数按名称匹配到控制器方法的同名参数上。

@RequestMapping("/pararm03")
public Map<String,Object> pararm03(String uname, Integer age){
    Map<String,Object> map = new HashMap<>();
    map.put("uname", uname);
    map.put("age", age);
    return map;
}

注意事项:

  • 参数名称必须完全一致。请求中的参数名(如 ?uname=zhangsan&age=25)必须与方法中的参数名(uname, age)相同。
  • Spring MVC 会自动进行简单的类型转换。例如,将"25"自动转换为Integer类型的25。如果转换失败(如"abc"无法转为Integer),会抛出异常。
  • 如果请求中没有传递某个参数,对应的参数值会是 null(对于对象类型)或默认值(对于基本数据类型,但可能引发异常,建议使用包装类型如Integer)。

常用使用场景:

  • 处理简单、参数数量较少的GET或POST请求。
  • 当前后端参数命名规范统一时,这是最简洁、最直观的映射方式。

3. 通过 @RequestParam 注解映射

这是对直接映射的增强,提供了更多的控制选项,是处理单个参数时最常用的注解。

@RequestMapping("/pararm04")
public Map<String,Object> pararm04(
    @RequestParam(value = "username", required = false) String uname,
    @RequestParam(value = "age", defaultValue = "20") Integer age
){
    Map<String,Object> map = new HashMap<>();
    map.put("uname", uname);
    map.put("age", age);
    return map;
}

注意事项:

  • value (或 name): 用于指定请求参数的名称。当方法参数名与请求参数名不一致时(例如前端传username,后端用uname接收),必须使用此属性。
  • required: 布尔类型,默认为true
    • true (默认): 表示该参数必须传递,否则会报400错误(Bad Request)。
    • false: 表示该参数是可选的,如果不传递,则参数值为null
  • defaultValue: 字符串类型。如果请求中没有传递该参数,或者传递的值为空,则会使用这个默认值。注意,设置了defaultValue后,required属性会自动变为false

常用使用场景:

  • 当前后端参数名称不一致时。
  • 需要对参数进行校验,如设置某个参数为必传或可选。
  • 希望为某个参数提供一个默认值,以简化客户端的请求。

4. 通过实体类(POJO)进行映射

当请求参数较多时,可以使用一个实体类来统一接收,使代码更加整洁和结构化。

@RequestMapping("/pararm05")
public User pararm05(User user){ // Spring MVC自动创建User对象并填充属性
   return user;
}

注意事项:

  • 属性名与参数名必须一致。Spring MVC会通过调用实体类的setter方法来注入属性值。例如,请求参数uname会对应调用setUname()方法。
  • 实体类必须有一个无参构造函数,以便Spring MVC能够实例化它。
  • 支持级联属性映射,例如 ?address.city=beijing 可以映射到User对象中Address类型属性的city字段。

常用使用场景:

  • 表单提交,特别是当表单字段与数据库实体或业务模型相对应时。
  • 当请求参数超过3-4个时,使用实体类可以极大地提高代码的可读性和可维护性。
  • 适用于 application/x-www-form-urlencodedmultipart/form-data 类型的请求。

5. 通过 @PathVariable 注解进行映射

用于从URL路径中动态获取参数,是实现RESTful风格API的关键。

// 请求URL: localhost:8080/param/pararm06/admin/123456
@RequestMapping("/pararm06/{username}/{pwd}")
public Map<String,Object> pararm06(@PathVariable("username") String uname, @PathVariable String pwd){
    Map<String,Object> map = new HashMap<>();
    map.put("uname", uname);
    map.put("pwd", pwd);
    return map;
}

注意事项:

  • @RequestMapping的路径中必须使用占位符{...}来定义变量。
  • @PathVariable注解的参数名需要和占位符名称一致。如果不一致,可以通过 @PathVariable("占位符名") 来指定。
  • @PathVariable标记的参数默认为必传,因为它是URL路径的一部分。

常用使用场景:

  • RESTful API设计,例如查询特定资源 (/users/{id})、删除特定资源 (/products/{productId}) 等。
  • 当参数是资源的唯一标识符时,将其放在URL路径中比放在查询字符串中语义更清晰。

6. 通过 @RequestBody 注解获取请求体数据

用于接收HTTP请求体中的内容,通常是JSON或XML格式的数据。

// 接收JSON对象
@RequestMapping("/param07")
public User param07(@RequestBody User user){
    return user;
}

// 接收JSON数组
@RequestMapping("param08")
public List<User> param08(@RequestBody List<User> users) {
    return users;
}

注意事项:

  • 一个请求方法中只能有一个 @RequestBody 注解,因为它会读取整个请求体。
  • 前端请求方式通常为 POSTPUT,并且需要设置 Content-Typeapplication/json (或 application/xml 等)。
  • Spring MVC需要配合相应的HttpMessageConverter(如MappingJackson2HttpMessageConverter)来将JSON字符串反序列化为Java对象。通常,在引入spring-boot-starter-web依赖后会自动配置好。
  • 对于JSON到对象的映射,JSON对象的字段名需要和Java类的属性名一致(或通过Jackson的注解如@JsonProperty进行映射)。

常用使用场景:

  • 前后端分离项目中,接收前端通过AJAX提交的JSON格式数据。
  • 创建或更新资源时,客户端将资源的完整信息以JSON格式放在请求体中发送。
  • 接收复杂的数据结构,如嵌套对象、对象列表等。