通常在springboot应用中,对接口的安全性有要求时都会对请求参数做一些签名验证,这些验证逻辑一般都是统一放到过滤器或拦截器里,这样就不用每个接口都去重复编写验签的逻辑。对于接口有可能接收不同类型的数据,对于表单数据来说,只要调用request的getParameterMap就能全部取出来。对于json数据来说,需要通过request的输入流去读取。
但问题在于request的输入流只能读取一次不能重复读取,所以我们在过滤器或拦截器里读取了request的输入流之后,请求走到controller层时就会报错。而本文的目的就是介绍如何解决在这种场景下遇到HttpServletRequest的输入流只能读取一次的问题。
HttpServletRequest的输入流只能读取一次的原因HttpServletRequest 对象中调用getInputStream()方法获取输入流时得到的是一个InputStream对象,而实际类型是ServletInputStream,它继承于InputStream。InputStream的read()方法内部有一个postion,标志当前流被读取到的位置,每读取一次,该标志就会移动一次,如果读到最后,read()会返回-1,表示已经读取完了。如果想要重新读取则需要调用reset()方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。调用reset()方法的前提是已经重写了reset()方法,当然能否reset也是有条件的,它取决于markSupported()方法是否返回true。但是InputStream默认不实现reset(),并且markSupported()默认也是返回false。
查看源码截图如下:



