我在HttpPutFormContentFilter中添加了web.xml。
下面是一个既谴责GET、POST、DELETE和PUT方法的动作。
@RequestMapping(value = "/**")
public ResponseEntity<byte[]> proxy(HttpServletRequest request,@RequestParam MultiValueMap<String, String> params, @RequestBody byte[] body, @RequestHeader MultiValueMap<String, String> headers) {当我使用POST并添加application/x-www-form-urlencoded头时,我可以得到请求体和请求param。
当我使用PUT并添加application/x-www-form-urlencoded头时,我可以得到请求param,但是我不能得到请求正文!
HttpPutFormContentFilter中有错误吗?
发布于 2014-01-29 16:21:41
根据Servlet规范 (参见第1.1章和第3.1.1章),当您收到POST请求且内容类型为application/x-www-form-urlencoded时,需要通过HttpServletRequest#getParameterXXX()方法提供表单数据。对于PUT请求,情况并非如此。
在所有情况下,HttpServletRequest的主体都可以作为InputStream到Servlet和Filter实例。
当春天看到
@RequestParam MultiValueMap<String, String> params它使用一个RequestParamMapMethodArgumentResolver来解析这个参数。这直接从HttpServletRequest参数映射中读取。当春天看到
@RequestBody byte[] body它使用一个RequestResponseBodyMethodProcessor,它从HttpServletRequest InputStream中读取,使用ByteArrayHttpMessageConverter来填充byte[]。
一旦读取了HttpServletRequest InputStream,就不能重新读取(在默认配置中)。
对于PUT,因为Servlet容器没有为PUT请求在HttpServletRequest中存储表单参数,所以Spring决定引入HttpPutFormContentFilter。这个Filter读取HttpServletRequest主体,在它交给您的HttpServletRequestWrapper中填充自己的参数映射。
完成此操作后,RequestParamMapMethodArgumentResolver可以使用请求参数,但是当RequestResponseBodyMethodProcessor试图填充byte[]时,InputStream中没有剩馀的字节,因此它将其保留为空。
解决方法之一是创建您自己的Filter (必须在HttpPutFormContentFilter之前执行,因此这是一种糟糕的实践),它将HttpServletRequest封装在一个HttpServletRequestWrapper中,该HttpServletRequestWrapper在ByteArrayInputStream中缓冲InputStream,这样您就可以在必要时多次重新读取它。
https://stackoverflow.com/questions/21427658
复制相似问题