2

我有一个类似于此的 Spring 3.1 Controller 方法

@RequestMapping(method = RequestMethod.POST)
public void (@RequestBody SomeObject obj) {
    // Do something
}

spring 配置文件已正确设置以接受 JSON。如果我发送内容类型设置为“application/json”的请求并以 JSON 格式发送正确的正文,那么一切都会按预期进行。

如果我没有将 Content Type 指定为“application/json”,则返回 HTTP 415,这也是基于配置的预期。不管内容类型如何,是否有告诉 Spring 始终将 RequestBody 视为 JSON?

4

1 回答 1

2

为了处理带@RequestBody注释的参数并注入参数,Spring 使用RequestResponseBodyMethodProcessor. 这样做的第一件事HandlerMethodArgumentResolver是检查Content-Type标题。如果缺少它,则默认为application/octet-stream. 然后它获取已注册HttpMessageConverter实例的列表。默认情况下,这些是

StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setWriteAcceptCharset(false);

messageConverters.add(new ByteArrayHttpMessageConverter()); // if your argument is a byte[]
messageConverters.add(stringConverter); // if your argument is a String
messageConverters.add(new ResourceHttpMessageConverter()); // if your argument is a Resource
messageConverters.add(new SourceHttpMessageConverter<Source>()); // if your argument is one of the javax.xml Source classes
messageConverters.add(new AllEncompassingFormHttpMessageConverter());  // for application/x-www-form-urlencoded content-type
if (romePresent) {
    messageConverters.add(new AtomFeedHttpMessageConverter()); // for application/atom+xml content-type
    messageConverters.add(new RssChannelHttpMessageConverter()); // for application/rss+xml content-type
}
if (jaxb2Present) {
    messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); // if your argument class is annotated with @XmlRootElement or @XmlType
}
if (jackson2Present) {
    messageConverters.add(new MappingJackson2HttpMessageConverter()); // for content-type application/json and application/*+json (wildcard json)
}
else if (jacksonPresent) {
    messageConverters.add(new MappingJacksonHttpMessageConverter()); // in case, but rarely, same as above
}

然后RequestResponseBodyMethodProcessor按顺序遍历此列表,并调用canRead()每个HttpMessageConverter. 如果它返回true,则RequestResponseBodyMethodProcessor使用它HttpMessageConverter来创建参数。如果它永远找不到,它会抛出HttpMediaTypeNotSupportedException一个DispatcherServlet415 响应。

使用上述默认值,这是不可能的。您必须创建并注册自己的HttpMessageConverter可以做到这一点。请注意,它将适用于所有带有@RequestBody注释参数的处理程序方法。


作为建议,Content-Type标头专门用于此场景,您应该使用它。

于 2013-10-10T16:18:00.727 回答