侧边栏壁纸
博主头像
包包博主等级

talk is cheap,show me the code

  • 累计撰写 25 篇文章
  • 累计创建 59 个标签
  • 累计收到 30 条评论

SpringBoot后端接口请求参数映射方式详解

包包
2021-07-31 / 0 评论 / 5 点赞 / 1,084 阅读 / 7,918 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-19,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

在SpringBoot项目中,前端HTTP请求中的参数如何映射到Controller层的接口方法中的参数?这里针对各种方式做一个测试与总结,测试采用的SpringBoot版本号为2.2.10.RELEASE

QueryString方式

QueryString参数传递的方式为,在请求URL中直接拼接请求参数,如URL?param1=value1&param2=value2

QueryString参数传递方式对于请求方法GETPOSTPUTPATCHDELETE都适用

1.映射基本类型参数

可以在Controller的接口中声明基本类型的参数,然后用@RequestParam注解修饰,指定前端传递的参数名称

@RestController
@RequestMapping("param")
@Slf4j
public class RequestParamTestController {
    @RequestMapping("queryString1")
    public void testQueryString1(@RequestParam("name") String name, @RequestParam("age") Integer age) {
        log.info("name:{}   age:{}", name, age);
    }
}

测试结果如下

  • 如果请求参数名称和Controller中接口方法的参数名称一致,那么可以省略@RequestParam注解。不过一般还是建议加上

  • 当请求参数名称和Controller中接口方法的参数名称一致时,加与不加@RequestParam的区别是:

    • 加上@RequestParam,其属性required默认为true,那么当前端不传递对应的参数时将会抛出异常

    • 不加@RequestParam,前端可以不传递对应参数,此时Controller接口方法中的参数接收到的值为null

2.映射对象类型参数

定义一个对象,属性名称和前端传递的参数名称一致即可

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
}

然后将Controller接口方法中的参数声明为自定义对象

@RequestMapping("queryString2")
public void testQueryString2(User user) {
    log.info("name:{}   age:{}", user.getName(), user.getAge());
}

测试结果如下

3.映射数组、集合类型参数

前端有2种方式针对同一个参数传递多个值:

  • 在请求的QueryString中,拼接多个参数名称一样的参数即可,如URL?param=value1&param=value2&param=value3
  • 在请求的QueryString中,对同一个参数赋多个值,多个值之间用,隔开,如URL?param=value1,value2,value3

3.1 映射数组

在Controller接口方法中声明数组类型参数,用@RequestParam指明前端传递的参数名称即可

@RequestMapping("queryString3")
public void testQueryString3(@RequestParam("name") String[] nameArray) {
    if (nameArray != null) {
        for (String name : nameArray) {
            log.info(name);
        }
    }
}

测试结果如下

如果请求参数名称和Controller中接口方法的参数名称一致,那么可以省略@RequestParam注解。不过一般还是建议加上

3.2 映射Collection

在Controller接口方法中声明Collection类型参数,用@RequestParam指明前端传递的参数名称即可

@RequestMapping("queryString4")
public void testQueryString4(@RequestParam("name") Collection<String> nameCollection) {
    if (nameCollection != null) {
        log.info("类型:{}", nameCollection.getClass());
        for (String name : nameCollection) {
            log.info(name);
        }
    }
}

测试结果如下

可以发现框架默认采用的实现类是LinkedHashSet。那我们继续测试传递相同value的时候是否也会采用这个实现

可以发现传递多个相同value的时候框架采用的实现类还是LinkedHashSet,所以有去重的效果

3.3 映射List

在Controller接口方法中声明List类型参数,用@RequestParam指明前端传递的参数名称即可

@RequestMapping("queryString5")
public void testQueryString5(@RequestParam("name") List<String> nameList) {
    if (nameList != null) {
        log.info("类型:{}", nameList.getClass());
        for (String name : nameList) {
            log.info(name);
        }
    }
}

测试结果如下

可以发现框架默认采用的实现类是ArrayList

3.4 映射Set

