zoukankan      html  css  js  c++  java
  • 11.SpringMVC之HttpMessageConverter

    HttpMessageConverter简介

    HTTP 请求和响应的传输是字节流,意味着浏览器和服务器通过字节流进行通信。但是,使用 Spring,controller 类中的方法返回纯 String 类型或其他 Java 内建对象。如何将对象转换成字节流进行传输?

    在报文到达SpringMVC和从SpringMVC出去,都存在一个字节流到java对象的转换问题。在SpringMVC中,它是由HttpMessageConverter来处理的。

    当请求报文来到java中,它会被封装成为一个ServletInputStream的输入流,供我们读取报文。响应报文则是通过一个ServletOutputStream的输出流,来输出响应报文。

    我们可以用下图来加深理解。

     

    HttpMessageConverter接口

    在Spring中,内置了大量的HttpMessageConverter。通过请求头信息中的MIME类型,选择相应的HttpMessageConverter。

    // 数据转换器 -> 将数据转换成 requests 或 response 中的数据
    public interface HttpMessageConverter<T> {
    
        // 指定的 class 是否支持读取(MediaType 指数据的格式)
        boolean canRead(Class<?> clazz, MediaType mediaType);
    
        // 传入 class 与 MediaType -> 看 HttpMessageConverter 是否支持写数据到数据流中
        boolean canWrite(Class<?> clazz, MediaType mediaType);
    
        // 返回 HttpMessageConverter 支持的 MediaType
        List<MediaType> getSupportedMediaTypes();
    
        // 从 HttpInputMessage 中读取数据流, 并转化成 T 这站类型
        T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
    
        // 将 T 里面的数据信息写入到 HttpOutputMessage 的数据流中
        void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
    }

    HttpMessageConverter接口的定义中出现了成对的canRead(),read()和canWrite(),write()方法。MediaType是对请求的Media Type属性的封装。

    read方法中有一个HttpInputMessage,我们查看它的源码如下。

    public interface HttpInputMessageextends HttpMessage {
      InputStreamgetBody() throws IOException;
    }

    HttpInputMessage提供的接口就是将body中的数据转为输入流。
    write方法中有一个HttpOutputMessage,我们查看它的源码如下。

    public interface HttpOutputMessageextends HttpMessage {
      OutputStreamgetBody() throws IOException;
    }

    HttpOutputMessage提供的接口就是将body中的数据转为输出流。
    它们拥有相同的父接口HttpMessage。

    public interface HttpMessage {
      HttpHeadersgetHeaders();
    }

    HttpMessage提供的方法是读取头部中的信息。

    Spring中内置的一部分HttpMessageConverter

    1. FormHttpMessageConverter
        支持 MultiValueMap 类型, 并且 MediaType 类型是 "multipart/form-data", 从 InputStream 里面读取数据, 并通过&符号分割, 最后转换成 MultiValueMap, 或 将 MultiValueMap转换成 & 符号连接的字符串, 最后转换成字节流, 输出到远端
    2. BufferedImageHttpMessageConverter
        支持 BufferedImgae 的 HttpMessageConverter, 通过 ImageReader 将 HttpBody 里面的数据转换成 BufferedImage, 或ImageWriter 将ImageReader 转换成字节流输出到 OutputMessage
    3. StringHttpMessageConverter
        支持数据是 String 类型的, 从 InputMessage 中读取指定格式的 str, 或 将数据编码成指定的格式输出到 OutputMessage
    4. SourceHttpMessageConverter
        支持 DOMSource, SAXSource, StAXSource, StreamSource, Source 类型的消息转换器, 在读取的时候, 从 HttpBody 里面读取对应的数据流转换成对应对应, 输出时通过 TransformerFactory 转换成指定格式输出
    5. ResourceHttpMessageConverter
        支持数据类型是 Resource 的数据, 从 HttpBody 中读取数据流转换成 InputStreamResource|ByteArrayResource, 或从 Resource 中读取数据流, 输出到远端
    6. ProtobufHttpMessageConverter
        支持数据类型是 com.google.protobuf.Message, 通过 com.google.protobuf.Message.Builder 将 HttpBody 中的数据流转换成指定格式的 Message, 通过 ProtobufFormatter 将 com.google.protobuf.Message 转换成字节流输出到远端
    7. ObjectToStringHttpMessageConverter
        支持 MediaType是 text/plain 类型, 从 InputMessage 读取数据转换成字符串, 通过 ConversionService 将字符串转换成自定类型的 Object; 或将 Obj 转换成 String, 最后 将 String 转换成数据流
    8. ByteArrayHttpMessageConverter
        支持格式是 byte 类型, 从 InputMessage 中读取指定长度的字节流, 或将 OutputMessage 转换成字节流
    9. AbstractXmlHttpMessageConverter及其子类
        支持从 xml 与 Object 之间进行数据转换的 HttpMessageConverter
    10. AbstractGenericHttpMessageConverter
        支持从 Json 与 Object 之间进行数据转换的 HttpMessageConverter (PS: 主要通过 JackSon 或 Gson)
    11. GsonHttpMessageConverter
        支持 application/*++json 格式的数据, 并通过 Gson, 将字符串转换成对应的数据
    12. MappingJackson2XmlHttpMessageConverter
        持 application/*++json/*+xml 格式的数据, 并通过 JackSon, 将字符串转换成对应的数据

    HttpMessageConverter 在整个 SpringMVC 中起着根据 MediaType 类型将 HttpServletRequest 中的数据转换成 指定对象的转换器, 或将对象转换成指定格式的数据(PS: byte/String/xml/json 等);

    自定义HttpMessageConverter

    1.通过继承 AbstractHttpMessageConverter自定义HttpMessageConverter

    配置自定义HttpMessageConverter

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        <!--spring可以自动去扫描base-pack下面的包或者子包下面的java文件,
        如果扫描到有Spring的相关注解的类,则把这些类注册为Spring的bean-->
        <context:component-scan base-package="com.wen.controller"/>
        <!--设置默认的Servlet来响应静态文件-->
        <mvc:default-servlet-handler/>
        <!--设置配置方案,会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean-->
        <mvc:annotation-driven>
            <!--设置不使用默认的消息转换器-->
            <mvc:message-converters register-defaults="false">
                <!--配置Spring的转换器-->
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
                <!--配置fastjson中实现HttpMessageConverter接口的转换器-->
                <!--FastJsonHttpMessageConverter是fastjson中实现了HttpMessageConverter接口的类-->
                <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                    <!--加入支持的媒体类型:返回contentType-->
                    <property name="supportedMediaTypes">
                        <list>
                            <!--这里顺序一定不能写反,不然IE会出现下载提示-->
                            <value>text/html;charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
        <!--视图解析器-->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/pages/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
  • 相关阅读:
    C#调用VC++.net托管库程序集DLL
    SQL Server 2008 评估期已过期解决办法
    TFS2010安装(转)
    将dll添加到GAC(Global Assembly Cache)中
    LINQ to SQL with NOLOCK
    SQL Server 2008创建定期自动备份任务(转)
    问题解决记录(一)
    控制台读入
    数据库
    a标签的onclick与href的执行顺序
  • 原文地址:https://www.cnblogs.com/deityjian/p/11498749.html
Copyright © 2011-2022 走看看