我正在使用 Spring Boot 1.4.1,其中包括 spring-web-4.3.3。我有一个用 — 注释的类和用 @ExceptionHandler
@ControllerAdvice
注释的方法来处理服务代码抛出的异常。在处理这些异常时,我想记录 @RequestBody
这是 PUT 和 POST 操作请求的一部分,因此我可以看到导致问题的请求正文,这在我的情况下对诊断至关重要。
根据 Spring Docs , @ExceptionHandler
方法的方法签名可以包括各种内容,包括 HttpServletRequest
。请求正文通常可以通过 getInputStream()
或 getReader()
从这里获得,但如果我的控制器方法解析请求正文,如 "@RequestBody Foo fooBody"
就像我的所有人一样, HttpServletRequest's
输入流或读取器在调用我的异常处理程序方法时已经关闭。本质上,请求正文已被 Spring 读取,类似于 此处 描述的问题。使用 servlet 的一个常见问题是请求正文只能被读取一次。
不幸的是 @RequestBody
不是异常处理程序方法可用的选项之一,如果是的话,我可以使用它。
我可以将 InputStream
添加到异常处理程序方法中,但这最终与 HttpServletRequest 的 InputStream 相同,因此存在相同的问题。
我还尝试使用 ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
获取当前请求,这是获取当前请求的另一个技巧,但这最终与 Spring 传递给异常处理程序方法的 HttpServletRequest 相同,因此存在相同的问题。
我已经阅读了一些 这样 的 解决 方案,其中涉及在过滤器链中插入一个自定义请求包装器,它将读取请求的内容并缓存它们,以便可以多次读取它们。我不喜欢这个解决方案,因为我不想仅仅为了实现日志记录而中断整个过滤器/请求/响应链(并可能引入性能或稳定性问题),并且如果我有任何大型请求,例如上传的文档(其中我愿意),我不想将其缓存在内存中。此外,如果我只能找到它,Spring 可能已经在某处缓存了 @RequestBody
。
顺便说一句,许多解决方案建议使用 ContentCachingRequestWrapper
Spring 类,但根据我的经验,这不起作用。除了没有记录之外,查看它的源代码看起来它只缓存参数,而不是请求正文。尝试从此类中获取请求正文总是会导致空字符串。
所以我正在寻找我可能错过的任何其他选择。谢谢阅读。
原文由 Uncle Long Hair 发布,翻译遵循 CC BY-SA 4.0 许可协议
您可以将请求主体对象引用到请求范围的 bean。然后在您的异常处理程序中注入该请求范围的 bean 以检索请求正文(或您希望引用的其他请求上下文 bean)。