具有多个@RequestBody的Spring MVC控制器


问题内容

我想知道例如SpringMVC控制器是否可以具有方法签名,例如

@RequestMapping(value = "/target", method = RequestMethod.POST)
@ResponseBody
public void acceptObject(@RequestBody MyObjectDto dto,@RequestBody String messageBody) {
    //Authenticate messageBody
    //Process mapped DTO
}

目的是将JSON发布到此控制器,对原始消息主体进行身份验证以确保完整性,如果正确,则将JSON映射到可以移交给处理的DTO。

此刻我最终以

java.io.IOException: Stream closed

问题答案:

Spring使用一个称为的接口HandlerMethodArgumentResolver来决定将哪些参数传递给您的处理程序方法。对于带有注释的参数@RequestBody,请使用名为的类RequestResponseBodyMethodProcessor。此类基本上在一组HttpMessageConverter对象中查找可以读取content- type请求的对象并可以转换为指定类型的对象。如果找到一个,则将HttpServletRequestas
的主体传递InputStream给该HttpMessageConverter对象。

在这种情况下,您可能会发现一些JSON解串器正在工作。很可能(看到IOException您得到的)消耗流然后关闭它。

因此,实际上,这种做事方式并非直接可行。

一种解决方案是制作一个Filter,将封装HttpServletRequest在您自己的实现中,该实现对进行缓冲,InputStream以使其可重复使用/重新读取所需次数。但是同样,Spring可能会采用从身体反序列化的规则,而这并不是您真正想要的。在这种情况下,你可以创建自己的Annotation,并HandlerMethodArgumentResolver通过它来与您的配置应用程序注册。然后,您可以控制从请求主体反序列化事物的方式。

另一个解决方案是两者结合起来MyObjectDto,并messageBody成一个DTO,如果是有道理的,以数据模型(和spring反序列化过程)。