您的位置:首页 > 理论基础 > 计算机网络

HttpServletRequest.getInputStream() 只能读取一次

2016-08-15 10:30 253 查看
问题:在使用HTTP协议实现应用间接口通信时,服务端读取客户端请求过来的数据,会用到request.getInputStream(),第一次读取的时候可以读取到数据,但是接下来的读取操作都读取不到数据

原因
1. 一个InputStream对象在被读取完成后,将无法被再次读取,始终返回-1;
2. InputStream并没有实现reset方法(可以重置首次读取的位置),无法实现重置操作;

解决方法(缓存读取到的数据)
1.使用request、session等来缓存读取到的数据,这种方式很容易实现,只要setAttribute和getAttribute就行;
2.使用HttpServletRequestWrapper来包装HttpServletRequest,在MAPIHttpServletRequestWrapper中初始化读取request的InputStream数据,以byte[]形式缓存在其中,然后在Filter中将request转换为包装过的request;代码如下:

public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {

private final byte[] body; // 报文

public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = StreamUtil.readBytes(request.getInputStream());
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}

@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {

@Override
public int read() throws IOException {
return bais.read();
}
};
}

}


/**
* @author Perlin.Yao
* @date 2014年8月22日
* @version 1.0
*/
public class HttpServletRequestReplacedFilter implements Filter {

@Override
public void destroy() {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new MAPIHttpServletRequestWrapper((HttpServletRequest) request);
}
if(requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}

@Override
public void init(FilterConfig arg0) throws ServletException {

}

}


-----------------------------------------------------------

来源于:http://ayaoxinchao.iteye.com/blog/2110902
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: