post方法 request.getInputStream()为空解惑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了post方法 request.getInputStream()为空解惑相关的知识,希望对你有一定的参考价值。

参考技术A 在SpringMVC web应用中,对于一个rest接口,获取请求参数我们一般使用 @requestParam 、 @requestBody 等注解 。对于表单类型的请求参数,有一下几种获取方式

前两种方式其实是一种方式,@requestParam底层就是利用request.getParameter的原理。这两种方式有一个弊端就是只能一个个获取,而且必须知道对方传过来的参数的key值,如果想要一次性获取,可以使用request.getInputStream方法获取一个inputStream对象,然后读取流里面的数据。

但在实际过程中,我们会发现通过request.getInputStream()方式获取的数据为空。

这里的表单数据已经被填充到parameterMap中,不能再通过getInputStream获取。

如何解决这个问题呢。

在javax.servlet.http包下面有一个装饰器类 HttpServletRequestWrapper ,利用这个装饰器类,我们可以重新包装一个HttpServletRequest对象。

定义一个装饰器继承 HttpServletRequestWrapper , streamBody 字节变量用来保存读取的数据,以便于多次读取。

声明一个带有HttpServletRequest入参的构造器,从该参数对象的流中解析数据,如果没有则继续从parameterMap中获取,然后以key=value&key=value形式拼接。用streamBody接收。然后我们重写getInputStream方法,以后每次调用getInputStream方法,其实是重新利用streamBody重新new一个流,所以可以多次读取。

有了装饰器后,我们就要装饰目标对象。我们都知道SpringMVC的一次请求会被一个个过滤器层层调用,也就是我们常说的责任链模式。利用 Filter 我们就可以在某个特定的位置装饰HttpServletRequest对象。

OncePerRequestFilter 这个过滤器能够保证一次请求只经过一次过滤器,所以我们直接继承该类就行了。

然后注册该过滤器,设置优先级为1。Spring Boot 会按照order值的大小,从小到大的顺序来依次过滤。

我们写一个简单的rest接口测试下

curl命令

结果

以上是关于post方法 request.getInputStream()为空解惑的主要内容,如果未能解决你的问题,请参考以下文章

此路由不支持 POST 方法。支持的方法:GET、HEAD。但我只能使用 post 方法

在 laravel 6 中以 post 方法发送表单数据给出错误,因为该路由不支持 POST 方法。支持的方法:GET、HEAD

Django中使用POST方法获取POST数据

get和post的方法的区别(HTTP协议的主要方法都有哪些?)

jQuery – AJAX get() 和 post() 方法

Django - 使用 Ajax 的 POST 方法错误“POST /......./ HTTP/1.1”405 0