HTTP请求的输入流只能被读取一次,再想获取就获取不到了,那有什么方法可以缓存呢,我们可以自定义一个HttpServletRequest,或者是想在请求参数中统一添加或删除参数也可以使用此类进行改造,然后通过过滤器继续向下流转。废话不多说上代码。
java
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
private final Map<String, String[]> parameterMap;
private final byte[] cachedBody;
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
this.parameterMap = request.getParameterMap();
this.cachedBody = IoUtil.readBytes(request.getInputStream(), false);
}
@Override
public String getParameter(String name) {
String[] values = this.parameterMap.get(name);
return (values != null && values.length > 0) ? values[0] : null;
}
@Override
public Map<String, String[]> getParameterMap() {
return Collections.unmodifiableMap(this.parameterMap);
}
@Override
public String[] getParameterValues(String name) {
return this.parameterMap.get(name);
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new CachedBodyServletInputStream(this.cachedBody);
}
@Override
public BufferedReader getReader() throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(this.cachedBody);
return new BufferedReader(new InputStreamReader(bais));
}
public byte[] getCachedBody() {
return this.cachedBody;
}
private static class CachedBodyServletInputStream extends ServletInputStream {
private final ByteArrayInputStream buffer;
public CachedBodyServletInputStream(byte[] contents) {
this.buffer = new ByteArrayInputStream(contents);
}
@Override
public int read() throws IOException {
return buffer.read();
}
@Override
public boolean isFinished() {
return buffer.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener listener) {
throw new UnsupportedOperationException();
}
}
}
这里也要提到一个小知识点,当浏览器或其他客户端向服务器发送HTTP请求时,请求可以包含请求头和请求体。对于GET请求,通常没有请求体,而对于POST请求,请求体中可能包含了表单数据、JSON对象或其他类型的数据。request.getInputStream()
方法允许开发者读取这些数据。