我使用Spring Boot 1.4.1,其中包含spring-web-4.3.3。我有一个注释类为@ControllerAdvice
的类和使用@ExceptionHandler
注解的方法来处理服务代码抛出的异常。在处理这些异常时,我想记录作为PUT和POST操作请求一部分的@RequestBody
,以便我可以看到导致问题的请求主体,这在我的情况下对诊断至关重要。如何在@ExceptionHandler(Spring REST)中获取@RequestBody
每Spring Docs方法签名@ExceptionHandler
方法可以包括各种东西,包括HttpServletRequest
。请求正文通常可以通过getInputStream()
或getReader()
从这里获得,但是如果我的控制器方法像我所有的那样解析请求体"@RequestBody Foo fooBody"
,那么HttpServletRequest's
输入流或读取器在调用异常处理程序方法时已经关闭。本质上,Spring的请求体已经被读取,类似于here所描述的问题。使用servlet是一个常见的问题,请求主体只能被读取一次。
不幸的是@RequestBody
不是可用于异常处理程序方法的选项之一,如果那时我可以使用它。
我可以将InputStream
添加到异常处理程序方法,但最终与HttpServletRequest的InputStream相同,因此具有相同的问题。
我也试图让与((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
当前请求是获取当前的请求的另一个伎俩,但这最终是相同的HttpServletRequest了Spring进入到异常处理方法等有同样的问题。
我已阅读了几个解决方案,如this和this,它们涉及在筛选器链中插入一个自定义请求包装器,它将读取请求的内容并缓存它们,以便它们可以多次读取。我不喜欢这个解决方案,因为我不想中断整个过滤器/请求/响应链(并且可能引入性能或稳定性问题)来实现日志记录,并且如果我有任何大的请求,例如上传的文档我这样做),我不想将它缓存在内存中。此外,如果我只能找到它,Spring可能已经在某处缓存了@RequestBody
。
顺便提一下,许多解决方案建议使用ContentCachingRequestWrapper
春季班,但根据我的经验,这是行不通的。除了未被记录,查看它的源代码,它看起来像只缓存参数,而不是请求体。试图从这个类中获取请求体总是会产生一个空字符串。
所以我正在寻找任何其他选项,我可能错过了。谢谢阅读。
没有快速内置的解决方案来做你想做的事情。 Spring不会在任何地方缓存请求主体。你可以创建你自己的'HandlerMapping'和'HttpServletRequestWrapper'。 –