簡體   English   中英

如何在 Spring 'HandlerMethodArgumentResolver' 中多次讀取請求正文?

[英]How can I read request body multiple times in Spring 'HandlerMethodArgumentResolver'?

我正在嘗試解析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或請求主體呢?

您可以添加一個過濾器,攔截當前的HttpServletRequest並將其包裝在自定義的HttpServletRequestWrapper中。 在您的自定義HttpServletRequestWrapper中,您讀取請求主體並將其緩存,然后實現getInputStreamgetReader以從緩存的值中讀取。 由於包裝請求后,緩存值始終存在,您可以多次讀取請求主體:

@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的數據,甚至更糟的是將其放入內存中以供進一步檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM