requestBody 多次读取
网上的做法一般是
重新封装一个 request
把初始的request的body读取后 重新写入一个 inputStream
如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Map;
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper{
private byte[] body;
private BufferedReader reader;
private ServletInputStream inputStream;
public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException{ super(request); loadBody(request); }
private void loadBody(HttpServletRequest request) throws IOException{ body = IOUtils.toByteArray(request.getInputStream()); inputStream = new RequestCachingInputStream(body); }
public byte[] getBody() { return body; }
@Override public ServletInputStream getInputStream() throws IOException { if (inputStream != null) { return inputStream; } return super.getInputStream(); }
@Override public BufferedReader getReader() throws IOException { if (reader == null) { reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding())); } return reader; }
private static class RequestCachingInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public RequestCachingInputStream(byte[] bytes) { inputStream = new ByteArrayInputStream(bytes); } @Override public int read() throws IOException { return inputStream.read(); }
@Override public boolean isFinished() { return inputStream.available() == 0; }
@Override public boolean isReady() { return true; }
@Override public void setReadListener(ReadListener readlistener) { }
}
}
|
这个写法有个问题就是
有些方法使用 parameterMap 获取请求参数的 会获取不到
应该改为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Map;
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper{
private byte[] body;
private final Map<String, String[]> parameterMap;
private BufferedReader reader;
private ServletInputStream inputStream;
public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException{ super(request); parameterMap = request.getParameterMap(); loadBody(request); }
private void loadBody(HttpServletRequest request) throws IOException{ body = IOUtils.toByteArray(request.getInputStream()); inputStream = new RequestCachingInputStream(body); }
public byte[] getBody() { return body; }
@Override public Map<String, String[]> getParameterMap() { return this.parameterMap; }
@Override public ServletInputStream getInputStream() throws IOException { if (inputStream != null) { return inputStream; } return super.getInputStream(); }
@Override public BufferedReader getReader() throws IOException { if (reader == null) { reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding())); } return reader; }
private static class RequestCachingInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public RequestCachingInputStream(byte[] bytes) { inputStream = new ByteArrayInputStream(bytes); } @Override public int read() throws IOException { return inputStream.read(); }
@Override public boolean isFinished() { return inputStream.available() == 0; }
@Override public boolean isReady() { return true; }
@Override public void setReadListener(ReadListener readlistener) { }
}
}
|
这样就从 parameterMap 里面获取参数的方法也可以在我们自定义的request里面获取都 请求参数了
原因是 request.getParameterMap(); 和 request.getInputStream(); 这两个方法是竞争的
不管调用哪一个 都会执行 readStarted = true;