[TOCM]
SpringMVC@RequestBody 415 错误处理
问题描述
在 SpringMVC 中使用 @RequestBody
主要是为了从 Request 流中获取 JSON 字符串并且自动转为 JavaBean,结果就出现了 HTTP 错误码 415 Unsupported media type。
分析问题
对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝。但是我们希望在控制台日志上能够看到明显的错误描述,所以这个时候需要将日志级别调至 Debug,然后在控制台可以看到如下信息。
20160106125258 4736706 [http-apr-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported
20160106125258 4736707 [http-apr-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported
20160106125258 4736707 [http-apr-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported
从上面的日志可以得知 SpringMVC 有一个异常类的打印 HttpMediaTypeNotSupportedException
,并且可以看到后面的描述。
解决方案
根据上面的日志信息,可以想到一些解决源头,要么修改请求方,要么修改处理方。下面都介绍一下。
- 可以将 Ajax 的发送 POST 请求的
content-type
值设为application/json
; - 可以配置
MappingJacksonHttpMessageConverter
消息处理器,Spring 的不同版本其配置不一样,主要区别于 3.1 之前和之后。
3.1 之前的配置
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value> <!-- 增加这个配置 -->
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
3.1 之后的配置
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value> <!-- 增加这个配置 -->
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
关于 HttpMessageConverter 请求信息转换器简介
HttpMessageConverter 接口指定了一个可以把 Http request 信息和 Http response 信息进行格式转换的转换器。通常实现 HttpMessageConverter 接口的转换器有以下几种:
- ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;
- StringHttpMessageConverter: 负责读取字符串格式的数据和写出二进制格式的数据;
- ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;
- FormHttpMessageConverter: 负责读取 form 提交的数据(能读取的数据格式为 application/x-www-form-urlencoded,不能读取 multipart/form-data 格式数据);负责写入 application/x-www-from-urlencoded 和 multipart/form-data 格式的数据;
- MappingJacksonHttpMessageConverter: 负责读取和写入 json 格式的数据,这里使用的 Jackson 版本 1.x 的,该版本系列已经不再维护了;
- MappingJackson2HttpMessageConverter: 负责读取和写入 json 格式的数据,这里使用的 Jackson 版本 2.x 的;
- SourceHttpMessageConverter: 负责读取和写入 xml 中 javax.xml.transform.Source 定义的数据;
- Jaxb2RootElementHttpMessageConverter: 负责读取和写入 xml 标签格式的数据;
- AtomFeedHttpMessageConverter: 负责读取和写入 Atom 格式的数据;
- RssChannelHttpMessageConverter: 负责读取和写入 RSS 格式的数据;
- ...还有更多消息转换器,更多关于 HttpMessageConverter 的信息请看:http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/http/converter/HttpMessageConverter.html
HttpMessageConverter 请求信息转换器执行流程:
当用户发送请求后,@Requestbody 注解会读取请求 body 中的数据,默认的请求转换器 HttpMessageConverter 通过获取请求头 Header 中的 Content-Type 来确认请求头的数据格式,从而来为请求数据适配合适的转换器。例如 contentType:applicatin/json,那么转换器会适配 MappingJacksonHttpMessageConverter。响应时候的时候同理,@Responsebody 注解会启用 HttpMessageConverter,通过检测 Header 中 Accept 属性来适配的响应的转换器。
其他问题说明
需要注意的是:使用 spring 版本好 spring 配置文件中声明 DTD 版本要一致,否则出现问题很难排查。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于