HttpMessageConverter接口定义

 * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
*/
public interface HttpMessageConverter<T> { /**
* Indicates whether the given class can be read by this converter.
* @param clazz the class to test for readability
* @param mediaType the media type to read, can be {@code null} if not specified.
* Typically the value of a {@code Content-Type} header.
* @return {@code true} if readable; {@code false} otherwise
*/
boolean canRead(Class<?> clazz, MediaType mediaType); /**
* Indicates whether the given class can be written by this converter.
* @param clazz the class to test for writability
* @param mediaType the media type to write, can be {@code null} if not specified.
* Typically the value of an {@code Accept} header.
* @return {@code true} if writable; {@code false} otherwise
*/
boolean canWrite(Class<?> clazz, MediaType mediaType); /**
* Return the list of {@link MediaType} objects supported by this converter.
* @return the list of supported media types
*/
List<MediaType> getSupportedMediaTypes(); /**
* Read an object of the given type form the given input message, and returns it.
* @param clazz the type of object to return. This type must have previously been passed to the
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException; /**
* Write an given object to the given output message.
* @param t the object to write to the output message. The type of this object must have previously been
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
* default content type of the converter must be used. If not {@code null}, this media type must have
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
* returned {@code true}.
* @param outputMessage the message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors
*/
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException; }

该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。

常用的HttpMessageConverter

在使用 <mvc:annotation-driven />标签配置时,默认配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter),并为他配置了一下默认的HttpMessageConverter:

ByteArrayHttpMessageConverter converts byte arrays.  

StringHttpMessageConverter converts strings.  

ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.  

SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.  

FormHttpMessageConverter converts form data to/from a MultiValueMap<String, String>.  

Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present on the classpath.  

MappingJacksonHttpMessageConverter converts to/from JSON — added if Jackson is present on the classpath.  

AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.  

RssChannelHttpMessageConverter converts RSS feeds — added if Rome is present on the classpath.  

ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;

StringHttpMessageConverter:负责读取字符串格式的数据和写出二进制格式的数据;

ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据; 

FormHttpMessageConverter:负责读取form提交的数据(能读取的数据格式为 application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入application/x-www-from-urlencoded和multipart/form-data格式的数据;

MappingJacksonHttpMessageConverter:  负责读取和写入json格式的数据;

SouceHttpMessageConverter:负责读取和写入 xml 中javax.xml.transform.Source定义的数据;

Jaxb2RootElementHttpMessageConverter:负责读取和写入xml 标签格式的数据;

AtomFeedHttpMessageConverter:负责读取和写入Atom格式的数据;

RssChannelHttpMessageConverter:负责读取和写入RSS格式的数据;

当使用 @RequestBody和 @ResponseBody注解时,RequestMappingHandlerAdapter就使用它们来进行读取或者写入相应格式的数据。

HttpMessageConverter匹配过程:

@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据。

spring 3.1源代码如下:

private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType) throws Exception {  

    MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
String paramName = methodParam.getParameterName();
if (paramName != null) {
builder.append(' ');
builder.append(paramName);
}
throw new HttpMediaTypeNotSupportedException("Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
} List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
if (this.messageConverters != null) {
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
if (messageConverter.canRead(paramType, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType + "\" using [" + messageConverter + "]");
}
return messageConverter.read(paramType, inputMessage);
}
}
}
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}

@ResponseBody注解时:根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的HttpMessageConverter。

spring 3.1 源代码如下:

private void writeWithMessageConverters(Object returnValue,  HttpInputMessage inputMessage, HttpOutputMessage outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {
List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
if (acceptedMediaTypes.isEmpty()) {
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
}
MediaType.sortByQualityValue(acceptedMediaTypes);
Class<?> returnValueType = returnValue.getClass();
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
if (getMessageConverters() != null) {
for (MediaType acceptedMediaType : acceptedMediaTypes) {
for (HttpMessageConverter messageConverter : getMessageConverters()) {
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = acceptedMediaType;
}
logger.debug("Written [" + returnValue + "] as \"" + contentType +
"\" using [" + messageConverter + "]");
}
this.responseArgumentUsed = true;
return;
}
}
}
for (HttpMessageConverter messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
}
}
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}

