ServletInputStream不支持多次读取的一种解决方法

本文作者:suxingrui
本文链接:https://blog.csdn.net/suxingrui/article/details/103787116
版权声明:本文为原创文章,转载请注明出处。

回顾2019年碰到的问题及解决方式
问题:ServletInputStream不支持多次读取

问题发现:
使用拦截器对请求的参数进行签名校验的时候,
因为post json请求的参数放在body里,所以只能通过流的方式获取,
即使用ServletInputStream inputStream = httpServletRequest.getInputStream()获取放在body里面的json字符串来进行相应的签名校验

然后,这样操作之后,因为流里面的数据已经被读取了,就会导致后续异常:
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

调查分析:
发现了问题,自然就是分析解决问题,经过一系列的源码跟进,问题原因如标题所示:ServletInputStream不支持多次读取

同时,在调查问题的时候,看了ServletInputStream的两个子类ResettableServletInputStreamWrapper、ContentCachingInputStream的实现
以及EmptyBodyCheckingHttpInputMessage中对PushbackInputStream的处理
参照着,自然而然想到了以下的解决方法

解决方法:
大概原理就是使用PushbackInputStream对ServletInputStream进行包装

1、实现ServletInputStream的子类:PushbackServletInputStream
ServletInputStream不支持多次读取的一种解决方法_第1张图片
2、实现HttpServletRequestWrapper的子类,使用PushbackServletInputStream对ServletInputStream进行包装:PushbackInputStreamHttpServletRequestWrapper
ServletInputStream不支持多次读取的一种解决方法_第2张图片
3、实现web filter过滤器:WebPostJsonFilter
ServletInputStream不支持多次读取的一种解决方法_第3张图片
4、签名或者其他处理时的读取使用:
ServletInputStream不支持多次读取的一种解决方法_第4张图片
5、最后加上@Bean,大功告成!
在这里插入图片描述

你可能感兴趣的:(Java)