该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

HttpMessageConverter

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()方法。

在使用 <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;

源代码如下:

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);  }

MappingJacksonHttpMessageConverter 调用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的对象就传入Object参数内。若返回的对象为已经格式化好的json串时,不使用@RequestBody注解,而应该这样处理:
1、response.setContentType("application/json; charset=UTF-8");
2、response.getWriter().print(jsonStr);
直接输出到body区,然后的视图为void。

@ResponseBody相关推荐

  1. @responseBody和@RequestBody

    @responseBody和@RequestBody @responseBody把后台pojo转换json对象,返回到页面. @RequestBody接受前台json数据,把json数据自动封装jav ...

  2. Spring MVC常用注解--“姐妹花”@RequestBody和@ResponseBody

    1. 引言 在这篇短文中,我们简要地介绍了Spring MVC中常用的注解 @RequestBody和@ResponseBody. 2. @RequestBody 简单地说,在@RequestBody ...

  3. @ResponseBody注解作用

    https://blog.csdn.net/qq_41378597/article/details/84295071 @ResponseBody注解的作用是将controller的方法返回的对象 通过 ...

  4. @ResponseBody 和 @RequestBody 的作用

    先提一嘴 @RequestMapping("url"),这里的 url写的是请求路径的一部分,一般作用在 Controller的方法上,作为请求的映射地址. 代码: @Reques ...

  5. @ResponseBody 注解

    @ResponseBody 作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区. ...

  6. 如何在返回String的Spring MVC @ResponseBody方法中响应HTTP 400错误?

    本文翻译自:How to respond with HTTP 400 error in a Spring MVC @ResponseBody method returning String? I'm ...

  7. @RequestBody, @ResponseBody 注解详解

    简介: @RequestBody 作用: i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对 ...

  8. spring boot中@ResponseBody等注解的作用与区别

    在使用springmvc框架的时候,在处理json的时候需要用到spring框架特有的注解@ResponseBody或者@RestController注解,这两个注解都会处理返回的数据格式,使用了该类 ...

  9. 详述@ResponseBody和@RequestBody注解的区别

    2019独角兽企业重金招聘Python工程师标准>>> 1 前言 在详述 @ResponseBody 和 @RequestBody 注解之前,咱先了解一下 @RequestMappi ...

最新文章

  1. 参加51CTO学院软考培训,我通过啦
  2. 使用 Tye 辅助开发 dotnet 应用程序
  3. C++(STL):28 ---关联式容器map用法
  4. linux7自动挂载怎么做,centos 7 实现自动按需挂载
  5. Python 精要参考(第二版) 第八章 模块和包
  6. 1)python,现在用过的,后面推出每日练习语法与深度挖掘应用
  7. 计算机速录学什么,学速录需要哪些能力
  8. CAM350对比电路图方法
  9. C语言编程齿轮轮廓线坐标,c语言程序实现齿轮基本参数几何尺寸计算.pdf
  10. 面试经验|传音控股自动化测试
  11. 27种主流编程语言分类及优劣
  12. 不恢复余数除法原理_小学数学基础概念大全,家长收藏起来,一条一条讲给孩子听。能全背下来的,考试也不带怕的了!...
  13. 入侵检测工具AIDE极简教程
  14. 星起航:短视频营销之场景化
  15. apicloud的使用
  16. Mac通过brew安装Nodejs错误:Could not symlink lib/dtrace/node.d
  17. Mondo Rescue备份iso镜像文件与安装系统
  18. 1.11——Go语言适合做什么
  19. 微软研究院科大实习生聚餐
  20. windows installer 窗口一直”正在取消“,无法关闭

热门文章

  1. 张三入职遭遇,供入台资企业参考
  2. shell逻辑判断式与表达式
  3. 如何用hover写出顺畅的动态效果
  4. 部分 VII. Array
  5. 集合覆盖 顶点覆盖: set cover和vertex cover
  6. 挑战“IT我最大 Win7由你秀”
  7. freebsd 编译核心
  8. Xshell连接不上虚拟机Linux系统
  9. Flume日志收集系统
  10. Android利用RecyclerView实现列表倒计时