在 Filter 中对 request 中的 body 进行参数签名校验, 会报如下错误:
getReader() has already been called for this request
原因是 request.getReader() 和 request.getInputStream() 都是只能调用一次
并且 getReader() 方法底层也是调用 getInputStream() 来实现的.
所以我们要使用 HttpServletRequestWrapper 来实现自定义的 CustomHttpServletRequestWrapper, 把 body 保存在 CustomHttpServletRequestWrapper 中, 并且重写 getInputStream() 方法
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper{
private byte[] body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
BufferedReader reader = request.getReader();
try (StringWriter writer = new StringWriter()) {
int read;
char[] buf = new char[1024 * 8];
while ((read = reader.read(buf)) != -1) {
writer.write(buf, 0, read);
}
this.body = writer.getBuffer().toString().getBytes();
}
}
public byte[] getBody() {
return body;
}
@Override
public ServletInputStream getInputStream() throws IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public boolean isReady() {
return false;
}
@Override
public boolean isFinished() {
return false;
}
};
}
}
然后, 获取 body 就调用 CustomHttpServletRequestWrapper 中的 getBody() 方法, 后面就使用
filterChain.doFilter(customHttpServletRequestWrapper, response);
就 OK 了