Spring MVC重复多次读取请求的Body
我们知道,HttpServletRequest的InputStream流只能读取一次,不能重复读取。在Spring MVC中,它提供了类ContentCachingRequestWrapper,它会对原始的HttpServletRequest对象进行包装。 当我们调用request body时,ContentCachingRequestWrapper会把request body的内容进行缓存,这样我们就可以在后续的使用重复读取request body。
创建ContentCachingRequestWrapper
为了使用ContentCachingRequestWrapper,需要我们创建一个web filter,示例如下:
@Component
public class CachingRequestBodyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
chain.doFilter(wrappedRequest, servletResponse);
}
}
在Web filter的doFilter方法里,创建ContentCachingRequestWrapper对request做包装。
使用ContentCachingRequestWrapper
接下来我们就可以在Controller里调用ContentCachingRequestWrapper的方法获取request body。示例如下:
@RestController
public class GreetController {
@PostMapping("/greet")
public String greet(@RequestBody String name, HttpServletRequest request) {
ContentCachingRequestWrapper requestWrapper = (ContentCachingRequestWrapper) request;
String requestBody = new String(requestWrapper.getContentAsByteArray());
return "Greetings " + requestBody;
}
这和普通的Controller写法是一样的,只是在获取request body的内容时,调用的是ContentCachingRequestWrapper的getContentAsByteArray方法,它会返回request Body的原始字节。