如何在春季“HandlerMethodArgumentResolver”中多次读取请求正文?

2022-09-01 15:50:33

我正在尝试解析方法的某些参数,从请求正文中提取值并验证它们并将其注入某些带注释的参数中。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;
}

最大的问题是我发现(从中获取)无法多次读取输入流(某些参数在请求正文中)。那么我怎样才能多次检索/或请求正文呢?HttpServletRequestNativeWebRequestInputstreamReader


答案 1

您可以添加过滤器,拦截电流并将其包装在自定义中。在自定义 中,读取请求正文并对其进行缓存,然后实现并从缓存的值中读取。由于在包装请求后,缓存的值始终存在,因此您可以多次读取请求正文:HttpServletRequestHttpServletRequestWrapperHttpServletRequestWrappergetInputStreamgetReader

@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
    }
}

为了实现,你可以从spring框架中查看ContentCachingRequestWrapper,它基本上做同样的事情。MultipleReadHttpRequest

这种方法有其自身的缺点。首先,它有点低效,因为对于每个请求,请求正文至少被读取两次。另一个重要的缺点是,如果你的请求正文包含值得的流,你会读取这些数据,更糟糕的是,它会把它放到内存中以供进一步检查。10 GB10 GB


答案 2

推荐