你可以添加过滤器,拦截当前过滤器HttpServletRequest
并将其包装在custom
中HttpServletRequestWrapper
。在你的custom中HttpServletRequestWrapper
,你将读取请求主体并将其缓存,然后实现getInputStream
并getReader
从缓存的值中读取。由于包装请求后,缓存值始终存在,因此你可以多次读取请求正文:
@Component
public class CachingRequestBodyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
MultipleReadHttpRequest wrappedRequest = new MultipleReadHttpRequest(currentRequest);
chain.doFilter(wrappedRequest, servletResponse);
}
}
经过此过滤器后,每个人都将看到wrappedRequest具有多次读取功能的:
public class MultipleReadHttpRequest extends HttpServletRequestWrapper {
private ByteArrayOutputStream cachedContent;
public MultipleReadHttpRequest(HttpServletRequest request) throws IOException {
// Read the request body and populate the cachedContent
}
@Override
public ServletInputStream getInputStream() throws IOException {
// Create input stream from cachedContent
// and return it
}
@Override
public BufferedReader getReader() throws IOException {
// Create a reader from cachedContent
// and return it
}
}
对于实现MultipleReadHttpRequest
,你可以ContentCachingRequestWrapper
从基本上做同样事情的spring框架中了解一下。
这种方法有其自身的缺点。首先,它效率不高,因为对于每个请求,请求正文至少被读取两次。另一个重要的缺点是,如果你的请求正文包含10 GB
有价值的流,则你会读取该10 GB
数据,甚至更糟的是将其带入内存以进行进一步检查。