HttpMessageConverter用法的更多相关文章

  1. @RequestMapping 用法详解之地址映射

    @RequestMapping 用法详解之地址映射 引言: 前段时间项目中用到了RESTful模式来开发程序,但是当用POST.PUT模式提交数据时,发现服务器端接受不到提交的数据(服务器端参数绑定没 ...

  2. RestTemplate 微信接口 text/plain HttpMessageConverter

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

  3. Spring常用注解用法总结

    转自http://www.cnblogs.com/leskang/p/5445698.html 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由Dispat ...

  4. Spring MVC的WebMvcConfigurerAdapter用法收集(零配置,无XML配置)

    原理先不了解,只记录常用方法 用法: @EnableWebMvc 开启MVC配置,相当于 <?xml version="1.0" encoding="UTF-8&q ...

  5. [转帖]@RequestMapping 用法详解之地址映射(转)

    @RequestMapping 用法详解之地址映射(转) https://www.cnblogs.com/qq78292959/p/3760560.html 从csdn 发现的文章 然后csdn指向c ...

  6. EditText 基本用法

    title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...

  7. jquery插件的用法之cookie 插件

    一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...

  8. Java中的Socket的用法

                                   Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...

  9. [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法

    一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...

随机推荐

  1. Nlog Layout

    Nlog.config <targets>     <target type="Console" name="trace" layout=&q ...

  2. bzoj3571

    同样的最小乘积XXX模型,这里显然是二分图带权匹配 我不会写KM……于是写了个费用流,由于是稠密图,会退化到n^4 然后本地跑了56s,交上去过了………………一定是我电脑太慢…… 改天写个KM吧 *; ...

  3. iOS开发:本地数据存储-NSUserDefaults

    Getting Default Values arrayForKey(_:) boolForKey(_:) dataForKey(_:) dictionaryForKey(_:) floatForKe ...

  4. Asp.Net操作FTP方法

    将用户上传的附件(文件.图片等)通过FTP方式传送到另外一台服务器上,从而缓解服务器压力 1.相关的文章如下: Discuz!NT中远程附件的功能实现[FTP协议] http://www.cnblog ...

  5. windows安装TortoiseGit详细使用教程【基础篇】

    标签:tortoisegit 环境:win8.1 64bit 安装准备: 首先你得安装windows下的git msysgit1.9.5 安装版本控制器客户端tortoisegit  tortoise ...

  6. LeetCode Letter Combinations of a Phone Number 电话号码组合

    题意:给一个电话号码,要求返回所有在手机上按键的组合,组合必须由键盘上号码的下方的字母组成. 思路:尼玛,一直RE,题意都不说0和1怎么办.DP解决. class Solution { public: ...

  7. 在Windows下编译FFmpeg详细说明

    MinGW:一个可自由使用和自由发布的Windows特定头文件和使用GNC工具集导入库的集合,允许你生成本地的Windows程序而不需要第三方C运行时 MinGW,即 Minimalist GNU F ...

  8. $( ).focus()与$( )[0].focus()区别

    $( #id).focus()与$( #id)[0].focus()没有区别,因为id必须是唯一的.如果同一页面出现多个相同的ID(这是不符合w3c规范的),$(#id)也只会拿到第一个该ID,后面的 ...

  9. C# 如何以参数的形式调用.exe程序

    System.Diagnostics.Process.Start("程序的路径", "参数1 参数2");第一个参数是aaa.exe 的路径,第二个参数是用空格 ...

  10. 在Ubuntu下卸载Apache

    卸载Apache 转自:http://blog.csdn.net/chmo2011/article/details/7026384 1. 删除apache 代码: $ sudo apt-get --p ...