MQ-消息转换器

一、默认转换器存在问题

  在 SpringAMQP 的发送方法中,接收消息的类型是 Object,也就是说我们可以发送任意对象类型的消息,Spring 会帮我们序列化为字节后发送给 MQ,接收消息的时候,还会把字节反序列化为 Java 对象
  只不过,默认情况下 Spring 采用的序列化方式是 JDK 序列化。众所周知,JDK 序列化存在下列问题:

  • 数据体积过大
  • 有安全漏洞
  • 可读性差

二、测试默认转换器

1.声明队列

  因为我们向在 mq 客户端看到消息,所以我们在 consumer 配置类中利用 @Bean 的方式声明一个队列:

package cn.itcast.mq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 温柔哥
 * @create 2024-02-02 10:25
 */
@Configuration
public class FanoutConfig {
    // 测试默认转换器
    @Bean
    public Queue objectQueue() {
        return new Queue("object.queue");
    }
}

  启动 consumer 服务,查看 mq 客户端声明队列是否成功

在这里插入图片描述

2.测试发送者发消息

  使用 Map 对象当作消息发送到队列 object.queue

// 测试转换器
@Test
public void testSendObjectQueue() {
    Map<String, Object> message = new HashMap<>();
    message.put("name", "gentlebrother");
    message.put("age", 22);
    rabbitTemplate.convertAndSend("object.queue", message);
}

运行该测试类,到 mq 客户端查看消息

3.分析结果

  可以看到,消息内容变成了一大长串的字符串,根本看不懂是什么。
  然后再看一下 content_type(消息类型)为 java 序列化,这时再想一下,rabbitmq 只支持字节类型的消息,而 SpringAMQP 却允许我们发送 Object 对象类型的消息,这就说明了 Spring 会将我们的对象做序列化。
  默认用的序列化方式就是 jdk 的序列化,但是我们知道 ObjectOutputStream 这种序列化有很多缺点,第一是性能比较差,第二是安全性有问题,容易出现注入的问题,第三是数据长度也太长了,消息体越大,消息传送速度越慢,还占用额外的内存空间
在这里插入图片描述

三、配置JSON转换器

  Spring 的对消息对象的处理是由 org.springframework.amqp.support.converter.MessageConverter 来处理的。而默认实现是 SimpleMessageConverter,基于 JDK 的 ObjectOutputStream 完成序列化。
  如果要修改只需要定义一个 MessageConverter 类型的 Bean 即可。推荐用 JSON 方式序列化,步骤如下:

1.引入依赖

  因为无论是消费者需要反序列化为 java 对象,还是发送者需要进行序列化,都需要使用 jackon 的依赖,故我们直接在父工程中引入依赖:

<!-- jackson 依赖-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

2.在publisher服务声明bean

  我们在 publisher 服务声明 MessageConverter,因为启动类也是一个配置类,所以我们直接在 publisher 服务的启动类声明即可

package cn.itcast.mq;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class PublisherApplication {
    public static void main(String[] args) {
        SpringApplication.run(PublisherApplication.class);
    }

	// 配置JSON转换器
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

3.测试发送消息是否JSON序列化成功

  首先到 mq 客户端将 object.queue 队列中的之前的消息清空

在这里插入图片描述

  运行之前写好的测试发送者发送消息的方法,重新发送消息,可以看到发送的消息成功转换成 JSON 格式

在这里插入图片描述

4.在consumer服务声明bean

  直接在 consumer 服务的启动类声明即可

package cn.itcast.mq;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    // 配置JSON转换器
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

5.定义一个消费者

  定义一个消费者,监听 object.queue 队列并消费消息,消息类型和我们发送消息使用的类型一样,都是 Map 类型

package cn.itcast.mq.listener;

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author 温柔哥
 * @create 2024-02-01 16:01
 */
@Component
public class SpringRabbitListener {
    // 测试转换器
    @RabbitListener(queues = "object.queue")
    public void listenObjectQueue1(Map<String, Object> message) {
        System.out.println("消费者接受到 object.queue 的消息:【" + message + "】");
    }
}

  重启 consumer 服务,查看控制台消息,可以看到已经将消息反序列化为了 java 对象

在这里插入图片描述

四、总结

  SpringAMQP中消息的序列化和反序列化是怎么实现的?

利用MessageConverter实现的,默认是JDK的序列化
注意发送方与接收方必须使用相同的MessageConverter

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值