如何在Spring'HandlerMethodArgumentResolver'中多次读取请求体? [英] How can I read request body multiple times in Spring 'HandlerMethodArgumentResolver'?

查看:130
本文介绍了如何在Spring'HandlerMethodArgumentResolver'中多次读取请求体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解析 RequestMapping 方法的某些参数,从请求体中提取值并验证它们并将它们注入到某些带注释的参数中。

I'm trying to resolve some certain parameters of RequestMapping methods, to extract values from request body and validates them and inject them into certain annotated parameters.

@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 或请求正文?

The biggest problem is that I find out that HttpServletRequest(get from NativeWebRequest) cannot read input stream(some parameters are in the request body) more than one time. So how can I retrieve Inputstream/Reader or the request body more than one time?

推荐答案

您可以添加过滤器,拦截当前的 HttpServletRequest 并将其包装在自定义<$ c中$ C>了HttpServletRequestWrapper 。在您的自定义 HttpServletRequestWrapper 中,您读取请求正文并对其进行缓存,然后实现 getInputStream getReader 从缓存值中读取。由于在包装请求后,缓存的值始终存在,您可以多次读取请求正文:

You can add a filter, intercept the current HttpServletRequest and wrap it in a custom HttpServletRequestWrapper. In your custom HttpServletRequestWrapper, you read the request body and cache it and then implement getInputStream and getReader to read from the cached value. Since after wrapping the request, the cached value is always present, you can read the request body multiple times:

@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 ,具有多次读取的能力:

After this filter, everybody will see the wrappedRequest which has the capability of being read multiple times:

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 基本上做同样的事情。

For implementing MultipleReadHttpRequest, you can take a look at ContentCachingRequestWrapper from spring framework which is basically does the same thing.

这种方法有它自己的缺点。首先,它效率有点低,因为对于每个请求,请求主体至少被读取两次。另一个重要的缺点是,如果您的请求正文包含 10 GB 值的流,您会读到 10 GB 数据甚至更糟糕的是把它带入记忆中以便进一

This approach has its own disadvantages. First of all, it's somewhat inefficient, since for every request, request body is being read at least two times. The other important drawback is if your request body contains 10 GB worth of stream, you read that 10 GB data and even worse bring that into memory for further examination.

这篇关于如何在Spring'HandlerMethodArgumentResolver'中多次读取请求体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