在Controller接口方法中声明Set类型参数,用@RequestParam指明前端传递的参数名称即可

@RequestMapping("queryString6")
public void testQueryString6(@RequestParam("name") Set<String> nameSet) {
    if (nameSet != null) {
        log.info("类型:{}", nameSet.getClass());
        for (String name : nameSet) {
            log.info(name);
        }
    }
}

测试结果如下

可以发现框架默认采用的实现类是LinkedHashSet,与声明为Collection类型时一致

注意:

  • 也可以在自定义对象中将属性声明为数组、集合类型,来接收多个值

  • 对于映射CollectionListSet类型参数时,即便前端提交的QueryString中的参数名称与Controller接口方法的参数名称一致,也不能省略@RequestParam注解,否则会抛出如下异常

路径参数方式

路径传参方式是将参数直接包含在URL路径中,比如URL/paramValue1/paramValue2

路径参数方式对于请求方法GETPOSTPUTPATCHDELETE都适用

1.映射基本类型参数

在Controller中用如下步骤接收参数:

  1. 在接口对应的请求路径中用{参数名}形式标出路径参数
  2. 在接口方法的参数上标注@PathVariable指名对应路径参数的参数名
@RequestMapping("path1/{name}/{age}")
public void testPath1(@PathVariable("name") String name, @PathVariable("age") Integer age) {
    log.info("name:{}   age:{}", name, age);
}

测试结果如下

如果接口方法上@RequestMapping中路径参数的参数名称和接口方法的参数名称相同,可以省略@PathVariable注解。但一般推荐加上

2.映射数组、集合类型参数

直接给路径参数多个值,用,隔开即可

2.1 映射数组

在Controller接口方法中声明数组类型参数,用@PathVariable指明路径参数的名称即可

@RequestMapping("path2/{name}/{age}")
public void testPath2(@PathVariable("name") String[] nameArray, @PathVariable("age") Integer[] ageArray) {
    for (String name : nameArray) {
        log.info(name);
    }
    for (Integer age : ageArray) {
        log.info(age.toString());
    }
}

测试结果如下

2.2 映射Collection

在Controller接口方法中声明Collection类型参数,用@PathVariable指明路径参数的名称即可

@RequestMapping("path3/{name}/{age}")
public void testPath3(@PathVariable("name") Collection<String> nameCollection, @PathVariable("age") Collection<Integer> ageCollection) {
    log.info("类型:{}", nameCollection.getClass());
    for (String name : nameCollection) {
        log.info(name);
    }
    for (Integer age : ageCollection) {
        log.info(age.toString());
    }
}

测试结果如下

可以发现框架默认采用的类型是LinkedHashSet

2.3 映射List

在Controller接口方法中声明List类型参数,用@PathVariable指明路径参数的名称即可

@RequestMapping("path4/{name}/{age}")
public void testPath4(@PathVariable("name") List<String> nameList, @PathVariable("age") List<Integer> ageList) {
    log.info("类型:{}", nameList.getClass());
    for (String name : nameList) {
        log.info(name);
    }
    for (Integer age : ageList) {
        log.info(age.toString());
    }
}

测试结果如下

框架采用的实现类是ArrayList

2.4 映射Set

在Controller接口方法中声明Set类型参数,用@PathVariable指明路径参数的名称即可

@RequestMapping("path5/{name}/{age}")
public void testPath5(@PathVariable("name") Set<String> nameSet, @PathVariable("age") Set<Integer> ageSet) {
    log.info("类型:{}", nameSet.getClass());
    for (String name : nameSet) {
        log.info(name);
    }
    for (Integer age : ageSet) {
        log.info(age.toString());
    }
}

测试结果如下

框架采用的实现类是LinkedHashSet

路径参数方式映射到Controller接口方法中的数组CollectionListSet类型参数时,即便路径中的参数名称和接口方法中的参数名称一致,也不能省略@PathVariable注解

表单参数方式

表单参数方式要求在请求头中携带Content-Type,值为application/x-www-form-urlencoded,并且请求体中以param:value形式携带参数,每行代表一个参数,多个参数就有多行

