Filter中读取输入流spring
在不少场景中,咱们须要读取接口调用方的原始报文,以方便出现问题的时候进行对质、修复,可是在spring mvc中的输入流只容许读取一次,在Filter中读取以后action中就没法就行绑定了,以下面的代码数组
if(request != null){ //读取原始报文 val originText = request.inputStream.bufferedReader().readText() println(originText) chain?.doFilter(request,response) }
这样在模型绑定的时候直接抛出缓存
Required request body is missing
按照常理上思惟,输入流读取到最后,我重置不就好了吗,事实上尝试以后发现不可行,spring mvc根本没有实现,那咱们只能本身造轮子了mvc
class ResettableStreamHttpServletRequest(val request: HttpServletRequest) : HttpServletRequestWrapper(request) { //把输入流缓存到字节数组 private val rawData: ByteArray = IOUtils.toByteArray(this.request.inputStream) //可重置的输入流对象 private val servletStream: ResettableServletInputStream init { //初始化的时候就把缓存的字节数组读到流中 servletStream = ResettableServletInputStream(ByteArrayInputStream(rawData)) } internal fun resetInputStream() { //重置的时候,从新构造一个输入流对象 servletStream.stream = ByteArrayInputStream(rawData) } override fun getInputStream(): ServletInputStream { return servletStream } override fun getReader(): BufferedReader { val encoding = characterEncoding return if (encoding != null) { BufferedReader(InputStreamReader(servletStream, encoding)) } else { BufferedReader(InputStreamReader(servletStream)) } } } //必须定义一个ServletInputStream,它没有提供公开的构造方法 class ResettableServletInputStream(var stream: InputStream) : ServletInputStream() { override fun isReady(): Boolean { return true } override fun isFinished(): Boolean { return false } override fun setReadListener(listener: ReadListener?) { } override fun read(): Int { return stream.read() } }
在Filter中使用ResettableStreamHttpServletRequestapp
val resettableStreamHttpServletRequest = ResettableStreamHttpServletRequest(request = request as HttpServletRequest) //读取原始报文 val orginText = resettableStreamHttpServletRequest.inputStream.bufferedReader().readText() println(orginText) resettableStreamHttpServletRequest.resetInputStream() chain?.doFilter(resettableStreamHttpServletRequest,response)