使用 ContentCachingRequestWrapper 后缺少所需的请求正文
Posted
技术标签:
【中文标题】使用 ContentCachingRequestWrapper 后缺少所需的请求正文【英文标题】:Required request body is missing after using ContentCachingRequestWrapper 【发布时间】:2020-12-26 17:10:29 【问题描述】:我需要在我的GenericFilterBean
之一中读取请求有效负载。
因为我不能打电话给getreader twice 我用ContentCachingRequestWrapper
like-
HttpServletRequest httpRequest = (HttpServletRequest) request;
ContentCachingRequestWrapper cachedRequest = new ContentCachingRequestWrapper(httpRequest);
获取请求正文-
String payload = cachedRequest.getReader().lines().collect(Collectors.joining());
并链接请求-
chain.doFilter(cachedRequest, response);
但我的控制器仍然抛出-
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public org.springframework.http.ResponseEntity<?> com.siemens.plm.it.sf.api.controllers.OrderController.createCCOrder(com.siemens.plm.it.de.ms.provisioning.model.sap.SapQuoteCreationArgument,javax.servlet.http.HttpServletRequest) throws java.lang.Exception
关于如何链接请求以便我也可以读取控制器中的有效负载的 Ant 想法?
谢谢。
【问题讨论】:
使用ContentCachingRequestWrapper
,您无法多次读取正文。在本教程中有一个替代方案,希望对您有所帮助。 baeldung.com/spring-reading-httpservletrequest-multiple-times
【参考方案1】:
我遇到了同样的问题。您需要在 requestWrapper 上调用 getInputStream 以使其被缓存。这就是您的过滤器的外观:
@Component
public class CachingRequestBodyFilter extends GenericFilterBean
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) servletRequest);
//this line is necessary to cache InputStream
wrappedRequest.getInputStream();
//String requestBody = IOUtils.toString(wrappedRequest.getInputStream(), StandardCharsets.UTF_8); with this line you can map requestBody to String
chain.doFilter(wrappedRequest, servletResponse);
控制器:
@PostMapping(ENDPOINT)
void endpoint(HttpServletRequest request)
ContentCachingRequestWrapper requestWrapper = (ContentCachingRequestWrapper) request;
String requestBody = new String(requestWrapper.getContentAsByteArray());
//process requestBody
【讨论】:
【参考方案2】:我认为这样做:
String payload = cachedRequest.getReader().lines().collect(Collectors.joining());
你做错了。
试试这个:
String input = ByteSource.wrap(cachedRequest.getContentAsByteArray())
.asCharSource(StandardCharsets.UTF_8).read();
正如documentation 建议的那样:
缓存从输入流和阅读器读取的所有内容,并允许通过字节数组检索此内容
一些有用的链接: Link 1, Link 2.
【讨论】:
我有完全相同的问题,@Furquam Ahmed 的评论不起作用。以上是关于使用 ContentCachingRequestWrapper 后缺少所需的请求正文的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)