SpringMVC@RequestBody 415 错误处理

本贴最后更新于 2680 天前,其中的信息可能已经时过境迁

[TOCM]

SpringMVC@RequestBody 415 错误处理

问题描述

在 SpringMVC 中使用 @RequestBody 主要是为了从 Request 流中获取 JSON 字符串并且自动转为 JavaBean,结果就出现了 HTTP 错误码 415 Unsupported media type。
[001http-415.png]

分析问题

对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝。但是我们希望在控制台日志上能够看到明显的错误描述,所以这个时候需要将日志级别调至 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,并且可以看到后面的描述。

解决方案

根据上面的日志信息,可以想到一些解决源头,要么修改请求方,要么修改处理方。下面都介绍一下。

  1. 可以将 Ajax 的发送 POST 请求的 content-type 值设为 application/json;
  2. 可以配置 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 接口的转换器有以下几种:

  1. ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;
  2. StringHttpMessageConverter: 负责读取字符串格式的数据和写出二进制格式的数据;
  3. ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;
  4. FormHttpMessageConverter: 负责读取 form 提交的数据(能读取的数据格式为 application/x-www-form-urlencoded,不能读取 multipart/form-data 格式数据);负责写入 application/x-www-from-urlencoded 和 multipart/form-data 格式的数据;
  5. MappingJacksonHttpMessageConverter: 负责读取和写入 json 格式的数据,这里使用的 Jackson 版本 1.x 的,该版本系列已经不再维护了
  6. MappingJackson2HttpMessageConverter: 负责读取和写入 json 格式的数据,这里使用的 Jackson 版本 2.x 的
  7. SourceHttpMessageConverter: 负责读取和写入 xml 中 javax.xml.transform.Source 定义的数据;
  8. Jaxb2RootElementHttpMessageConverter: 负责读取和写入 xml 标签格式的数据;
  9. AtomFeedHttpMessageConverter: 负责读取和写入 Atom 格式的数据;
  10. RssChannelHttpMessageConverter: 负责读取和写入 RSS 格式的数据;
  11. ...还有更多消息转换器,更多关于 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 版本要一致,否则出现问题很难排查。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    941 引用 • 1458 回帖 • 150 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...