• Spring AMQP 源码分析 03


    ### 准备

    ## 目标

    了解 Spring AMQP 消息转化实现
     

    ## 相关资源

     
    Sample code:<https://github.com/gordonklg/study>,rabbitmq module
     

    ## 测试代码

    gordon.study.rabbitmq.springamqp.JsonMessage.java

     

    ### 分析

    ## MessageConverter

    org.springframework.amqp.support.converter.MessageConverter 接口负责消息转化,有两个方法:toMessage 方法将 Java 对象转化为 org.springframework.amqp.core.MessagefromMessage 方法将消息转化为 Java 对象。

    Message 类是 Spring AMQP 对消息的封装,其 byte[] body 属性代表消息内容,MessageProperties messageProperties 属性代表消息属性。
     
    RabbitTemplate 类持有 MessageConverter 的引用,用来帮助 RabbitTemplate 处理 Message 与 Java 对象之间的转化。
     

    ## Jackson2JsonMessageConverter

    org.springframework.amqp.support.converter.Jackson2JsonMessageConverter 通过 Jackson 2.x 版本进行 Java 对象(POJOs)与 JSON 格式内容之间的转化。
     
    toMessage 方法实现逻辑:
    1. 通过 ObjectMapper 将 Java 对象转化为 JSON 字符串,再将字符串转为 byte[]
    2. 设置 MessageProperties,contentType 设为 application/json,contentEncoding 设为 UTF-8,contentLength 设为 byte[] 长度
    3. 向 MessageProperties 的 headers 属性中添加 __TypeId__,其值为 Java 对象的类全名
     
    调试中截取的 Message 实际值为: 
    (Body:'{"name":"Gordon","birthday":1498024107659,"tall":172}' MessageProperties [headers={__TypeId__=gordon.study.rabbitmq.springamqp.Student}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=application/json, contentEncoding=UTF-8, contentLength=53, deliveryMode=PERSISTENT, receivedDeliveryMode=null, expiration=null, priority=0, redelivered=null, receivedExchange=null, receivedRoutingKey=null, receivedDelay=null, deliveryTag=0, messageCount=null, consumerTag=null, consumerQueue=null])
    其中 deliveryMode 默认值为 PERSISTENT(即默认持久化),这是 MessageProperties 定义的默认值
     
    fromMessage 方法实现逻辑:
    1. 如果入参 Message 对象的 MessageProperties 属性为 null,或者消息属性 contentType 值既不为空又不包含 json 关键字,则直接返回 Message 的 body (byte[])
    2. 从 MessageProperties 的 headers 属性中读出 __TypeId__ 的值,通过 Jackson 的 API 将之转化为 JavaType 对象,再将 message body 转化为 Java 对象
     
    调试中截取的 Message 实际值为: 
    (Body:'{"name":"Gordon","birthday":1498032689741,"tall":172}' MessageProperties [headers={__TypeId__=gordon.study.rabbitmq.springamqp.Student}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=application/json, contentEncoding=UTF-8, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=spring, receivedDelay=null, deliveryTag=1, messageCount=0, consumerTag=null, consumerQueue=null])
     

    ## MessagePropertiesConverter

    我们发现前面调试中截取的 Message 实际值在 send 与 receive 方法中并不完全相同。这是因为 RabbitMQ 中定义的 BasicProperties 只是 Spring AMQP 中定义的 MessageProperties 的一个子集,例如 contentLength 并不是 BasicProperties 的属性,所以 receive 方法读取出来的消息默认是不会有 contentLength 值得(因为存不到 RabbitMQ 里面)。
     
    org.springframework.amqp.rabbit.support.MessagePropertiesConverter 接口就是用来提供 Spring AMQP MessageProperties 与 RabbitMQ BasicProperties 之间的转化策略的。
     
    Spring AMQP 中提供了 org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter 实现 MessagePropertiesConverter 接口。细节可以查看以下方法的实现:
     

    ## SimpleMessageConverter

    RabbitTemplate 默认使用 org.springframework.amqp.support.converter.SimpleMessageConverter 作为自己的消息转化器。SimpleMessageConverter 支持字符串、序列化对象和字节数组三种类型。
     
    SimpleMessageConverter 的 toMessage 方法根据传入 Java 对象的类型设置 contentType 并将对象转化为 byte[],支持以下 Java 类型:
    • byte[]:contentType 设置为 application/octet-stream
    • String:contentType 设置为 text/plain
    • Serializable:contentType 设置为 application/x-java-serialized-object,body 为对象序列化得到的 byte[]
    • other:contentType 为 MessageProperties 默认值 application/octet-stream,body 为 null。RabbitMQ 可以发送 body 为 null 的消息
     
    而 fromMessage 方法也会根据消息的 contentType 决定如何解析消息体,确定方法最终返回的对象类型。如果 contentType 以 text 开头的,则将 body 转化为字符串;如果 contentType 为 application/x-java-serialized-object,则将 body 反序列化为对象;其它情况直接返回 byte[] 形式的 body。
     
    由于通过 Jackson2JsonMessageConverter 发布的消息的 contentType 为 application/json,所以通过 SimpleMessageConverter 获取到的消息的消息体是 byte[] 类型。
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    关于10053 trace中的UNCOMPBKTS和ENDPTVALS
    12c新特性
    ORA600:[ksnpost:ksnigb]错误一例
    RAC CRS Resource资源的生命周期
    Windows上如何禁用TCP/IP自动调优特性
    11g新特性
    Exadata V2 OracleSun Database Machine数据库一体机
    Script:verify Oracle Object timestamp discrepancy
    Grid Control OMS Agent代理工作原理图
    Android 编程下报错 Exception raised during rendering: java.util.LinkedHashMap.eldest()Ljava/util/Map$Entry;
  • 原文地址:https://www.cnblogs.com/gordonkong/p/7066613.html
Copyright © 2020-2023  润新知