### 准备

## 目标

了解 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.Message;fromMessage 方法将消息转化为 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[] 类型。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Spring AMQP 源码分析 03 - MessageConverter的更多相关文章

  1. Spring AMQP 源码分析 07 - MessageListenerAdapter

    ### 准备 ## 目标 了解 Spring AMQP 如何用 POJO 处理消息 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相 ...

  2. Spring AMQP 源码分析 08 - XML 配置

    ### 准备 ## 目标 通过 XML 配置文件使用 Spring AMQP ## 前置知识 <Spring AMQP 源码分析 07 - MessageListenerAdapter> ...

  3. Spring AMQP 源码分析 06 - 手动消息确认

    ### 准备 ## 目标 了解 Spring AMQP 如何手动确认消息已成功消费 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相 ...

  4. Spring AMQP 源码分析 05 - 异常处理

    ### 准备 ## 目标 了解 Spring AMQP Message Listener 如何处理异常 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListene ...

  5. Spring AMQP 源码分析 02 - CachingConnectionFactory

    ### 准备 ## 目标 了解 CachingConnectionFactory 在默认缓存模式下的工作原理   ## 前置知识   <Spring AMQP 源码分析 01 - Impatie ...

  6. Spring AMQP 源码分析 04 - MessageListener

    ### 准备 ## 目标 了解 Spring AMQP 如何实现异步消息投递(推模式) ## 前置知识 <RabbitMQ入门_05_多线程消费同一队列> ## 相关资源 Quick To ...

  7. Spring AMQP 源码分析 01 - Impatient

    ### 准备   ## 目标 了解 Spring AMQP 核心代码   ## 前置知识 RabbitMQ 入门   ## 相关资源   Quick Tour for the impatient:&l ...

  8. Spring Security 源码分析(四):Spring Social实现微信社交登录

    社交登录又称作社会化登录(Social Login),是指网站的用户可以使用腾讯QQ.人人网.开心网.新浪微博.搜狐微博.腾讯微博.淘宝.豆瓣.MSN.Google等社会化媒体账号登录该网站. 前言 ...

  9. spring事务源码分析结合mybatis源码(一)

    最近想提升,苦逼程序猿,想了想还是拿最熟悉,之前也一直想看但没看的spring源码来看吧,正好最近在弄事务这部分的东西,就看了下,同时写下随笔记录下,以备后查. spring tx源码分析 这里只分析 ...

随机推荐

  1. git的使用(包括创建远程仓库到上传代码到git的详细步骤以及git的一些常用命令)

    A创建远程仓库到上传代码到git 1)登陆或这注册git账号 https://github.com 2)创建远程仓库 3)打开终端输入命令 cd到你的本地项目根目录下,执行如下git命令 git in ...

  2. 使用 MtVerify.h头文件 ,用的时候把他头文件的内容添加到项目

    #include <windows.h>  //windodws变量相关头文件 MtVerify.h的内容如下:#pragma comment( lib, "USER32&quo ...

  3. 【安装vsftpd】安装vsftpd工具步骤

    1 安装vsftpd组件 [root@bogon ~]# yum -y install vsftpd 安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件. 2 添 ...

  4. explain查看sql执行计划

    http://www.cnblogs.com/wolf-sun/p/5291563.html 一该命令作用:该命令会向您展示查询是如何被执行的. 1.各个项的含义:https://blog.csdn. ...

  5. 解决fiddler不能抓取eclipse发出接口请求的问题

    使用eclipse执行接口时,发现在fiddler里面抓不到这些请求. 网上找了很多资料都是让在Eclipse 中设置:Windows > Preferences > Java > ...

  6. mysql备份恢复详解

    前言 为什么需要备份数据? 数据的备份类型 MySQL备份数据的方式 备份需要考虑的问题 设计合适的备份策略 实战演练 使用cp进行备份 使用mysqldump+复制BINARY LOG备份 使用lv ...

  7. 基于Spring Cloud的微服务落地

    微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的微服务 ...

  8. ajax原理和XmlHttpRequest对象

    Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.这其中最关键的一步就是从服务器获得请求数据.要清楚这 ...

  9. EF 一个实体对象不能由多个 IEntityChangeTracker 实例引用 解决办法

    在DAL层中,建立工厂类 namespace DAL { public static class SysDbContextFactory { /// <summary> /// 从Http ...

  10. 探索Java8:Stream的使用

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达 ...