消费了body中的流,@RequestBody映射不上了

springmvc

前几天朋友找我,说遇到一个问题,在使用springboot开发的时候,json数据传值但是后台model映射不上,问我有没有遇到这个问题。因为看到不到源码,只能靠猜测。便猜测了几个原因。可是呢 都不对。

最后告诉我是被拦截器拦截了,突然意识到应该是body中的流被消费了。
拦截器呢是这么写的。


消费了body中的流,@RequestBody映射不上了_第1张图片
image.png

后台采用下图的接收方式:


image.png

便让我给分析下原因,正好有时间,我就还原了一下现场。

顺便考虑下解决方案,代码上传到了github: https://github.com/topyuluo/question

先说第一个问题吧:拦截器中通过request.getInputStream()消费了流中的数据,而@RequestBody只能以流的方式读取,流被读过一次后,就不存在了,会导致后续无法处理。后台会抛出此异常:

java.io.IOException: Stream closed

从网上找了一张图,先看下springmvc的工作流程:

消费了body中的流,@RequestBody映射不上了_第2张图片
图片来自网络.png

上图是springmvc的整个执行流程。已经很清楚了,就不赘述了。

下面从源码的层级来看下此异常的出处,先说一下异常产生的原因,我画了一张图。

消费了body中的流,@RequestBody映射不上了_第3张图片
image.png

@RequestBody ,是从InputStream中取值
@RequestParam ,是利用request.getParameterValues()来取值

解决方案:
既然找到了原因,对症下药就可以了,由于我们消费了流,导致了流关闭,那么如果能将流拷贝一份或者向后台在传一份一模一样的是否就解决了呢。
由于拦截器的特点不能实现这个需求,所以将拦截器替换为过滤器。

主要代码如下:
request包装类


消费了body中的流,@RequestBody映射不上了_第4张图片
request.png

response包装类:


消费了body中的流,@RequestBody映射不上了_第5张图片
response.png

注册过滤器:


消费了body中的流,@RequestBody映射不上了_第6张图片
register.png

过滤器中使用:


消费了body中的流,@RequestBody映射不上了_第7张图片
filter.png

这样就可以在controller中使用@RequestBody接收了。

你可能感兴趣的:(消费了body中的流,@RequestBody映射不上了)