我正在尝试解析RequestMapping
方法的某些参数,从请求体中提取值并验证它们并将它们注入到某些带注释的参数中。
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// 1, get corresponding input parameter from NativeWebRequest
// 2, validate
// 3, type convertion and assemble value to return
return null;
}
最大的问题是,我发现HttpServletRequest
(来自NativeWebRequest
)无法读取输入流(某些参数位于请求正文中)多次 。那么如何多次检索Inputstream
/ Reader
或请求正文?
答案 0 :(得分:23)
您可以添加过滤器,拦截当前HttpServletRequest
并将其包装在自定义HttpServletRequestWrapper
中。在自定义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
,您可以从spring框架看一下ContentCachingRequestWrapper
,这基本上是相同的。
这种方法有其自身的缺点。首先,它效率有点低,因为对于每个请求,请求主体至少被读取两次。另一个重要的缺点是,如果您的请求正文包含10 GB
个值的流,您会读取10 GB
数据,更糟糕的是将其带入内存以供进一步检查。