13

我想知道例如 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
4

1 回答 1

13

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

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

所以实际上这种做事的方式并不是直接可行的。

一种解决方案是制作一个Filter包装HttpServletRequest在您自己的实现中的缓冲InputStream以使其可重用/重读的次数根据需要进行多次。但同样,从正文中反序列化的规则可能由 Spring 假定,而不是您想要的。在这种情况下,您可以创建自己的AnnotationHandlerMethodArgumentResolver然后在配置中向应用程序注册。然后,您可以准确控制如何从请求正文中反序列化事物。

另一种解决方案是将两者结合MyObjectDtomessageBody一个 DTO 中,如果这对您的数据模型(以及 Spring 反序列化过程)有意义。

于 2013-09-09T02:58:17.230 回答