1.方法一:使用SpringMVC提供的ContentCachingRequestWrapper包装请求
自定义一个Filter
public class CachingRequestBodyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest currentRequest = (HttpServletRequest) request;
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
chain.doFilter(wrappedRequest, response);
}
}
把Filter注册到Servlet容器中
@Configuration
public class CachingRequestBodyFilterConfig {
@Bean
public FilterRegistrationBean<CachingRequestBodyFilter> filterRegistration() {
FilterRegistrationBean<CachingRequestBodyFilter> registration = new FilterRegistrationBean<>(new CachingRequestBodyFilter());
registration.setOrder(2);
return registration;
}
}
读取请求体中的内容:
ContentCachingRequestWrapper nativeRequest = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
byte[] contentAsByteArray = nativeRequest.getContentAsByteArray();
String s = new String(contentAsByteArray);
System.out.println(s);
2.方法二
思路很简单:第一步,读取HttpServletRequest的字节流的数据,保存到一个字节数组bytes;第二步,重写getInputStream()方法和getReader()方法,让这两个方法都从字节数组bytes中读取数据,返回给调用者;第三步,写个过滤器,让HTTP请求一进入系统,就执行第一步和第二步,然后后面都用重写的HttpServletRequest对象。这样,就可以重复读取HttpServletRequest携带的HTTP请求体数据了。
public class RepeatableHttpServletRequest extends HttpServletRequestWrapper {
private final byte[] bytes;
public RepeatableHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
//读取字节流数据到字节数组
bytes = IOUtils.toByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
//重写getInputStream()
return new ServletInputStream() {
private int lastIndexRetrieved = -1;
private ReadListener readListener = null;
@Override
public boolean isFinished() {
return (lastIndexRetrieved == bytes.length-1);
}
@Override
public boolean isReady() {
// This implementation will never block
// We also never need to call the readListener from this method, as this method will never return false
return isFinished();
}
@Override
public void setReadListener(ReadListener readListener) {
this.readListener = readListener;
if (!isFinished()) {
try {
readListener.onDataAvailable();
} catch (IOException e) {
readListener.onError(e);
}
} else {
try {
readListener.onAllDataRead();
} catch (IOException e) {
readListener.onError(e);
}
}
}
@Override
public int read() throws IOException {
int i;
if (!isFinished()) {
i = bytes[lastIndexRetrieved+1];
lastIndexRetrieved++;
if (isFinished() && (readListener != null)) {
try {
readListener.onAllDataRead();
} catch (IOException ex) {
readListener.onError(ex);
throw ex;
}
}
return i;
} else {
return -1;
}
}
};
}
//重写getReader()方法
@Override
public BufferedReader getReader() throws IOException {
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
BufferedReader temp = new BufferedReader(new InputStreamReader(is));
return temp;
}
}
封装过滤器:
public class CachingRequestBodyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest currentRequest = (HttpServletRequest) request;
RepeatableHttpServletRequest wrappedRequest = new RepeatableHttpServletRequest(currentRequest);
chain.doFilter(wrappedRequest, response);
}
}
注册过滤器和方法一中相同
读取请求体中的内容:
ServletInputStream inputStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while((len = inputStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String s = outSteam.toString();
System.out.println(s);