HttpMessageConverter

一、HttpMessageConverter<T>  

作用:
它负责将请求信息转换为一个对象(类型为T),将该对象输出为响应信息。

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

那么问题来了?
问题1:如何使用HttpMessageConverter<T>  将请求信息转化并绑定到处理方法的入参当中呢?

解答:      
1.使用@RequestBody/@ResponseBody对处理方法进行标注
         
2.使用HttpEntity<T>/ResponseEntity<T>作为处理方法的入参或者返回值

问题2:处理方法如何知道请求消息的格式?在处理完成后又是根据什么确定响应消息的格式嗯?
解答:根据请求消息头的”Content-Type“及Accept属性确定。

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 将方法返回值转换并输出响应消息。

ResponseEntity< byte[]> re = new ResponseEntity<byte []>(bytes, headers, statusCode);


https://blog.csdn.net/u010834071/article/details/41773371

HttpMessageConverter主要针对那些不会返回view视图的response。其中StringHttpMessageConverter有两个构造函数。当你没有给它指定字符集时,使用默认的ISO-8859-1,这便是造成乱码的一个原因,由于我们经常使用utf-8,所以可以在构造它时指定一下字符集。

引言:如何在SpringMVC中统一对返回的Json进行加密?”。

大部分人的第一反应是通过SpringMVC拦截器(Interceptor)中的postHandler方法处理。实际这是行不通的,因为当程序运行到该方法,是在返回数据之后,渲染页面之前,所以这时候HttpServletResponse中的输出流已经关闭了,自然无法在对返回数据进行处理。

其实这个问题用几行代码就可以搞定,因为SpringMVC提供了非常丰富的扩展支持,无论是之前提到的MethodArgumentResolverHandlerMethodReturnValueHandler,还是接下来要提到的HttpMessageConverter

在SpringMVC的 Controller层经常会用到@RequestBody@ResponseBody,通过这两个注解,可以在Controller中直接使用Java对象作为请求参数和返回内容,而完成这之间转换作用的便是HttpMessageConverter

--------------------- 本文来自 若水三千-LOVE 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/lovesomnus/article/details/73918025?utm_source=copy 

@RequestBody作用:

  1. 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
  2. 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

使用时机:

  1. GET、POST方式提时, 根据request header Content-Type的值来判断:
    application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据 @RequestParam, @ModelAttribute也可以处理,当然 @RequestBody也能处理);
    multipart/form-data, 不能处理(即使用 @RequestBody不能处理这种格式的数据);
    其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用 @RequestBody来处理);
  2. 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等)使用;

https://www.cnblogs.com/cuiyf/p/6247862.html

json数据交互

☛ @RequestBody

@RequestBody注解用于读取 http 请求的内容(字符串),通过 SpringMVC 提供的 HttpMessageConverter 接口将读到的内容转换为 json、xml 等格式的数据并绑定到 controller 方法的参数上。

本例子的应用:@RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象

List.action?id=1&name=zhangsan&age=12
复制代码

☛ @ResponseBody

作用:该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 response 响应给客户端。

本例子的应用:@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端


作者:Jaybo
链接:https://juejin.im/post/5b83c4a151882542f105470e
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

REST支持
除了典型的MVC场景之外,我们还可以使用框架来创建REST Web服务。
简而言之,我们可以接受Resource作为输入,指定POJO作为方法参数,并使用@RequestBody对其进行注释。也可以使用@ResponseBody注释方法本身,以指定其结果必须直接转换为HTTP响应:

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
@ResponseBody
@PostMapping("/message")
public MyOutputResource sendMessage(
@RequestBody MyInputResource inputResource) {
return new MyOutputResource("Received: "
+ inputResource.getRequestMessage());
}

归功于Spring MVC的可扩展性,这也是可行的。
为了将内部DTO编组为REST表示,框架使用HttpMessageConverter基础结构。例如,其中一个实现是MappingJackson2HttpMessageConverter,它可以使用Jackson库将模型对象转换为JSON或从JSON转换。

https://www.zhihu.com/question/38696452

SpringMVC返回JSON

参考:http://blog.icoolxue.com/springmvc-3%E4%BD%BF%E7%94%A8fastjson%E4%BB%A3%E6%9B%BFjackson/
http://my.oschina.net/haopeng/blog/324934
由于SpringMVC默认采用Jackson解析Json,所以首先添加Jackson相关依赖。



