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)
相关文章
相关标签/搜索