HttpMessageConverter<T>是Spring3的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。

DispatcherServlet默认已安装了RequestMappingHandlerAdapter作为HandlerAdapter的组件实现类,HttpMessageConverter即由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。

HttpMessageConverter<T>接口定义以下几个方法:

  1. /**
  2. * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
  3. */
  4. public interface HttpMessageConverter<T> {
  5.  
  6. /**
  7. * Indicates whether the given class can be read by this converter.
  8. */
  9. boolean canRead(Class<?> clazz, MediaType mediaType);
  10.  
  11. /**
  12. * Indicates whether the given class can be written by this converter.
  13. */
  14. boolean canWrite(Class<?> clazz, MediaType mediaType);
  15.  
  16. /**
  17. * Return the list of {@link MediaType} objects supported by this converter.
  18. */
  19. List<MediaType> getSupportedMediaTypes();
  20.  
  21. /**
  22. * Read an object of the given type form the given input message, and returns it.
  23. */
  24. T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
  25. throws IOException, HttpMessageNotReadableException;
  26.  
  27. /**
  28. * Write an given object to the given output message.
  29. */
  30. void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
  31. throws IOException, HttpMessageNotWritableException;
  32.  
  33. }

Spring为HttpMessageConverter提供了众多的实现类

RequestMappingHandlerAdapter默认已经注册了以下HttpMessageConverter:

  1. private List<HttpMessageConverter<?>> messageConverters;
  2. public RequestMappingHandlerAdapter() {
  3. StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
  4. stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316
  5. this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
  6. this.messageConverters.add(new ByteArrayHttpMessageConverter());
  7. this.messageConverters.add(stringHttpMessageConverter);
  8. this.messageConverters.add(new SourceHttpMessageConverter<Source>());
  9. this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
  10. }

如果需要装配其他类型的HttpMessageConverter,可以在Spring的web容器(Spring子容器)上下文中自行定义一个RequestMappingHandlerAdapter,注册若干HttpMessageConverter。dispatcher-servlet.xml

  1. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
  2. <property name="messageConverters" ref="messageConverters"/>
  3. </bean>
  4. <!--HttpMessageConverter列表-->
  5. <util:list id="messageConverters">
  6. <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
  7. <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
  8. <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
  9. <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
  10. <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
  11. </util:list>

如果在Spring web容器中显式定义了一个RequestMappingHandlerAdapter,则Spring MVC将使用它覆盖默认的AnnotationMethodHandlerAdapter(默认配置就没有了)。

如何使用 HttpMessageConverter<T> 将请求信息转换并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring MVC提供了两种途径:

1. 使用@RequestBody/@ResponseBody 对处理方法进行标注

2. 使用HttpEntity<T>/ResponseEntity<T> 作为处理方法的入参或返回值

示例1:

  1. @RequestMapping(value = "/handle41")
  2. public String handle41(@RequestBody String requestBody){
  3. //将请求-报文体-转换为字符串绑定到requestBody入参中
  4. }
  5. @ResponseBody
  6. @RequestMapping("/handle42")
  7. public byte[] handle42(){
  8. //
  9. }

handle41()处Spring MVC将根据requestBody的类型(String)查找匹配的HttpMessageConverter由于StringHttpMessageConverter的泛型类型对应String,所以StringHttpMessageConverter将会被Spring MVC选中,用它将请求体(POST)信息进行转换并且将结果绑定到requestBody入参上!

handle42()处,由于方法的返回值类型为byte[],所以Spring MVC根据类型匹配的查找规则将使用ByteArrayHttpMessageConverter对返回值进行处理。

和@RequestBody/@ResponseBody类似,HttpEntity<?>不但可以访问请求和响应报文头的数据,还可以访问请求和响应报文体的数据(也就是HttpEntity中不但有头数据还有体数据),Spring MVC根据HttpEntity的泛型类型查找对应的HttpMessageConverter

在接收到一个http请求的时候,处理方法如何知道请求消息的格式,在处理完成之后又根据什么确定响应消息的格式?答案很简单,根据请求消息头的"Content-Type"及Accept属性确定。

Content-Type表示本次请求的报文内容格式。

Accept表示接受的MIME类型。

例如:
  1. @ResponseBody
  2. @RequestMapping( "/getEmployeesForJson")
  3. public Collection<Employee> getEmployees() {
  4. return employeeDao .getAll();
  5. }
 请求时的目标类型:
方法的实际返回值为:Employee 的集合
SpringMVC 发现需要返回的是JSON类型,但实际返回的是Employee的集合。此时@ResponseBody查找有没有把结果转为JSON的HttpMessageConverter,如果有,则调用其对应的方法,把结果转为JSON类型。
结论:
1.只有当处理器方法使用到@RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,SpringMVC才使用注册的HttpMessageConverter 对请求响应消息进行处理。
2.当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter, 然后根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错
3.@RequestBody 和 @ResponseBody 不需要成对出现。如果方法入参使用到了@RequestBody,SpringMVC将会选择匹配的HttpMessageConverter 将请求信息转换并绑定到该入参中。如果处理方法标注了@ResponseBody,SpringMVC选择匹配的HttpMessageConverter 将方法返回值转换并输出响应消息。

