java.lang.IllegalStateException:在当前请求已调用 getReader() 后无法调用 getInputStream()

Вяч*_*шов 5 java interceptor

我写了拦截器:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("[pre-handle] method: {}\tURL: {}", request.getMethod(), request.getRequestURL());
    if (HttpMethod.POST.name().equals(request.getMethod())) {
        log.info(request.getReader().lines().collect(Collectors.joining()));
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试调用控制器时,会抛出异常:

java.lang.IllegalStateException:在当前请求已调用 getReader() 后无法调用 getInputStream()

据我了解, getReader() 调用关闭 InputStream 并且没有任何内容到达控制器。如何修复它?

小智 7

要多次读取请求,您需要在第一次读取请求之前缓存您的请求。更多信息可以在这里阅读。

Spring MVC 提供了 ContentCachingRequestWrapper 类。它是原始 HttpServletRequest 对象的包装器。

要使用它,我们必须首先创建一个包装原始 HttpServletRequest 的 Web 过滤器:

@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);
    }
Run Code Online (Sandbox Code Playgroud)

之后,您可以在拦截器中使用 ContentCachingRequestWrapper 的 getContentAsByteArray 方法获取 byte[] 内容。