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

2019-04-29  本文已影响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 进行读取

参考

上一篇下一篇

猜你喜欢

热点阅读