前后端分离。前端POST请求参数过长,导致400错误解决办法及分析
2017-10-17 10:08
1756 查看
这两天做好的功能要上线了。但是测试的时候忽然发现当POST提交数据量多大时,会导致后端报400错误。最开始以为瓶颈存在于tomcat,因为tomcat默认能接受的POST请求大小为2M,所以手动修改tomcat server.xml 文件,将接受POST大小修改为不限制。 经测试,发现依旧不起作用。 今天上网查询了相关资料,解决了这个问题。资料比较零散,在这里整理一下,为同样遇到该问题的伙伴们提供一个解决思路。也为自己以后再遇到这种问题做个笔记。
首先看了一下前端提交的Content-type 发现是application/x-www-form-urlencoded
然后就根据这个去查找相关问题,找到如下文章:
http://hongjiang.info/http-application-x-www-form-urlencoded/#comments
里面介绍的有几句话起到了很大的作用:
同事遇到在servlet端通过request对象getInputStream读取POST过来的数据,却读不到的问题,怀疑是tomcat的问题。查了一下
熟悉servlet的话,这个问题应该算常识了。它其实跟容器无关,所有的servlet容器都是这样的行为。几年前在实现一个网关代理的时候就遇到过这个问题,当时使用的是jetty,发现POST过来的数据读不到,也是
在servlet规范3.1.1节里,对POST数据何时会被当做parameters有描述:
规范里已经明确的声明当请求满足: 1) http/https, 2) POST, 3) Content-type 是
4) 调用过getParameter方法;则数据会被当做请求的paramaters,而不能再通过 request 的 inputstream 直接读取。
这里给了我很大的思路,说是POST提交,实则在我spring mvc中是这么写的:
[java] view
plain copy
/**
* 保存盘点记录
*
* @param data
* @return
*/
@ResponseBody
@RequestMapping(value = "/saveStoreCheck", method = RequestMethod.POST)
public AjaxResult saveStoreCheck(String data) {
GoodsJson materials = new Gson().fromJson(data, InventoryCheckIn.class);
inventoryCheckIn.setCheckId(ShopUUID.getUUID(ShopUUID.UUID_CHECK));
inventoryCheckIn.setKtvId(ShopConstUtil.getShopId());
try {
String checkId = inventoryCheckService.saveStoreCheck(inventoryCheckIn);
return AjaxResult.getOK(checkId);
} catch (InventoryCheckException | AccessToLibraryException | AllotException e) {
return AjaxResult.getLogicError(e.getMessage(), "");
}
}
在我看来,这样的写法实际上传过来的参数依旧是会拼成类似于URL参数一样过来。所以当长度过长时,会导致出错。所以就将提交方式 Content-type修改为了application/json 这种JSON格式,不会限制传过来的大小。同时后台接收也就需要修改。代码修改为:
[java] view
plain copy
/**
* 保存盘点记录
*
* @param data
* @return
*/
@ResponseBody
@RequestMapping(value = "/saveStoreCheck", method = RequestMethod.POST,produces="application/json")
public AjaxResult saveStoreCheck(@RequestBody InventoryCheck inventoryCheckIn) {
inventoryCheckIn.setCheckId(ShopUUID.getUUID(ShopUUID.UUID_CHECK));
inventoryCheckIn.setKtvId(ShopConstUtil.getShopId());
try {
String checkId = inventoryCheckService.saveStoreCheck(inventoryCheckIn);
return AjaxResult.getOK(checkId);
} catch (InventoryCheckException | AccessToLibraryException | AllotException e) {
return AjaxResult.getLogicError(e.getMessage(), "");
}
}
直接使用对象接收,不需要再进行JSON转换。这样问题就解决了。
http://blog.csdn.net/andong154564667/article/details/52087346
首先看了一下前端提交的Content-type 发现是application/x-www-form-urlencoded
然后就根据这个去查找相关问题,找到如下文章:
http://hongjiang.info/http-application-x-www-form-urlencoded/#comments
里面介绍的有几句话起到了很大的作用:
同事遇到在servlet端通过request对象getInputStream读取POST过来的数据,却读不到的问题,怀疑是tomcat的问题。查了一下
Content-type是
application/x-www-form-urlencoded,估计是被解析成了
parameters,果然在他获取流之前,有过
request.getParameter的操作。
熟悉servlet的话,这个问题应该算常识了。它其实跟容器无关,所有的servlet容器都是这样的行为。几年前在实现一个网关代理的时候就遇到过这个问题,当时使用的是jetty,发现POST过来的数据读不到,也是
application/x-www-form-urlencoded编码,断点跟踪发现是在获取流之前有过
request.getParameter,数据会被解析,并且后续数据流不可再被读取。
在servlet规范3.1.1节里,对POST数据何时会被当做parameters有描述:
1. The request is an HTTP or HTTPS request. 2. The HTTP method is POST. 3. The content type is application/x-www-form-urlencoded. 4. The servlet has made an initial call of any of the getParameter family of methods on the request object. If the conditions are met, post form data will no longer be available for reading directly from the request object’s input stream.
规范里已经明确的声明当请求满足: 1) http/https, 2) POST, 3) Content-type 是
application/x-www-form-urlencoded,
4) 调用过getParameter方法;则数据会被当做请求的paramaters,而不能再通过 request 的 inputstream 直接读取。
这里给了我很大的思路,说是POST提交,实则在我spring mvc中是这么写的:
[java] view
plain copy
/**
* 保存盘点记录
*
* @param data
* @return
*/
@ResponseBody
@RequestMapping(value = "/saveStoreCheck", method = RequestMethod.POST)
public AjaxResult saveStoreCheck(String data) {
GoodsJson materials = new Gson().fromJson(data, InventoryCheckIn.class);
inventoryCheckIn.setCheckId(ShopUUID.getUUID(ShopUUID.UUID_CHECK));
inventoryCheckIn.setKtvId(ShopConstUtil.getShopId());
try {
String checkId = inventoryCheckService.saveStoreCheck(inventoryCheckIn);
return AjaxResult.getOK(checkId);
} catch (InventoryCheckException | AccessToLibraryException | AllotException e) {
return AjaxResult.getLogicError(e.getMessage(), "");
}
}
在我看来,这样的写法实际上传过来的参数依旧是会拼成类似于URL参数一样过来。所以当长度过长时,会导致出错。所以就将提交方式 Content-type修改为了application/json 这种JSON格式,不会限制传过来的大小。同时后台接收也就需要修改。代码修改为:
[java] view
plain copy
/**
* 保存盘点记录
*
* @param data
* @return
*/
@ResponseBody
@RequestMapping(value = "/saveStoreCheck", method = RequestMethod.POST,produces="application/json")
public AjaxResult saveStoreCheck(@RequestBody InventoryCheck inventoryCheckIn) {
inventoryCheckIn.setCheckId(ShopUUID.getUUID(ShopUUID.UUID_CHECK));
inventoryCheckIn.setKtvId(ShopConstUtil.getShopId());
try {
String checkId = inventoryCheckService.saveStoreCheck(inventoryCheckIn);
return AjaxResult.getOK(checkId);
} catch (InventoryCheckException | AccessToLibraryException | AllotException e) {
return AjaxResult.getLogicError(e.getMessage(), "");
}
}
直接使用对象接收,不需要再进行JSON转换。这样问题就解决了。
http://blog.csdn.net/andong154564667/article/details/52087346
相关文章推荐
- 前后端分离。前端POST请求参数过长,导致400错误解决办法及分析
- 前端POST请求过长——后端接收参数失败
- post请求参数过长浏览器报400错误
- 详解tomcat 解决 POST请求传参数过长受限制的问题
- AngularJs中$http发送post或者get请求,SpringMVC后台接收不到参数值的解决办法
- 前后端分离,传参数出现400错误
- 详解get请求和post请求参数中文乱码的解决办法
- Post请求方式长度参数过长导致参数为空
- 腾讯微博Oauth认证页面 提示服务请求参数错误 解决办法
- SpringBoot页面表单请求失败,错误400的解决办法
- angular的post请求,SpringMVC后台接收不到参数值的解决办法(参考加自创)
- vue2.0 axios发送post请求,后端参数获取不到的解决方式
- 后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法
- Nodejs发送Post请求时出现socket hang up错误的解决办法
- LR模拟请求中出现中文字符串导致错误的解决办法_lr_convert_string_encoding
- requests post请求时参数复杂化解决办法
- 解决YII提交POST表单出现400错误,以及ajax post请求时出现400问题
- AngularJs中$http发送post或者get请求,SpringMVC后台接收不到参数值的解决办法
- @RequestBody之后AJAX请求总是报400/415错误的解决办法
- 【前端知识点】前后端关于post请求中,对body的不同数据格式的解决处理方案实现