kotlin使用spring mvc(三)

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)
相關文章
相關標籤/搜索