HttpMessageConverter的更多相关文章

  1. no suitable HttpMessageConverter found for request type [java.lang.Integer]

    今天在使用Spring Template的时候遇到了这个异常: no suitable HttpMessageConverter found for request type [java.lang.I ...

  2. SpringMVC 中HttpMessageConverter简介和Http请求415 Unsupported Media Type的问题

    一.概述: 本文介绍且记录如何解决在SpringMVC 中遇到415 Unsupported Media Type 的问题,并且顺便介绍Spring MVC的HTTP请求信息转换器HttpMessag ...

  3. HttpMessageConverter用法

    HttpMessageConverter接口定义 * Strategy interface that specifies a converter that can convert from and t ...

  4. 使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务

    原文地址:http://www.ibm.com/developerworks/cn/web/wa-restful/ 简介: Spring,构建 Java™ 平台和 Enterprise Edition ...

  5. 将SpringMVC中的HttpMessageConverter替换为Gson

    读者们看到这个标题也许会感到奇怪,SpringMVC中默认的HttpMessageConverter不是Jackson吗,但是我在使用的过程中发现Jackson并不好用,如果有一些复杂的嵌套类型,当然 ...

  6. springboot学习(三)——http序列化/反序列化之HttpMessageConverter

    以下内容,如有问题,烦请指出,谢谢! 上一篇说掉了点内容,这里补上,那就是springmvc的http的序列化/反序列化,这里简单说下如何在springboot中使用这个功能. 使用过原生netty ...

  7. springboot学习(三)————使用HttpMessageConverter进行http序列化和反序列化

    以下内容,如有问题,烦请指出,谢谢! 对象的序列化/反序列化大家应该都比较熟悉:序列化就是将object转化为可以传输的二进制,反序列化就是将二进制转化为程序内部的对象.序列化/反序列化主要体现在程序 ...

  8. 【Spring】HttpMessageConverter的作用及替换

    相信使用过Spring的开发人员都用过@RequestBody.@ResponseBody注解,可以直接将输入解析成Json.将输出解析成Json,但HTTP 请求和响应是基于文本的,意味着浏览器和服 ...

  9. RestTemplate 微信接口 text/plain HttpMessageConverter

    一.背景介绍 使用 Spring Boot 写项目,需要用到微信接口获取用户信息. 在 Jessey 和 Spring RestTemplate 两个 Rest 客户端中,想到尽量不引入更多的东西,然 ...

  10. HttpMessageConverter 专题

    配置HttpMessageConverterHttpMessageConverter是对http的request和response进行自动转换配置HttpMessageConverter可重载下面两个 ...

随机推荐

  1. CSS实现带阴影效果的三角形

    具体实现 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta ...

  2. JavaScript 网页脚本语言 由浅入深 (随笔)

    1)基础 学习目的: 1. 客户端表单验证 2. 页面动态效果 3. jQuery的基础 什么是JavaScript? 一种描述性语言,也是一种基于对象和事件驱动的,并具有安全性能的脚本语言 java ...

  3. HTTP 的请求过程?

    当点击一个链接时,浏览器首先找到站点的IP地址,这是通过DNS来实现的,在找到IP地址后就可以建立TCP连接了,连接建立后我们就可以发送请求了.但这个请求是什么样子的呢 ? 我们现在假设点击了一个从 ...

  4. android studio 添加有趣的注释模板 佛祖保佑无bug等

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 汉化包 百度云盘 下载地址:https://pan.baidu.com/s/1pLjwy ...

  5. 2333: [SCOI2011]棘手的操作[我不玩了]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1979  Solved: 772[Submit][Stat ...

  6. C++11中的raw string literals

    作为一名C++书看得少得可怜的新手,我一直没有勇气去系统地学习一下C++ 11添加的新特性.不过,平日里逛论坛,阅读大犇们的博客,倒是了解了一些.比如,这个帖子: 如何绕过g++ 4.8.1那个不能在 ...

  7. [HDU6212]Zuma

    题目大意: 祖玛游戏. 给你一个01串,你可以往里面加一些0或1,如果连续的0或1超过3个,那么就可以消去.问消去所有的珠子至少要加几个珠子. 思路: 区间DP. 首先把原来的01串,改成存储连续的同 ...

  8. bzoj 1176: [Balkan2007]Mokia&&2683: 简单题 -- cdq分治

    2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MB Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要 ...

  9. ZOJ 2969 Easy Task

    E - Easy Task Description Calculating the derivation of a polynomial is an easy task. Given a functi ...

  10. ZeptoLab Code Rush 2015 A. King of Thieves 暴力

    A. King of Thieves Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/526/pr ...