当前位置: 首页 > 知识库问答 >
问题:

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

蓟捷
2023-03-14

我试图解析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或请求正文?

共有1个答案

狄易安
2023-03-14

您可以添加一个筛选器,截取当前的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 framework中的ContentCachingRequestWrapper,它基本上执行相同的操作。

这种做法有其自身的缺点。首先,它有些低效,因为对于每个请求,请求体至少要被读取两次。另一个重要的缺点是,如果请求体包含10 GB值的流,您将读取10 GB数据,甚至更糟的是将其带入内存以便进一步检查。

 类似资料:
  • 问题内容: 我正在尝试解析方法的某些参数,从请求正文中提取值并进行验证,然后将其注入某些带注释的参数中。 最大的问题是我发现(get from )不能 多次 读取输入流(某些参数在请求正文中)。那么,如何才能多次检索/ 或请求正文? 问题答案: 您可以添加过滤器,拦截当前过滤器并将其包装在custom中。在您的custom中,您将读取请求主体并将其缓存,然后实现并从缓存的值中读取。由于包装请求后,

  • 问题内容: type ValidationModel struct { Name string Email string Password string } 首先,我使用govalidator验证请求正文。 在验证了请求之后,我再次将请求主体解码为用户结构,但已使用validationModel读取了请求主体一次,因此当我尝试再次将其解码为用户时,它没有提供任何值。 我在这里可以想到两种解决方案:

  • 问题内容: 我现在使用的代码: 似乎工作正常,但我不确定在将ByteBuffer返回池之前是否需要ByteBuffer。我什至不确定要使用。文档中没有太多关于它的内容。 问题答案: 读取请求正文的一种更简单的方法是将其分派到一个工作线程,该工作线程可以使用。 有两种方法:使用或文档中所示的调度模式。这是使用的示例: 在基本上没有派遣你。

  • 如何在reactor netty服务器中读取请求正文?我想让请求主体确定响应的内容,但在示例代码中找不到这样的示例。 例外 block()/blockFirst()/blockLast()正在阻塞,这在线程reactor-http-nio-2中不受支持 调用者 卷曲http://127.0.0.1:45441/test1/test-d“12312321312”-i-H“内容类型:应用程序/json

  • 问题内容: 在这篇文章中),指出了response.Body应该被关闭以避免资源泄漏。它也显示在http软件包godoc的概述示例中。 在测试代​​码中,我发送了多个请求以尝试使用 在同一功能中多次。这是不好的做法吗?在这种情况下,我要在每本书之后写一次还是只写一次? 在服务器端(即)内部的相关问题,是否也需要关闭请求主体? 问题答案: 是的,您需要关闭两个回复。推迟一个呼叫不会以某种方式影响另一

  • 问题内容: 我正在用golang编写HTTP处理程序的单元测试。在查看代码覆盖率报告时,我遇到了以下问题:从请求中读取请求正文时,可能会返回我需要处理的错误。但是,当我为我的处理程序编写单元测试时,我不知道如何以触发该错误的方式将请求发送到我的处理程序(内容的结尾过早似乎不会产生这样的错误,但是会在解体身体)。这就是我想要做的: 我该如何为不存在的情况编写测试用例? 问题答案: 您可以创建和使用伪