因为项目里面需要对http请求进行多次读取,而HttpServletRequest不支持mark和reset,所以就需要把流存储起来,在每次getInputStream()的时候就用我们自己存储的数据。最开始有两种解决方案:
- 将inputstream转换成byte数组封装在一个类里面,然后将这个类用ThreadLocal进行存储。
- 用装饰者模式,而HttpServletRequestWrapper就是装饰模式的典型例子,我们这里只需要新建一个对象继承HttpServletRequestWrapper将对应的方法进行重写即可。
<pre name="code" class="java">import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)
throws IOException {
super(request);
int len = request.getContentLength();
if(len < 0) len = 0;
body = new byte[len];
try {
request.getInputStream().read(body);
} catch (IOException e) {
e.printStackTrace();
}
}
@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();
}
};
}
}