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

如何在@ExceptionHandler中获得@RequestBody(Spring REST)

莘睿
2023-03-14

我使用的是Spring Boot1.4.1,其中包括Spring-Web-4.3.3。我有一个用@ControllerAdvise注释的类和用@ExceptionHandler注释的方法,以处理服务代码引发的异常。在处理这些异常时,我希望记录作为PUT和POST操作请求的一部分的@requestbody,这样我就可以看到导致问题的请求体,在我的情况下,这对于诊断至关重要。

在每个Spring文档中,@ExceptionHandler方法的方法签名可以包括各种内容,包括HttpServletRequest。请求正文通常可以从这里通过getInputStream()getReader()获得,但是如果我的控制器方法像我的所有方法一样像“@requestbody Foo foobody”那样解析请求正文,那么在调用异常处理程序方法时,HttpServletRequest的输入流或读取器已经关闭。基本上,请求体已经被Spring读取,类似于这里描述的问题。使用servlet时,请求主体只能读取一次,这是一个常见的问题。

不幸的是@requestbody不是异常处理程序方法的可用选项之一,如果是的话,我可以使用它。

我可以将InputStream添加到异常处理程序方法中,但这最终与HttpServletRequest的InputStream相同,因此存在相同的问题。

我还尝试使用((ServletRequestAttributes)RequestContexTHolder.currentRequestAttributes()).getRequest()获取当前请求,这是获取当前请求的另一个技巧,但这最终与Spring传递给异常处理程序方法的HttpServletRequest相同,因此存在同样的问题。

我读过一些类似的解决方案,其中包括在筛选器链中插入一个自定义请求包装器,该包装器将读取请求的内容并缓存它们,以便可以多次读取这些内容。我不喜欢这个解决方案,因为我不想仅仅为了实现日志记录而中断整个筛选器/请求/响应链(并可能引入性能或稳定性问题),而且如果我有任何大的请求,比如上传的文档(我这样做了),我不想在内存中缓存它。此外,Spring可能已经将@requestbody缓存在某个地方了,只要我能找到它。

顺便提一下,许多解决方案建议使用ContentCachingRequestWrapperSpring类,但根据我的经验,这并不起作用。除了没有文档之外,查看它的源代码,它看起来只缓存参数,而不缓存请求主体。试图从该类获取请求正文总是导致空字符串。

所以我在寻找我可能错过的任何其他选择。谢谢你的阅读。

共有1个答案

卢伟志
2023-03-14

您可以将请求主体对象引用到请求范围的bean。然后将请求范围的bean注入异常处理程序中,以检索请求主体(或希望引用的其他请求上下文bean)。

// @Component
// @Scope("request")
@ManagedBean
@RequestScope
public class RequestContext {
    // fields, getters, and setters for request-scoped beans
}

@RestController
@RequestMapping("/api/v1/persons")
public class PersonController {

    @Inject
    private RequestContext requestContext;

    @Inject
    private PersonService personService;

    @PostMapping
    public Person savePerson(@RequestBody Person person) throws PersonServiceException {
         requestContext.setRequestBody(person);
         return personService.save(person);
    }

}

@ControllerAdvice
public class ExceptionMapper {

    @Inject
    private RequestContext requestContext;

    @ExceptionHandler(PersonServiceException.class)
    protected ResponseEntity<?> onPersonServiceException(PersonServiceException exception) {
         Object requestBody = requestContext.getRequestBody();
         // ...
         return responseEntity;
    }
}
 类似资料:
  • 问题内容: 我正在使用Spring Boot 1.4.1,其中包括。我有一个带有注释的类和带有注释的方法,用于处理服务代码引发的异常。处理这些异常时,我想记录和POST操作请求的一部分,因此我可以看到导致问题的请求正文,在我看来,该问题对于诊断至关重要。 在Spring Docs中,方法的方法签名可以包括多种内容。通常可以从此处通过或获取请求正文,但是如果我的控制器方法像我的所有方法一样解析请求正

  • 我是新来spring boot的,当我从Postman那里获得RestController中的JSON时,我遇到了一个小问题。 当我从Postmat发送带有属性的请求时,RequestBody中总是为null。 这是我的Rest控制器 我的请求是这样的: 我用邮递员把这些属性 我试图将第一个字符设置为小写,但它不起作用。 这是提出的例外情况: 提前谢谢大家。

  • 我想使用@Valid注释和@RequestBody注释,并在我自己的方法中处理错误,这些方法用@ExceptionHandler注释注释。我希望总是返回ReponseEntity的实例。但是当我为MethodArgumentNotValidException创建ExceptionHandler时,我无法启动我的应用程序。我的控制器如下所示: 对于另一种类型的异常,一切都能正常工作,但我不能为Met

  • 问题内容: 我正在开发一个具有基于Flex的前端和Spring / Hibernate后端的应用程序。 要使Facebook集成以目前的方式运行,我需要阅读后端前端javascript中设置的cookie,并在登录期间进行一些验证,以查看用户是否尝试欺骗其Facebook。登录。 这将非常容易,但是我不知道如何获取HttpServletRequest。我正在使用一个非常基本的Spring配置(这是

  • 实际上,我有一个,它是(在和),现在我需要创建另一个(在该的下方),一开始必须不可见。 当我的活动运行时,我想对隐藏的布局进行动画处理。 隐藏的必须自下而上。我不知道如何实现这个动画??我不知道如何创建一个最初不可见的布局,经过一段时间的延迟后,它必须从屏幕下方显示并从侧面显示??? 这是我的xml文件代码