简介:

@RequestBody

作用:

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

ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

使用时机:

A) GET、POST方式提时, 根据request header Content-Type的值来判断:

  • application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
  • multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
  • 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);

B) PUT方式提交时, 根据request header Content-Type的值来判断:

  • application/x-www-form-urlencoded, 必须;
  • multipart/form-data, 不能处理;
  • 其他格式, 必须;

说明:request的body部分的数据编码格式由header部分的Content-Type指定;

@ResponseBody

作用:

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

使用时机:

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

HttpMessageConverter

  1. <span style="font-family:Microsoft YaHei;">/**
  2. * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
  3. *
  4. * @author Arjen Poutsma
  5. * @author Juergen Hoeller
  6. * @since 3.0
  7. */
  8. public interface HttpMessageConverter<T> {
  9.  
  10. /**
  11. * Indicates whether the given class can be read by this converter.
  12. * @param clazz the class to test for readability
  13. * @param mediaType the media type to read, can be {@code null} if not specified.
  14. * Typically the value of a {@code Content-Type} header.
  15. * @return {@code true} if readable; {@code false} otherwise
  16. */
  17. boolean canRead(Class<?> clazz, MediaType mediaType);
  18.  
  19. /**
  20. * Indicates whether the given class can be written by this converter.
  21. * @param clazz the class to test for writability
  22. * @param mediaType the media type to write, can be {@code null} if not specified.
  23. * Typically the value of an {@code Accept} header.
  24. * @return {@code true} if writable; {@code false} otherwise
  25. */
  26. boolean canWrite(Class<?> clazz, MediaType mediaType);
  27.  
  28. /**
  29. * Return the list of {@link MediaType} objects supported by this converter.
  30. * @return the list of supported media types
  31. */
  32. List<MediaType> getSupportedMediaTypes();
  33.  
  34. /**
  35. * Read an object of the given type form the given input message, and returns it.
  36. * @param clazz the type of object to return. This type must have previously been passed to the
  37. * {@link #canRead canRead} method of this interface, which must have returned {@code true}.
  38. * @param inputMessage the HTTP input message to read from
  39. * @return the converted object
  40. * @throws IOException in case of I/O errors
  41. * @throws HttpMessageNotReadableException in case of conversion errors
  42. */
  43. T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
  44. throws IOException, HttpMessageNotReadableException;
  45.  
  46. /**
  47. * Write an given object to the given output message.
  48. * @param t the object to write to the output message. The type of this object must have previously been
  49. * passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
  50. * @param contentType the content type to use when writing. May be {@code null} to indicate that the
  51. * default content type of the converter must be used. If not {@code null}, this media type must have
  52. * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
  53. * returned {@code true}.
  54. * @param outputMessage the message to write to
  55. * @throws IOException in case of I/O errors
  56. * @throws HttpMessageNotWritableException in case of conversion errors
  57. */
  58. void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
  59. throws IOException, HttpMessageNotWritableException;
  60.  
  61. }
  62. </span>

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

在使用 <mvc:annotation-driven />标签配置时,默认配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看spring 3.1 document “16.14 Configuring spring MVC”章节),并为他配置了一下默认的HttpMessageConverter:

  1. ByteArrayHttpMessageConverter converts byte arrays.
  2.  
  3. StringHttpMessageConverter converts strings.
  4.  
  5. ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.
  6.  
  7. SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.
  8.  
  9. FormHttpMessageConverter converts form data to/from a MultiValueMap<String, String>.
  10.  
  11. Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML added if JAXB2 is present on the classpath.
  12.  
  13. MappingJacksonHttpMessageConverter converts to/from JSON added if Jackson is present on the classpath.
  14.  
  15. AtomFeedHttpMessageConverter converts Atom feeds added if Rome is present on the classpath.
  16.  
  17. 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匹配过程:

  1. <span style="font-family:Microsoft YaHei;">private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType)
  2. throws Exception {
  3.  
  4. MediaType contentType = inputMessage.getHeaders().getContentType();
  5. if (contentType == null) {
  6. StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
  7. String paramName = methodParam.getParameterName();
  8. if (paramName != null) {
  9. builder.append(' ');
  10. builder.append(paramName);
  11. }
  12. throw new HttpMediaTypeNotSupportedException(
  13. "Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
  14. }
  15.  
  16. List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
  17. if (this.messageConverters != null) {
  18. for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
  19. allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
  20. if (messageConverter.canRead(paramType, contentType)) {
  21. if (logger.isDebugEnabled()) {
  22. logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
  23. +"\" using [" + messageConverter + "]");
  24. }
  25. return messageConverter.read(paramType, inputMessage);
  26. }
  27. }
  28. }
  29. throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
  30. }</span>

 

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

源代码如下:

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

