Java构建可重复读取的Request和Response

为什么要可重复读取的req和resp

Request和Response本质上都是输入输出流,网络IO流。Request通过InputStream获取输入数据,Response通过OutputStream获取输出数据。因为流中的数据不是一直存储的,读取了就消失了,意思是只能读取一次。所以在像Servlet中拦截器这一部分,拦截Req和Resp的数据并读取,进行相应的操作,因此要对Req和Resp的数据进行保存一份,否者接下来就无法再次获取。

构建可重复读Request,应用在请求拦截器

public class RepeatedRequestWrapper extends HttpServletRequestWrapper {
// req数据
private final byte[] body;

public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
super(request);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// TODO 获取req的二进制数据,自己实现这部分(就是输入流转字符串)
body = xxxUtil.reqToString(request.getInputStream()).getBytes("UTF-8");
}

@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();
}

@Override
public int available() throws IOException {
return body.length;
}

@Override
public boolean isFinished() {
return false;
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {

}
};
}
}

构建可重复读Response,应用在响应拦截器

public class RepeatedResponseWrapper extends HttpServletResponseWrapper {

private ByteArrayOutputStream byteArrayOutputStream;

private ServletOutputStream servletOutputStream;

public RepeatedResponseWrapper(HttpServletResponse response) {
super(response);
byteArrayOutputStream = new ByteArrayOutputStream();
servletOutputStream = new ServletOutputStream() {
@Override
public boolean isReady() {
return false;
}

@Override
public void setWriteListener(WriteListener writeListener) {

}

@Override
public void write(int b) throws IOException {
response.getOutputStream().write(b);
// 同时写入字节数组
byteArrayOutputStream.write(b);
}
};
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
return servletOutputStream;
}

public byte[] toByteArray() {
return byteArrayOutputStream.toByteArray();
}
}