post请求
不用@RequestBody注解
@RequestMapping("/post/test")
@PostMapping
public String testPost(StudentDTO dto) {
return dto.toString();
}
如果后台接口是这样写的话,前端请求接口用form-data
、x-www-form-urlencoded
、application/json
这三种方式发送请求,后端接口都不能接收到参数的值。
用@RequestBody注解
@RequestMapping("/post/test1")
@PostMapping
public String testPost1(@RequestBody StudentDTO dto) {
return dto.toString();
}
如果后台接口是这样写的话:
前端如果用form-data格式发送请求
- 页面会得到错误:
{"timestamp":1604191503418,"status":400,"error":"Bad Request","message":"JSON parse error: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: (PushbackInputStream); line: 1, column:
前端如果用x-www-form-urlencoded格式发送请求
- 页面会得到错误:
{"timestamp":1604191818105,"status":415,"error":"Unsupported Media Type","message":"Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"","trace":"org.springframework.web.HttpMediaTypeNotSupportedException: Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"\r\n\tat
前端如果用application/json格式发送请求
还有种情况就是后台接口定义成post,前端传的参数格式是application/json
并且,而且这个接口的参数只需要一个,目前对于这种情况下,我的解决办法是,把需要的这个参数封装到DTO
里面去,然后再用@RequestBody
来修饰这个DTO
作为入参。因为如果这个接口需要的唯一一个参数不放到DTO里面去的话,直接像下面这样的话,@RequestBody不能正确的解析调用该接口传的name字段值。个人理解@RequestBody是用来修饰对象的,而不是基本类型数据的。
@RequestMapping("/post/test2")
@PostMapping
public String testPost2(@RequestBody String name) {
StudentDTO dto = new StudentDTO();
dto.setName(name);
return dto.toString();
}
get请求
首先,get的请求的话,参数都是在请求地址后面拼接参数的方式传参数给后端接口,也就是postman上Params这个方式。所以接口如果是get请求,前端固定是用Params方式传参。所以下面的测试是建立在传参用Params的方式为前提。
后端接口用DTO入参
@RequestMapping("/get/test")
@GetMapping
public String testGETDTO(StudentDTO dto) {
dto.setId(dto.getId());
dto.setName(dto.getName());
return dto.toString();
}
请求得到错误:
{"timestamp":1604193712894,"status":415,"error":"Unsupported Media Type","message":"Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"","trace":"org.springframework.web.HttpMediaTypeNotSupportedException: Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"\r\n\tat
后端接口用DTO并且使用@RequestBody
@RequestMapping("/get/test1")
@GetMapping
public String testGETRequestBody(@RequestBody StudentDTO dto) {
dto.setId(dto.getId());
dto.setName(dto.getName());
return dto.toString();
}
请求得到错误:
{"timestamp":1604195606813,"status":415,"error":"Unsupported Media Type","message":"Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"","trace":"org.springframework.web.HttpMediaTypeNotSupportedException: Invalid mime type \"application/json, application/x-www-form-urlencoded\": Invalid token character ',' in token \"json, application/x-www-form-urlencoded\"\r\n\tat
后端接口用基本类型入参,没有用注解
@RequestMapping("/get/test2")
@GetMapping
public String testGET1(Integer id, String name) {
StudentDTO dto = new StudentDTO();
dto.setId(id);
dto.setName(name);
return dto.toString();
}
后台接收到了数据:
后端接口用基本类型入参,用@RequestParam注解
@RequestMapping("/get/test3")
@GetMapping
public String testGET2(@RequestParam Integer id, @RequestParam String name) {
StudentDTO dto = new StudentDTO();
dto.setId(id);
dto.setName(name);
return dto.toString();
}
-
如果请求这个接口的时候,只传了
id
或name
,就会报另一个必传参数没有传递的错误,因为@RequestParam
注解修饰的参数默认是必传。{"timestamp":1604195939558,"status":400,"error":"Bad Request","message":"Required String parameter 'name' is not present","trace":"org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'name' is not present\r\n\tat org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:202)\r\n\tat org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:113)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126)\r\n\tat
-
@RequestParam
修饰的参数都传递,则后台接口正确的接收
总结
-
使用接口定义为
post
请求的时候,并且接收参数格式是application/json
的话,则接口的入参用@RequestBody
,并且用@RequestBody
修饰的参数类型是对象类型,而不是String
或者其他基本类型或者基本类型的包装类。 -
使用
get
请求的时候,并且请求格式是params(参数拼接在url后面)的话,则接口的入参类型必须是基本类型或基本类型的包装类,注解的话可以用@RequestParam
也可以不用,用这个@RequestParam
注解的好处是它会校验必传参数。 -
题外篇:
- 浏览器地址栏发送的请求默认是get请求。
@RequestBody
注解做的事情,其实就是按json
的格式解析发送的请求写在Body
里面的数据。比如用postman的raw方式,然后选择body,然后在body里面按照json格式写请求参数,然后发送请求。POST
请求:可以把参数放到body
中,也可以把参数放到url中GET
请求:参数只能放到url
中,如果放到body中 服务端从body
拿到的是空的,get
不适合传输大的参数。
可以参考:https://www.zhihu.com/question/64312188