zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    设计模式学习笔记--迭代器模式
    设计模式学习笔记--组合模式
    设计模式学习笔记--备忘录模式
    Asp.Net Core IdentityServer4 中的基本概念
    Asp.Net Core 中间件应用实践中你不知道的那些事
    Asp.Net Core Filter 深入浅出的那些事-AOP
    ASP.NET CORE 内置的IOC解读及使用
    ASP.NET CORE 管道模型及中间件使用解读
    ASP.NET CORE 启动过程及源码解读
    Linux +Docker +Nginx 部署代理转发初探
  • 原文地址:https://www.cnblogs.com/softidea/p/9756441.html
Copyright © 2011-2022 走看看