注意:表单参数方式不适用于GET请求,适用于POSTPUTPATCHDELETE

1.映射基本类型参数

可以在Controller的接口中声明基本类型的参数,然后用@RequestParam注解修饰,指定请求体中的参数名称

@RequestMapping("form1")
public void testForm1(@RequestParam("name") String name, @RequestParam("age") Integer age) {
    log.info("name:{}   age:{}", name, age);
}

测试结果如下

2.映射对象类型参数

定义一个对象,属性名称和请求体中的参数名称一致即可

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
}

然后将Controller接口方法中的参数声明为自定义对象

@RequestMapping("form2")
public void testForm2(User user) {
    log.info("name:{}   age:{}", user.getName(), user.getAge());
}

测试结果如下

3.映射数组、集合类型参数

请求体中的参数如果想要传递多个值,有2种方式:

  • 直接给参数多个值,用,隔开即可
  • 声明多个参数名一样的参数

3.1 映射数组

在Controller接口方法中声明数组类型参数,用@RequestParam指明请求体中的参数名称即可

@RequestMapping("form3")
public void testForm3(@RequestParam("name") String[] nameArray) {
    for (String name : nameArray) {
        log.info(name);
    }
}

测试结果如下

3.2 映射Collection

在Controller接口方法中声明Collection类型参数,用@RequestParam指明请求体中的参数名称即可

@RequestMapping("form4")
public void testForm4(@RequestParam("name") Collection<String> nameCollection) {
    log.info("类型:{}", nameCollection.getClass());
    for (String name : nameCollection) {
        log.info(name);
    }
}

测试结果如下

3.3 映射List

在Controller接口方法中声明List类型参数,用@RequestParam指明请求体中的参数名称即可

@RequestMapping("form5")
public void testForm5(@RequestParam("nameList") List<String> nameList) {
    log.info("类型:{}", nameList.getClass());
    for (String name : nameList) {
        log.info(name);
    }
}

测试结果如下

3.4 映射Set

在Controller接口方法中声明Set类型参数,用@RequestParam指明请求体中的参数名称即可

@RequestMapping("form6")
public void testForm6(@RequestParam("name") Set<String> nameSet) {
    log.info("类型:{}", nameSet.getClass());
    for (String name : nameSet) {
        log.info(name);
    }
}

测试结果如下

也可以在自定义对象中将属性声明为数组、集合类型,来接收多个值

FormData方式

用于文件上传。要求在请求头中携带Content-Type,值为multipart/form-data。请求体中可以携带普通参数,也可以携带文件

Postman测试发现这种方式适用于GETPOSTPUTPATCHDELETE,但浏览器一般只能用POST表单提交进行文件上传,所以建议用POST请求

可以在Controller的接口中分别声明普通类型参数和文件类型参数,其中文件类型参数必须是MultipartFile类型,然后用@RequestParam注解修饰,指定请求体中对应的参数名称

@RequestMapping("formData1")
public void testFormData1(@RequestParam("fileName") String fileName, @RequestParam("file")MultipartFile file) {
    log.info("{}:{}", fileName, file.getSize());
}

测试结果如下

FormData方式中的普通参数(即非文件类型参数)同样也可以利用数组、集合类型接收多个值,可以封装为自定义对象,方法与表单参数方式类似

请求体json方式

要求请求头携带Content-Type,值为application/json。请求体中的内容为json格式

在Controller的接口方法映射这种请求参数只能通过自定义对象,自定义对象的属性名称要与请求体中json的属性名称一致,然后将自定义对象作为接口方法的参数,并标注@RequestBody注解,框架会自动将请求体的json转换为自定义对象

@RequestMapping("json1")
public void testJson1(@RequestBody User user) {
    log.info(user.toString());
}

测试结果如下

经过PostMan测试发现,用GET方法发送这种请求也可以顺利接收到参数,但是一般浏览器不支持GET请求携带请求体数据,所以还是建议实际开发中只针对POSTPUTPATCHDELETE采用这种方式进行参数映射

5

评论区