文章目录
一、@RequestParam(一个方法中能使用多次)
1. 简介
-
用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,也就是常用的Query参数拼接(
?service=110&name=spring
)。(Http协议中,如果不指定Content-Type,则默认传递的参数就是application/x-www-form-urlencoded类型)
-
RequestParam可以接受简单类型的属性,也可以接受对象类型。 实质是将Request.getParameter() 中的Key-Value参数Map利用Spring的转化机制ConversionService配置,转化成参数接收对象或字段。
-
在Content-Type: application/x-www-form-urlencoded的请求中, get 方式中queryString的值,和post方式中 body data的值都会被Servlet接受到并转化到Request.getParameter()参数集中,所以@RequestParam可以获取的到。
2. 实例
@RequestMapping("uploadStringFile")
public JsonResult uploadStringFile(@RequestParam("stringFile")String stringFile, @RequestParam("bucket") String bucket){
}
二、 @RequestBody(一个方法中能使用多次,但是建议只使用一次)
1. 简介
- 处理HttpEntity传递过来的数据,一般用来处理非Content-Type: application/x-www-form-urlencoded编码格式的数据。可以处理application/json或者是application/xml等,一般情况下来说常用其来处理application/json类型。
- GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。
- POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。
- @RequestBody注解一次性将请求体中的数据全部取出来,所以不建议在一次方法中使用多次
2.实例
$.ajax({
url:"/login",
type:"POST",
data:'{"userName":"admin","pwd","admin123"}',
content-type:"application/json charset=utf-8",
success:function(data){
alert("request success ! ");
}
});
@requestMapping("/login")
public void login(@requestBody String userName,@requestBody String pwd){
}
这种情况是将JSON字符串中的两个变量的值分别赋予了两个字符串,但是呢假如我有一个User类,拥有如下字段:
class User{
String userName;
String pwd;
}
那么上述参数可以改为以下形式:@RequestBody User user
,这种形式会将JSON字符串中的值赋予user中对应的属性上,需要注意的是,JSON字符串中的key必须对应user中的属性名,否则是请求不过去的
三、@PathVariable (一个方法中可以使用多次)
1. 简介
需要配合rest风格url使用,目的是接收rest Url中的参数,可以拼接多个
例如:
GET请求路径:http://127.0.0.1:8080/hello/4/zs
@RequestMapping(value = "/hello/{pageSize}/{name}", method = RequestMethod.GET)
public String say(@PathVariable("pageSize") String pageSize,@PathVariable("name") String name) {
}
四、@RequestPart(复杂的请求场景)
1.简介
- @RequestPart这个注解用在multipart/form-data表单提交请求的方法上。
- 支持的请求方法的方式MultipartFile,属于Spring的MultipartResolver类。这个请求是通过http协议传输的。
- @RequestParam也同样支持multipart/form-data请求。(即两者都能用于后端接收文件)
- 他们最大的不同是,当请求方法的请求参数类型不再是String类型的时候,@RequestParam适用于name-valueString类型的请求域,@RequestPart适用于复杂的请求域(像JSON,XML)。
2.实例
public Object taskSaveAttachment(@RequestPart("file") MultipartFile file,
@RequestPart("attachmentSaveVO") @Valid AttachmentSaveVO attachmentSaveVO){
}
@RequestMapping("uploadFile")
public JsonResult uploadFile(@RequestPart("file") MultipartFile file, @RequestParam String bucket){
}
@RequestPart-同时上传文件和json的解决方案
1)通过@RequestParam("josnData") String jsonData 和@RequestPart("uploadFile") MultiPartFile uploadFile
两个注解分别接受参数,此时使用@RequestParam(“josnData”)注解接受的类型只能为String,需要自行进行JSON解析String,不过能实现POST上传文件类型参数和json格式字符串参数。
@RequestMapping("uploadFile")
public JsonResult uploadFile(@RequestPart("uploadFile") MultipartFile[] uploadFiles, @RequestParam("jsonData") String jsonData){
}
2)下面这种则使用@RequestPart注解接受JSON数据,此时可以将接收的json字符串直接序列化为实例对象,注意:此时json字符串一定要声明类型 Content-Type: application/json,否则使用@RequestPart注解无法反序列化
@RequestMapping("jsonDataAndUploadFile")
@ResponseBody
public String jsonDataAndUploadFile(@RequestPart("uploadFile") List<MultipartFile> uploadFiles,
@RequestPart("jsonData") Person person) {
}
org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver#resolveArgument
HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, name);
上面两行会根据参数名称以及请求实例化请求流。
org.springframework.web.multipart.support.RequestPartServletServerHttpRequest#RequestPartServletServerHttpRequest
HttpHeaders headers = this.multipartRequest.getMultipartHeaders(this.partName);
在RequestPartServletServerHttpRequest初始化时候,会获取请求参数的请求头信息,如果头为空则会报异常操作
如果存在则会正常解析内容。
多文件
@PostMapping("/save")
public void save(@RequestPart(required = false) FormData formData,
@RequestParam(value="files", required=false) MultipartFile[] files) {
}
这里的files多文件在postman上是这样调用的:
五、总结
1. 小结
-
在GET请求中,不能使用@RequestBody。
-
在POST请求中,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,对于参数转化的配置必须统一。
举个例子,在SpringMVC配置了HttpMessageConverters处理栈中,指定json转化的格式,如Date转成‘yyyy-MM-dd’,则参数接收对象包含的字段如果是Date类型,就只能让客户端传递年月日的格式,不能传时分秒。因为不同的接口,它的参数可能对时间参数有不同的格式要求,所以这样做会让客户端调用同事对参数的格式有点困惑,所以说扩展性不高。 -
如果使用@RequestParam来接受参数,可以在接受参数的model中设置@DateFormat指定所需要接受时间参数的格式。
-
另外,使用@RequestBody接受的参数是不会被Servlet转化统一放在request对象的Param参数集中,@RequestParam是可以的。
-
综上所述,一般情况下,推荐使用@RequestParam注解来接受Http请求参数。
-
Get请求不能使用表单(没有请求体),只能在url中传参,传参方式只有这一种。 Post请求可以使用表单,也可以在url中传参。
使用表单时有几种数据类型(表现为数据的存储位置不同):
1、 x-www-form-urlencoded 参数存储在query中 用@RequestParam接收。
2、formdata 参数存储在body中,用@RequestBody接收,文件类型用@RequestPart接收。
3、raw(json,xml) 参数存储在body中 用@RequetBody接收。
总结一下: 凡是放在body中的都可以用@RequestBody接收,文件类型的数据可以用@RequestPart接收。 凡是放在query中的都可以用@RequestParam接收,包括Get方式提交和Post(x-www-form-urlencoded)方式提交的。
2. 分类
注解 | GET | POST | 支持的Content-Type | 不支持的Content-Type |
---|---|---|---|---|
@RequestBody | ✘ | ✔ | application/json,application/xml | application/x-www-form-urlencoded |
@RequestParam | ✔ | ✔ | multipart/form-data,application/x-www-form-urlencoded | … |
@RequestPart | ✔ | ✔ | multipart/form-data,application/x-www-form-urlencoded,application/json,application/xml | … |
@PathVariable | ✔ | ✔ | … | … |
六、 实际使用情况
- 如果项目组规定使用 rest 风格的api 并且参数不是很复杂不是很多的得情况下优先使用 @PathVariable 注解接收路径穿过来的参数
- 能使用@PathVariable 注解的地方都能使用 @RequestParam 进行替换 ,@RequestParam 注解既能接收get请求 问号传参过来的参数,也能接收post请求 问号传参,(post也能使用问号传参)以及post请求 并且Content-Type: 为 application/x-www-form-urlencoded 通常用于接收文件
- @RequestPart 注解可以用来替换 @RequestParam 接收文件以及其他更为复杂的数据类型(json xml等等)
- @RequestBody 多用于接收post请求 中的请求体的内容,(json数据,大多对应后端的一个实体,或Map类型的数据 等等)
- @PathVariable @RequestParam @RequestBody @RequestPart 这四个注解能混合使用,并且每一次注解都支持使用 (required = false)非必须参数