场景如下:
前端vue使用axios向后台发了一个Content-type为application/json
的post请求,
后台springmvc接口如下:
@RequestMapping("xxx")
public Result xxx(User user) {
Result result = Result.getSuccessResult();
return result;
}
发现接收不到user的信息。
改为 request.getParamter 也一样接收不到。
搜索一番,从这篇博客找到了答案
AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。
HTTP POST表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使用原生AJAX的POST请求如果不指定请求头RequestHeader,默认使用的Content-Type是text/plain;charset=UTF-8。
由于Tomcat对于Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)做了“特殊处理”。
服务器为什么会对表单提交和文件上传做特殊处理,是因为表单提交数据是名值对的方式,且Content-Type为application/x-www-form-urlencoded,而文件上传服务器需要特殊处理,普通的post请求(Content-Type不是application/x-www-form-urlencoded)数据格式不固定,不一定是名值对的方式,所以服务器无法知道具体的处理方式,所以只能通过获取原始数据流的方式来进行解析。
总结为:原生ajax如果不指定Context-type
默认使用text/plain;charset=UTF-8
,jquery的ajax则是application/x-www-form-urlencoded
,而axios底层正是使用了原生的ajax,后端会对非Content-type不为application/x-www-form-urlencoded
的请求做特殊处理,由此导致后端request.getParameter()
无法接收。
解决方法:
1、不使用框架的情况下,使用原始的读取流的方式:
private String getRequestPayload(HttpServletRequest req) {
StringBuildersb = new StringBuilder();
try(BufferedReaderreader = req.getReader();) {
char[]buff = new char[1024];
intlen;
while((len = reader.read(buff)) != -1) {
sb.append(buff,0, len);
}
}catch (IOException e) {
e.printStackTrace();
}
returnsb.toString();
}
2、使用spring框架:
加入@RequestBody
注解,如下:
@RequestMapping("xxx")
public Result xxx(@RequestBody User user) {
Result result = Result.getSuccessResult();
return result;
}