spring 3.1源代码如下:

  1. <span style="font-family:Microsoft YaHei;">private void writeWithMessageConverters(Object returnValue,
  2. HttpInputMessage inputMessage, HttpOutputMessage outputMessage)
  3. throws IOException, HttpMediaTypeNotAcceptableException {
  4. List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
  5. if (acceptedMediaTypes.isEmpty()) {
  6. acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
  7. }
  8. MediaType.sortByQualityValue(acceptedMediaTypes);
  9. Class<?> returnValueType = returnValue.getClass();
  10. List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
  11. if (getMessageConverters() != null) {
  12. for (MediaType acceptedMediaType : acceptedMediaTypes) {
  13. for (HttpMessageConverter messageConverter : getMessageConverters()) {
  14. if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
  15. messageConverter.write(returnValue, acceptedMediaType, outputMessage);
  16. if (logger.isDebugEnabled()) {
  17. MediaType contentType = outputMessage.getHeaders().getContentType();
  18. if (contentType == null) {
  19. contentType = acceptedMediaType;
  20. }
  21. logger.debug("Written [" + returnValue + "] as \"" + contentType +
  22. "\" using [" + messageConverter + "]");
  23. }
  24. this.responseArgumentUsed = true;
  25. return;
  26. }
  27. }
  28. }
  29. for (HttpMessageConverter messageConverter : messageConverters) {
  30. allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
  31. }
  32. }
  33. throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
  34. }</span>

补充:

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

@RequestBody, @ResponseBody 注解详解的更多相关文章

  1. @RequestBody, @ResponseBody 注解详解(转)

    原文地址: https://www.cnblogs.com/qq78292959/p/3760651.html @RequestBody, @ResponseBody 注解详解(转) 引言: 接上一篇 ...

  2. @RequestBody 和@ResponseBody 注解详解

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

  3. 【转】@RequestParam @RequestBody @PathVariable 等参数绑定注解详解

    @RequestParam @RequestBody @PathVariable 等参数绑定注解详解 2014-06-02 11:24 23683人阅读 评论(2) 收藏 举报 目录(?)[+] 引言 ...

  4. @PathVariable @RequestParam @RequestBody等参数绑定注解详解

    一.分类 handler method 参数绑定常用的注解,我们根据他们处理的Request的内容不同分为四类: 处理request uri 部分的注解:   @PathVariable;(这里指ur ...

  5. SpringMVC 常用注解 详解

    SpringMVC 常用注解 详解 SpringMVC 常用注解 1.@RequestMapping                                      路径映射 2.@Requ ...

  6. @ModelAttribute注解详解

    @ModelAttribute注解详解 1.@ModelAttribute定义: 被该注解定义的方法,会在该方法所在的controller的任何目标方法执行之前执行 2.@ModelAttribute ...

  7. Java基础13:反射与注解详解

    Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...

  8. java中的注解详解和自定义注解

    一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...

  9. SpringBoot事务注解详解

    @Transactional spring 事务注解 1.简单开启事务管理 @EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:ann ...

随机推荐

  1. BZOJ-1008 越狱 数论快速幂

    1008: [HNOI2008]越狱 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 6192 Solved: 2636 [Submit][Status] ...

  2. spring c3p0数据库连接池连接配置

    c3p0连接池配置 xml文件内容如下: C3P0 通过这些属性,可以对数据源进行各种有效的控制 lc_biz_datasource_c3p0.properties 配置: lc_biz_dataso ...

  3. C#获取本机的MAC地址

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.M ...

  4. electron加载jquery报错问题

    <!-- Insert this line above script imports --> <script>if (typeof module === 'object') { ...

  5. std::thread join和detach区别

    thread detach, join 线程有两种状态,joinable或者detachable,pthread默认创建的线程是joinable的,也可以指定atrribute创建成一个detacha ...

  6. tp三大自动

    ThinkPHP三大自动 (2012-03-21 10:48:56) 转载▼ 标签: thinkphp 三大自动 自动验证 自动完成 自动填充 自动映射 字段映射 杂谈 分类: php 一.自动验证 ...

  7. 修改更新源sources.list,提高软件下载安装速度(提供Kali 2.0 更新源)

    1.切换到root用户(如果已经是root用户就直接看第二步) dnt@HackerKali:~$ su 密码: 2.用文本编辑器打开sources.list,手动添加下面的更新源 root@Hack ...

  8. meclipse中project facet问题

    meclipse中project facet问题 (2012-02-14 14:59:48) 转载▼ 标签: 杂谈 分类: 技术 一般出现在从别处import的项目上,只有项目文件夹上有红叉,其他地方 ...

  9. Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)

    Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...

  10. C++ 迭代器 基础介绍

    C++ 迭代器 基础介绍 迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围.迭代器就如同一个指针.事实上,C++的指针也是一种迭代器.但是,迭代器不仅仅是指针,因此你不能认为他们一定 ...