### 准备

## 目标

了解 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. centos迷你版,没有安装ifconfig命令

    ifconfig命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息,可是有些时候最小化安装CentOS等Linux发行版的时候会默认不安装ifconfig等命令,这时候你进入终端,运行ifc ...

  2. 【转】编程思想之多线程与多进程(3)——Java中的多线程

    <编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程>一文详细讲述了线程.进程的关系及在操作系统中的表现,这是多线程学习必须了解的基础.本文将接着讲一下Java中多线程程序的 ...

  3. linux常用命令:lsof 命令

    lsof(list open files) 是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以 如传输控制 ...

  4. quartz-job实现实时或定时发送短信任务

    存放调度器(Job 和 Trigger)信息的xml配置文件: 这是某个指定的要实现的定时任务: <!-- 每天给项目经理发送短信避免短信服务挂了 定时每天08:30执行--> <j ...

  5. Bootstrap+AngularJS对话框实例

    <script type="text/javascript" src="/assets/JS/plugins/jquery.min.js">< ...

  6. win7 安装.Net framework 4.0出现 安装不成功,错误代码0x80240037 的解决方法

    1.安装说明 系统:win7 64位 安装包:dotNetFx40_Full_x86_x64.exe(.Net framework 4.0) 出现的问题:在win7 上安装dotNetFx40_Ful ...

  7. jQuery 概述

    jQuery 概述 版权声明:未经博主授权,内容严禁分享转载! 什么是 JavaScript 类库 JavaScript 类库是指已经被封装好的一系列 JavaScript 函数,能够实现一些特定的功 ...

  8. 20145317 网络对抗技术 逆向与Bof基础

    20145317 网络对抗技术 逆向与Bof基础 实践要求 1. 掌握NOP,JNE,JE,JMP,CMP汇编指令的机器码 2. 掌握反汇编与十六进制编程器 3. 能正确修改机器指令改变程序执行流程 ...

  9. Linxu内核版本号后面多出字符串或者+号【学习笔记】

    作者:庄泽彬 之前一直没有留意到但是最近在编译内核的时候版本号竟然多出了个加号+号或字符串, 后面终于找到原因了,原来config如果设置了CONFIG_LOCALVERSION_AUTO=y,内核的 ...

  10. P1471 方差

    题目 luogu 思路 \[\frac{1}{n}*\sum_{1}^{n}( a_{i}-A)^{2}\] \[\frac{1}{n}*\sum_{1}^{n}( a_{i}^2-2*A*a_{i} ...