<jackson.version>1.8.9</jackson.version>   

<dependency>   
  <groupId>org.codehaus.jackson</groupId>   
  <artifactId>jackson-core-lgpl</artifactId>   
  <version>${jackson.version}</version>   
</dependency>   
<dependency>   
  <groupId>org.codehaus.jackson</groupId>   
  <artifactId>jackson-mapper-lgpl</artifactId>   
  <version>${jackson.version}</version>   
</dependency>

然后进行如下步骤:
1、配置<mvc:annotation-driven/>启用
2、controller 配置@ResponseBody . @RequestBody注解的命令对象的转换,Spring会根据相应的HttpMessageConverter进行模型数据(处理方法的返回值)到JSON响应内容的转换。跳过View解析直接输出到客户端。

注意:使用@ResponseBody时不要忘记在@ReuqestMapping的属性中添加headers = "Accept=application/json"
注意:使用@RequestBody不要忘记在@ReuqestMapping的属性中添加headers = "Content-Type=application/json"
原因:当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用HttpMessageConverter来进行读取或者写入相应格式的数据。
HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的
@Controller public class LoginController { @RequestMapping(value="/validataUser.json" headers = "Accept=application/json") @ResponseBody public Map<String,Object> validataUser(@RequestParam String userName){ logger.info(" validata user : {}",userName); Map<String,Object> map = new HashMap<String,Object>(); map.put("code", true); return map; } }
## 使用FastJson替换Jackson
首先别忘了添加Fastjson的包,如果使用Maven,可使用如下设置
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.7</version> </dependency>
<!-- 启用默认配置 --> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!-- 配置Fastjson支持 --> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <property name="supportedMediaTypes"> <list> <!-- 这里顺序不能反,一定先写text/html,不然ie下出现下载提示 --> <value>text/html;charset=UTF-8</value> <value>application/json</value> </list> </property> <!-- <property name="features"> <list> <value>WriteMapNullValue</value> <value>QuoteFieldNames</value> </list> </property> --> </bean> </mvc:message-converters> </mvc:annotation-driven>
## @RequestBody, @ResponseBody详解
详细介绍下@RequestBody、@ResponseBody的具体用法和使用时机;
@RequestBody
作用:
i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
注意:使用@RequestBody不要忘记在@ReuqestMapping的属性中添加headers = "Content-Type=application/json"



 @RequestMapping(value = "/{username}", method = RequestMethod.PUT,    
                  headers = "Content-Type=application/json")   // headers = "Content-Type=application/json"   
  @ResponseStatus(HttpStatus.NO_CONTENT)   
  public void updateSpitter(@PathVariable String username,    
                        @RequestBody Spitter spitter) {  // @RequestBody   
    spitterService.saveSpitter(spitter);   
  }
  • 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等)使用;

注意:使用@ResponseBody时不要忘记在@ReuqestMapping的属性中添加headers = "Accept=application/json"



 @RequestMapping(value = "/{username}/spittles",    
                  method = RequestMethod.GET,    
                  headers = "Accept=application/json")//headers = "Accept=application/json"   
  public @ResponseBody   List<Spittle> getSpittlesForSpitter(@PathVariable String username) {  //@ResponseBody   List<Spittle>   
    return spitterService.getSpittlesForSpitter(username);   
  }

HttpMessageConverter

该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。
在使用<mvc:annotation-driven />标签配置时:

  • 1、默认配置了RequestMappingHandlerAdapter(注意SpringMVC3.1之后是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看Spring 3.1 document “16.14 Configuring Spring MVC”章节),
  • 2、并为他配置了一下默认的HttpMessageConverter

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来读取数据;
@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的

关于直接返回json格式字符串的注意:

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

方式二、不过也可以使用@ResponseBody,不过需要进行乱码配置:
直接返回字符串,使用@ResponseBody注解时,后台会调用StringHttpMessageConverter,它默认的字符集为ISO-8859-1,这会导致中文乱码。可以参考[[spring:springmvc_json乱码]]进行配置即可。

参考:
http://blog.csdn.net/kobejayandy/article/details/12690555

http://www.xby1993.net/pages/dokuwiki/spring/springmvc%E8%BF%94%E5%9B%9Ejson.html

原文地址:https://www.cnblogs.com/softidea/p/9756441.html