SpringBoot传递单⼀参数时@RequestParam和
@RequestBody的区别
⽤SpringBoot框架做项⽬时,经常需要前端给后端传递参数,如果需要多条参数,通常的做法是把这些参数封装为⼀个对象来传递,前端⽤POST⽅式调⽤。但有时会遇到后端只需要⼀条参数(⽐如⼀个String)的情况,此时如果还封装为⼀个对象,有些⿇烦;最好的办法是⽤GET⽅式调⽤,直接把参数拼接在url后⾯。然⽽,⼀般项⽬都有统⼀的接⼝规范,要求接⼝都要⽤POST⽅式,此时就遇到⼀个问题:controller⽅法上到底是⽤@RequestParam注解还是⽤@RequestBody注解?
之前对这两个注解的区别,只有⼀个粗枝⼤叶的理解——@RequestParam针对单⼀的参数,⽽@RequestBody针对多个参数封装为⼀个对象,问了⾝边⼏个同事,⼤概也都是这种理解。但是,实际测试中(使⽤Postman),当我⽤@RequestParam接受String的单⼀参数时,前端给我传递的参数却接收不到。于是决定通过实验,彻底搞明⽩⼆者的区别(针对单⼀参数、且规定使⽤POST⽅式的场景)。实验的过程是分别⽤两个注解去接受前端传递的⼀个名为content的String。
实验⼀:使⽤@RequestParam注解
Controller⽅法代码:(省略其他部分以及返回值Result代码)
@RequestMapping(value="/requestParam", method= RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Result<String> requestParam(@RequestParam("content") String content) {
System.out.println("content:"+content);
return success(new Result<String>(), content);
现在我⽤postman来测试⼏种可能的参数传递⽅式:
1. 在Body的raw⾥⾯传递,也是最通常的传参⽅式:
结果是接收不到(不管是⽤text还是json等各种⽂本形式)!
{ "timestamp": 1544798083474,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter 'content' is not present",
"path": "/testParam/requestParam"
}
2. 在Headers⾥通过key-value的形式传递。这是⽹上⼀些帖⼦⾥说的⽅式。
但结果还是接收不到!和上⾯⼀样报错400。
关于这⼀点,⽹上有些帖⼦⾥说@RequestParam的参数会写到Headers⾥,可见是错误的,并⾮在Headers⾥,还是在Body⾥。
3. 在Body的form-data⾥通过key-value的形式传递,可以接收!前端测试和后端测试的区别
但是,前端在传参时,是⽆法向这个form-data⾥传递参数的,所以这种⽅法只能被排除。
4. 在url后问号拼接参数。和很多⼈⼀样,之前⼀直根深蒂固地认为只有GET⽅式才能⽤url问号传参,POST⽅式不⾏,但事实证明在这⾥问号传参POST⽅式同样能接收到。如图:
虽然能接受到参数,但前端也有统⼀的规范,⼀般不使⽤问号传参的⽅式,所以这种⽅法也被排除。
实验⼆:使⽤@RequestBody注解
@RequestMapping(value="/requestBody", method= RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Result<String> requestBody(@RequestBody String content) {
System.out.println("content:"+content);
return success(new Result<String>(), content);
}
既然是Body,⾃然不能在header⾥传参,也不能在url⾥问号传参。⾄于Body的form-data,经测试也⽆效。所以,这⾥只有唯⼀⼀种⽅式,就是将参数直接写在Body的raw模式下,可以接收到,⽽且最好选择Text⽽⾮JSON(application/json),如图:
注意:这⾥body体⾥⾯传什么内容,后台就会原样接收,所以不要写成content: XXX这种键值对形式,⽽应直接把String的内容写在body体⾥。
总结:
对于传递单⼀参数(最典型的是String)的场合,最简便的⽅法是⽤GET请求。但鉴于很多项⽬接⼝统⼀要求使⽤POST⽅式,此时不能使⽤@RequestParam⽅式,因为此⽅式前端传递的参数后端⽆法接收;⽽只能⽤@RequestBody,直接将需要的参数内容写⼊Body体,后端即可正常获取!