【发布时间】:2020-05-29 08:39:34
【问题描述】:
我正在配置自定义错误处理,以便将每个错误请求记录到我的 API。 在我的场景中,了解请求中传递的有效负载很重要,以便我可以根据需要修复/测试/重新处理它。
我已经构建了一个简单的@RestControllerAdvise,但我很难从中获取请求正文:
@RestControllerAdvice
class ExceptionHandler {
companion object {
private val logger = getLogger()
}
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun badRequest(e: Exception, request: HttpServletRequest): Exception {
logger.error("Received a bad request with body: ${request.getBodyPlease()}", e) // Note getBodyPlease() is not a real method
return e
}
}
我尝试从请求中读取InputStream,但此时它已经关闭。
Another question 建议注入 RequestContext 并将其设置为 Controller。这在Bad Request 场景中不起作用,因为它不会执行控制器。此外,在每个控制器中设置它也没有多大意义。
提前致谢,
编辑
正如@BeUndead 建议的那样,我尝试实现一个过滤器来包装请求:
@Component
class RequestWrapperFilter : Filter {
override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) {
val reqWrapper = ContentCachingRequestWrapper(req as HttpServletRequest)
chain.doFilter(reqWrapper, res)
}
}
然后我试图让身体像request.reader.lines().collect(Collectors.joining())。
当我尝试使用过滤器时,ServletRequest 工作正常,我看到了身体。但是当我尝试使用 @ExceptionHandler 和 ContentCachingRequestWrapper 时,我得到一个空字符串,
【问题讨论】:
-
你能添加一个
Filter,它将HttpServletRequest包装成ContentCachingRequestWrapper,然后然后从请求中获取InputStream吗? -
@BeUndead 我已经尝试过实施,但仍然没有做好。您可以检查问题中的编辑吗?
-
@BeUndead 发现了。如here 所述,即使使用
ContentCachingRequestWrapper,我们仍然只能从流中读取一次。但是我们可以从contentAsByteArray属性中执行任意多次。谢谢!
标签: java spring-boot kotlin error-handling