当前位置: 首页 > 面试题库 >

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

祝允晨
2023-03-14
问题内容

我正在使用Spring Boot 1.4.1,其中包括spring-web-4.3.3。我有一个带有@ControllerAdvice注释的类和带有注释的方法,@ExceptionHandler用于处理服务代码引发的异常。处理这些异常时,我想记录@RequestBodyPUT和POST操作请求的一部分,因此我可以看到导致问题的请求正文,在我看来,该问题对于诊断至关重要。

在Spring Docs中,方法的方法签名@ExceptionHandler可以包括多种内容HttpServletRequest。通常可以从此处通过getInputStream()或获取请求正文getReader(),但是如果我的控制器方法像"@RequestBody Foo fooBody"我的所有方法一样解析请求正文,则在HttpServletRequest's调用我的异常处理程序方法时,输入流或阅读器已经关闭。本质上,Spring已经读取了请求正文,类似于此处描述的问题。使用servlet是一个常见问题,即请求正文只能被读取一次。

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

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

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

我看了一下像一些解决方案,这个和这个涉及插入过滤器链将读取请求的内容,并缓存它们,所以它们可以被读取一次以上的自定义请求包装。我不喜欢这种解决方案,因为我不想为了实现日志记录而中断整个过滤器/请求/响应链(并可能引入性能或稳定性问题),并且如果我有任何大请求,例如上载文档(我知道),我不想将其缓存在内存中。此外,@RequestBody如果我只能找到的话,Spring可能已经在某个地方缓存了。

顺便说一句,许多解决方案建议使用ContentCachingRequestWrapperSpring类,但是根据我的经验,这是行不通的。除了没有文档记录之外,查看其源代码看起来还只是缓存参数,而不缓存请求正文。尝试从此类获取请求正文始终会导致一个空字符串。

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


问题答案:

你可以将请求主体对象引用到请求范围的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 Boot1.4.1,其中包括Spring-Web-4.3.3。我有一个用注释的类和用注释的方法,以处理服务代码引发的异常。在处理这些异常时,我希望记录作为PUT和POST操作请求的一部分的,这样我就可以看到导致问题的请求体,在我的情况下,这对于诊断至关重要。 在每个Spring文档中,方法的方法签名可以包括各种内容,包括。请求正文通常可以从这里通过或获得,但是如果我的控制器

  • 下面的API接受来自客户端的json字符串,并将其映射到电子邮件对象中。如何将请求正文()作为原始字符串获取?(我需要原始字符串和键入版本的参数) PS:这个问题不是重复的:如何在SpringREST控制器中访问普通json主体?

  • 我有一个用@ControllerAdvice注释的类和用@ExceptionHandler注释的方法来处理服务代码引发的异常。在处理这些异常时,我希望获得@RequestBody,它是请求POST操作的一部分。 我尝试为发送的请求创建POJO类,并尝试在异常处理程序类中检索,但它返回null。 遵循本查询中给出的相同解决方案~如何在@ExceptionHandler(Spring REST)中获取

  • 我的Rest控制器 我的异常处理无效的原始 json 帖子。我尝试使用请求。 IllegalStateException:已经为此请求调用了getInputStream() 我想在这个异常上保留日志输入原始json数据。 有人能帮我吗?谢谢。 更新 作为@Sean Carrol的建议。我尝试按照建议使用HttpServletRequest estWrapper,但它仍然不起作用。 我在InputS

  • 应用程序应异步(在单独的线程中)记录以下信息,而不会影响客户端。 请求HTTP方法和URI 如果我们在过滤器中使用,那么spring将无法再次使用它进行json到对象的映射。在输入流到对象映射期间的某个地方,我们可以插入记录器吗? 更新: 我们可以在MessageConverter中编写日志代码,但这似乎不是一个好主意。

  • 问题内容: 我建立了一个HTTP服务器。我正在使用下面的代码来获取请求URL,但未获取完整URL。 我只得到和。 我想获得完整的客户端请求的URL作为或。 谢谢。 问题答案: 从net / http包的文档中: 您的代码的修改后的版本: 输出示例: