zoukankan      html  css  js  c++  java
  • Spring 消息转换器和注解控制器

    1、什么是消息转换器?

    @RequestBody 和 @ResponseBody 两个注解,分别完成请求报文到对象和对象到响应报文的转换。
    底层这种灵活的消息转换机制,就是 Spring3.x 中新引入的 HttpMessageConverter,即消息转换器机制。
    而负责这种机制的主要接口HttpMessageConverter及其各种子类(StringHttpMessageConverter等),就是消息转换器。

    2、消息转换器结构:HttpMessageConverter

    消息转换器的结构如下图

    • HttpInputMessage 这个接口是 SpringMVC 内部对一次 Http 请求报文的抽象
    • HttpOutputMessage 这个接口是 SpringMVC 内部对一次 Http 响应报文的抽象
    • HttpMessageConverter 这个接口对消息转换器最高层次的接口抽象
    • 其read()方法接收 HttpInputMessage 作为入参,负责读取请求报文
      • canRead()方法负责判断请求报文是否可以由该消息转换器处理
    • 其 write()方法接收 HttpOutputMessage 作为入参,负责将数据写入响应报文
      • canWrite()方法负责判断响应报文是否可以由该消息转换器处理

    接口说明见图:

    接口说明

    请求处理流程见图:

    流程说明

    3、Spring 调用逻辑

    3.1 HandlerMethodArgumentResolver 接口 和 HandlerMethodReturnValueHandler 接口

    这两个接口只是声明,定义一些方法。具体的实现才是最终处理。

    • HandlerMethodArgumentResolver 是将请求报文绑定到处理方法形参的策略接口
    • HandlerMethodReturnValueHandler 是对处理方法返回值进行处理的策略接口。

    3.2 RequestResponseBodyMethodProcessor 类

    • 该类同时实现了HandlerMethodArgumentResolver 接口 和 HandlerMethodReturnValueHandler 接口。所以充当了方法参数解析和返回值处理两种角色 。

    3.2.1 对 HandlerMethodArgumentResolver 接口的实现 ( resolveArgument()方法)

    • 实现可以见源码,这里只说明观看逻辑。
      • 依次进入:resolveArgument()方法→readWithMessageConverters()方法→super.readWithMessageConverters()方法
      • 然后可以看到先调用HttpMessageConverter的canRead()方法,校验通过后调用read()方法。

    3.2.2 对 HandlerMethodReturnValueHandler 接口的实现 ( handleReturnValue()方法)

    • 实现可以见源码,这里只说明观看逻辑。
      • 依次进入:handleReturnValue()方法→writeWithMessageConverters()方法[参数不同]→writeWithMessageConverters()方法[参数不同]
      • 然后可以看到先调用HttpMessageConverter的canWrite()方法,校验通过后调用write()方法。

    4、HttpMessageConverter子类及其在SpringMVC中的使用

    以我们代码中的一个配置作为说明,并具体理解这个加载过程:

    <mvc:annotation-driven>
        <mvc:message-converters>
            <ref bean="fastJsonHttpMessageConverter"/>
            <ref bean="sourceHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>
     
    <bean id="sourceHttpMessageConverter"
          class="org.springframework.http.converter.xml.SourceHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>application/xml;charset=UTF-8</value>
                <value>text/xml;charset=UTF-8</value>
            </list>
        </property>
    </bean>
     
    <bean id="fastJsonHttpMessageConverter"
          class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    

    4.1 注解的解析(注解控制器)及加载HttpMessageConverter

    主要参考文章: SpringMVC关于json、xml自动转换的原理研究-附带源码分析 - format丶 - 博客园

    对于注解的解析:<mvc:annotation-driven/>。该解析由类org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParserparse()方法处理。

    • 源码路径:AnnotationDrivenBeanDefinitionParser类→parse()方法→getMessageConverters()方法。
      • 源码中可知,如果没有配置<mvc:message-converters>属性,则加载默认的HttpMessageConverter。
        • 默认的有4个基础的,和5个需要条件再加载的。(这部分不做说明,不属于本文内容)
      • 如果配置了,则只加载配置的HttpMessageConverter

    如同上述配置,则只会加载两个sourceHttpMessageConverterfastJsonHttpMessageConverter

    4.2 HttpMessageConverter的supportedMediaTypes属性作用

    我们配置了多个HttpMessageConverter,而每个HttpMessageConverter可以处理哪些类型的请求则由supportedMediaTypes属性定义(不止该属性,但也是一部分)
    这部分的具体使用在:

    • 读部分参考【3.2.1】,找到canRead方法的调用地方之后,我们看canRead方法的实现。
      • 以FastJsonHttpMessageConverter为例,它的canRead方法实现实际调用的时父类(AbstractHttpMessageConverter)的canRead方法实现
        • 父类的实现如下,可以看到有对supportedMediaType的过滤

    至此,我们可以确定,XML的配置中的supportedMediaTypes会音响该消息转换器可以处理的请求。以上述配置为例,sourceHttpMessageConverter负责处理XML数据格式的请求;fastJsonHttpMessageConverter处理json格式的请求。

    canWrite方法也会用到supportedMediaTypes,可以自行梳理。至此,消息转换器的配置以及生效过程就比较清晰了。

    5、参考:

    1. SpringMVC 源码剖析(五)- 消息转换器 HttpMessageConverter - 相见欢的个人空间 - OSCHINA
      注:本篇博客就是该文章的翻版,所以原文很重要。
    2. SpringMVC关于json、xml自动转换的原理研究-附带源码分析 - format丶 - 博客园
      注:对配置的生效过程说明很详细,可以参考。
    3. Spring MVC 解读—— - Don't worry, Loser. - OSCHINA
      注:对于Spring XML配置的解析说明很清楚。重点: 标签解析都是由BeanDefinitionParser接口的子类来完成的。还有对于AnnotationDrivenBeanDefinitionParser 的详细解析。
    4. springMVC的消息转换器(Message Converter) - 简书
      注:对于自定义消息转换器说明很棒,源码说明也不错。
    5. SpringMVC HttpMessageConverter 匹配规则 - - SegmentFault 思否
      注:匹配规则,很深奥看不懂的感觉,后续再看。
  • 相关阅读:
    Jersey Politics
    网络流——最小费用最大流
    网络流——最大流Dinic算法
    【洛谷2756】飞行员配对方案问题(二分图匹配,网络流24题)
    状压dp入门
    2018九江市赛
    [CQOI2007]余数求和
    CSAPC2008 skyline
    [ZJOI2009]函数 题解
    由不定方程想到的——数论选讲
  • 原文地址:https://www.cnblogs.com/buwuliao/p/11859103.html
Copyright © 2011-2022 走看看