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 进行读取