美文网首页
request.getInputStream()输入流反复读取

request.getInputStream()输入流反复读取

作者: 南岩飞雪 | 来源:发表于2019-04-29 19:31 被阅读0次

    问题

    Spring MVC模式,到达Controller之前,还有filter和interceptor;如果filter和interceptor,做了一些通用处理,先读取了请求中的inputSteam,Controller再去读取的会报错

    • 报错

    解决

    封装一个Wrapper,保存最初inputStream读取出来的private byte[] buffer,每次取inputStream的时候,返回一个新的new BufferedServletInputStream(this.buffer);
    然后把这个Wrapper往下传递

    public class BufferedServletRequestWrapper extends HttpServletRequestWrapper {
    
        private byte[] buffer;
    
        public BufferedServletRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            InputStream is = request.getInputStream();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] tmp = new byte[1024];
            int read;
            while ((read = is.read(tmp)) > 0) {
                os.write(tmp, 0, read);
            }
            this.buffer = os.toByteArray();
        }
    
        @Override
        public ServletInputStream getInputStream() {
            return new BufferedServletInputStream(this.buffer);
        }
    }
    
    public class BufferedServletInputStream extends ServletInputStream {
        private ByteArrayInputStream inputStream;
    
        public BufferedServletInputStream(byte[] buffer) {
            this.inputStream = new ByteArrayInputStream(buffer);
        }
    
        @Override
        public int available() {
            return inputStream.available();
        }
    
        @Override
        public int read() throws IOException {
            return inputStream.read();
        }
    
        @Override
        public boolean isFinished() {
            return inputStream.available() == 0;
        }
    
        @Override
        public boolean isReady() {
            return true;
        }
    
        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");
        }
    }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest httpRequest = new BufferedServletRequestWrapper((HttpServletRequest) request);
            ......读取request中的流......
            request.getInputStream();
            ......
            chain.doFilter(httpRequest, response);
        }
    

    原因

    流的读取本身是单向的,所以只能将流的内容读取处理,放入 byte[] 中缓存起来,然后每次 getInputStream 都利用 ByteArrayOutputStream 来构造 InputStream, 达到了类似反复读取流的效果,其实是一直构造新的 ByteArrayOutputStream 进行读取

    参考

    相关文章

      网友评论

          本文标题:request.getInputStream()输入流反复读取

          本文链接:https://www.haomeiwen.com/subject/jtaygqtx.html