第三节:HttpMessageConverter

一、HttpMessageConverter<T>

  1、HttpMessageConverter 简介

    HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型T)输出为响应信息

  2、HttpMessageConverter<T> 接口定义的方法

  ① Boolean canRead(Class<?> clazz, MediaType mediaType):指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html; application/json 等)
        ② Boolean canWriter(Class<?> clazz, MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在 MediaType 中定义;
        ③ List<MediaType> getSupportMediaTypes():该转化器支持的媒体类型;
        ④ T read(Class<? extends T> clazz, HttpInputMessage inputMessage ):将请求信息转换为 T 类型的对象;
        ⑤ void write(T t, MediaType contentType, HttpOutputMessage outputMessage):将 T 类型的对象写到响应流中,同时指定相应的媒体类型为 contentType。    
    
// HttpInputMessage
import java.io.IOException;
import java.io.InputStream;
public interface HttpInputMessage extends HttpMessage {
    InputStream getBody() throws IOException;
}

//HttpOutputMessage
import java.io.IOException;
import java.io.OutputStream;
public interface HttpOutputMessage extends HttpMessage {
    OutputStream getBody() throws IOException;
}
 

二、HttpMessageConverter<T> 的实现类

  1、实现类

  2、DispatcherServlet 默认装配的是  RequestMappingHandleAdapter,而 RequestMappingHandlerAdapter  默认装配如下 HttpMessageConverter

    

  3、加入 jackson 的 jar 包后,RequestMappingHandlerAdapter 装配的 HttpMessageConverter。如下:

    默认情况下数组长度是6个:增加了 jackson 的包后多了一个 MappingJackson2HttpMessageConverter。

三、使用 HttpMessageConverter<T>

  1、使用 HttpMessageConverter<T>

  使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的形参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
  (1)使用 @RequestBody / @ResponseBody 对处理方法进行标注;
  (2)使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的形参或返回值

  2、如何使用

    当控制器处理方法使用到 @RequestBody / @ResponseBody 或 HttpEntity<T> / ResponseEntity<T> 时,Spring 首先根据请求头或响应头的  Accept 属性选择匹配的 HttpMessageConverter,进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter,若找不到可用的 HttpMessageConverter 将报错。
    @RequestBody / @ResponseBody  不需要成对出现
 

  3、@RequestBody 与 @ResponseBody 示例

     示例:

    (1)控制器

@Controller
public class TestHttpMessageConverter {
     //@RequestBody:是将 Http 请求正文插入方法中,修饰目标方法的形参
     @RequestMapping(value="/testHttpMessageConverter")
     @ResponseBody  //@ResponseBody 是将内容或对象作为  Http 响应正文返回
     public String  testHttpMessageConverter(@RequestBody String body) {
         System.out.println("body=" + body);
         return "Hello," + new Date();  //不再查找跳转的页面
     }
}

    (2)页面请求

     <form action="testHttpMessageConverter"  method="post" enctype="multipart/form-data">
         文件:<input type="file" name="file" />  

         描述:<input type="text" name="desc" />  

         <input type="submit" value="提交"/>
     </form>

    (3)结果

body=------WebKitFormBoundary52UbVwlZZjWzjOhh
Content-Disposition: form-data; name="file"; filename=""
Content-Type: application/octet-stream


------WebKitFormBoundary52UbVwlZZjWzjOhh
Content-Disposition: form-data; name="desc"


------WebKitFormBoundary52UbVwlZZjWzjOhh--

  4、HttpEntity<T> 与 ResponseEntity<T>

  

  

   示例:

  (1)HttpEntity 代码示例

     @RequestMapping("/handle")
     public String handle(HttpEntity<String> entity) {
         System.out.println(entity.getHeaders().getContentLength());
         System.out.println(entity.getHeaders().getContentType());
         return "success";
     }

  (2)ResponseEntity 示例

@Controller
public class FileController {
     
     @RequestMapping(value="/down")
     public ResponseEntity<byte[]> downFile(HttpSession  session) throws IOException {
         
         //获取下载文件的路径
         ServletContext servletContext =  session.getServletContext();
         String realPath =  servletContext.getRealPath("img");
         String finalPath = realPath + File.separator +  "1.jpg";
         
         //读取文件
         InputStream is = new  FileInputStream(finalPath);
         //将整个文件放入到 byte 数组中, available() 获取输入流所读取的文件的最大字节数
         byte[] b = new byte[is.available()];
         is.read(b);
         
         //设置请求头
         //HttpHeaders headers = new HttpHeaders();
         MultiValueMap<String, String> headers = new  HttpHeaders();
         //headers.add("Content-Disposition",  "attachment;filename=中国.jpg");  文件名为中文,不显示,存在问题
         headers.add("Content-Disposition",  "attachment;filename=aaa.jpg");
         
         //设置响应状态
         HttpStatus statusCode = HttpStatus.OK;
         
         //将响应数据到客户端
         // ResponseEntity<T>(T body,  MultiValueMap<String,String> headers, HttpStatus  statusCode)
         ResponseEntity<byte[]> entity = new  ResponseEntity<byte[]>(b, headers, statusCode);
         
         return entity;
     }
}

  MultiValueMap<K,V> 继承关系:

  

四、扩展

  1、HttpHeaders

    该类继承了 MultiValueMap<K,V> 里面大多数都是与请求头相关。

  2、HttpStatus

    

  这个一个枚举类,这里定义了许多中请求状态。
  如:OK:200 表示请求成功
                       404:路径错误或资源不存在
                       400:请求错误
                      405:请求方式和处理方式不匹配
                      406:客户端不能接收响应
                      500:服务器内部出现错误
原文地址:https://www.cnblogs.com/niujifei/p/15642026.html