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)