rabbitmq的安装使用及spring amqp的使用

同步调用与异步调用

  • 同步调用:时效性很强,feign调用方式是是同步调用
    • 耦合度高
    • 性能下降
    • 资源浪费
    • 级联失败
  • 异步调用方案,事件驱动模式:通过发布、订阅事件实现
    • 服务解耦
    • 性能提升、吞吐量高
    • 服务没有强依赖、不担心级联失败问题
    • 资源浪费失败
    • 流量削峰

MQ(MessageQueue)

  • 相当于事件驱动架构中的Broker
  • 常用mq技术:

在这里插入图片描述

RabbitMQ下载安装

  • 官网:https://www.rabbitmq.com/

  • channel: 操作mq的工具

  • exchange: 路由消息到队列中

  • queue: 缓存消息

  • virtual host: 虚拟主机,是对queue、exchange等资源的逻辑分组

  • erlang下载地址:https://www.rabbitmq.com/documentation.html

  • rabbitmq下载:https://www.rabbitmq.com/install-windows.html

  • erlang 配置环境遍历

    • 新建ERLANG_HOME 值为erlang安装地址
    • 在Path中添加 %ERLANG_HOME%\bin

在这里插入图片描述

  • rabbitmq
    • 环境遍历添加RABBITMQ_SERVER 值为
    • Path添加%RABBITMQ_SERVER%\sbin
    • 安装rabbit管理插件命令 rabbitmq-plugins enable rabbitmq_management
net start RabbitMQ  启动
net stop RabbitMQ  停止
rabbitmqctl status  查看状态
健康检查: rabbitmqctl status
启动监控管理器:rabbitmq-plugins enable rabbitmq_management
关闭监控:rabbitmq-plugins disable rabbitmq_management
停止服务:rabbitmq-service stop
启动服务:rabbitmq-service start
重启命令:net stop RabbitMQ && net start
帮助命令:rabbitmqctl help
rabbitmqctl list_queues查看所有队列
rabbitmqctl reset清除所有队列
rabbitmqctl list_exchanges查看所有交换器
rabbitmqctl add_user username password添加用户
rabbitmqctl set_user_tags username administrator分配角色
rabbitmqctl list_bindings 查看交换器和队列的绑定关系
  • 注意:erlang和rabbitmq是有版本要求的,最好不要用最新的,可能会有坑

在这里插入图片描述

在这里插入图片描述

  • 访问地址:http://127.0.0.1:15672/

在这里插入图片描述

在这里插入图片描述

  • 一般这个东西都会在linux系统上,会在linux上安装,如果会docker,可以直接docker安装更方便一点

rabbitmq创建用户及分配权限

在这里插入图片描述

在这里插入图片描述

1、超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
2、监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
3、策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
4、普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
5、其他
无法登陆管理控制台,通常就是普通的生产者和消费者。

在这里插入图片描述

rabbitmq实现简单消息模型案例

  • 新建一个mq-demo父工程、在创建publisher、consumer子工程

在这里插入图片描述

  • 依赖
    • springboot版本管理有两种方式一种是spring-boot-dependencies, 一般都配置在父工程中,子工程可继承父工程的版本
    • 另外一种是spring-boot-parent,一般都配置在父工程中,子工程可继承父工程的版本
 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring-boot-dependencies.version>2.3.12.RELEASE</spring-boot-dependencies.version>
    <spring-boot-starter-test.version>2.3.12.RELEASE</spring-boot-starter-test.version>
    <lombok.version>1.18.20</lombok.version>
    <spring-boot-starter-amqp.version>2.3.12.RELEASE</spring-boot-starter-amqp.version>
    <amqp-client.version>5.9.0</amqp-client.version>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${spring-boot-dependencies.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>${spring-boot-starter-test.version}</version>
      </dependency>

      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>${spring-boot-starter-amqp.version}</version>
      </dependency>

      <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>${amqp-client.version}</version>
      </dependency>

    </dependencies>
  </dependencyManagement>

  • 简单消息模式例子参考:https://www.rabbitmq.com/getstarted.html (网上很多例子,卸不下来copy一个看看,下面的puhlisher、consumer是我从网上copy下来的,改一改ip地址和用户名及密码)

在这里插入图片描述

  • 生产者
package com.konglz.publisher.test;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @description: 简单模式Simple
 */
public class Producer {


    public static void main(String[] args) {

        // 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
        // ip port

        // 1: 创建连接工程
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.0.114");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("klz");//rabbitmq登录的账号
        connectionFactory.setPassword("klz");//rabbitmq登录的密码
        connectionFactory.setVirtualHost("/");

        //springboot ---rabbitmq

        Connection connection = null;
        Channel channel = null;
        try {
            // 2: 创建连接Connection Rabbitmq为什么是基于channel去处理而不是链接? 长连接----信道channel
            connection = connectionFactory.newConnection("生产者");
            // 3: 通过连接获取通道Channel
            channel = connection.createChannel();
            // 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息
            String queueName = "queue1";

            /*
             * @params1 队列的名称
             * @params2 是否要持久化durable=false 所谓持久化消息是否存盘,如果false 非持久化 true是持久化? 非持久化会存盘吗? 会存盘,但是会随从重启服务会丢失。
             * @params3 排他性,是否是独占独立
             * @params4 是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
             * @params5 携带附属参数
             */
            channel.queueDeclare(queueName, true, false, false, null);
            // 5: 准备消息内容
            String message = "Hello rabbitmq!!!";
            // 6: 发送消息给队列queue
            // @params1: 交换机  @params2 队列、路由key @params 消息的状态控制  @params4 消息主题
            // 面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机。
            channel.basicPublish("", queueName, null, message.getBytes());

            System.out.println("消息发送成功!!!");
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            // 7: 关闭通道
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            // 8: 关闭连接

            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

  • 消费者
package com.konglz.consumer.test;

import com.rabbitmq.client.*;
import java.io.IOException;

public class Consumer {


    public static void main(String[] args) {

        // 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
        // ip port

        // 1: 创建连接工程
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.0.114");//服务器IP
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("klz");
        connectionFactory.setPassword("klz");
        connectionFactory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;
        try {
            // 2: 创建连接Connection
            connection = connectionFactory.newConnection("消费者");
            // 3: 通过连接获取通道Channel
            channel = connection.createChannel();
            // 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息


            // true = ack 正常的逻辑是没问题 死循环 rabbit 重发策略
            // false = nack 消息这在消费消息的时候可能会异常和故障
            final  Channel channel2 = channel;
            channel2.basicConsume("queue1", false, new DeliverCallback() {
                public void handle(String consumerTag, Delivery message) throws IOException {
                    try {
                        System.out.println("收到消息是" + new String(message.getBody(), "UTF-8"));
                        channel2.basicAck(message.getEnvelope().getDeliveryTag(),false);
                    }catch (Exception ex){
                        ex.printStackTrace();
                        // 三次确认 -- reject + sixin
                    }

                }
            }, new CancelCallback() {
                public void handle(String consumerTag) throws IOException {
                    System.out.println("接受失败了...");
                }
            });

            System.out.println("开始接受消息");
            System.in.read();

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            // 7: 关闭通道
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            // 8: 关闭连接

            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

AMQP

  • AMQP(advanced message queuing protocol)
  • Spring AMQP是一个模板

Spring AMQP实现简单消息模型

在这里插入图片描述

  • spring AMQP是spring对rabbit做的封装,提供的模板工具,使用起来很方便

  • 依赖(生产者、消费者都要引入)

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
      </dependency>
  • 生产者(写在测试模块)
package com.konglz.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void test1(){
        String queueName = "queue1";
        String message = "hello world i am spring amqp";
        rabbitTemplate.convertAndSend(queueName,message);
    }

}
  • 消费者(写完之后运行这个服务)
package com.konglz.consumer.test;

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

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {
    //注意这个queues的名称对应rabbitmq队列的名称,和生产者那边的队列名称一样
    @RabbitListener(queues = "queue1")
    public void springRabbitListener(String message){
        System.out.println("消费者接收到的消息:" + message);
    }
}

在这里插入图片描述

Spring AMQP实现工作消息模型

在这里插入图片描述

  • publisher:下面这段关于工作队列代码可能会报错,报没有这个队列名称的异常,这个时候我们可以手动的在rabbitmq总新建一个同名队列,或者使用代码创建同名队列
package com.konglz.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void test1(){
        String queueName = "queue1";
        String message = "hello world i am spring amqp";
        rabbitTemplate.convertAndSend(queueName,message);
    }
    
    @Test
    void workQueue() throws InterruptedException {
        String queueName = "workQueue";
        String message = "hello world i am spring amqp__";
        for(int i = 0; i < 100; i++){
            rabbitTemplate.convertAndSend(queueName,message+i);
            Thread.sleep(20);
        }
    }
}

在这里插入图片描述

  • Consumer:两个消费者的睡眠事件不要设置一样,一个大一个小,要不可能是一个消费者接受了所有信息
package com.konglz.consumer.test;

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

import java.time.LocalDateTime;

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {
    //注意这个queues的名称对应rabbitmq队列的名称,和生产者那边的队列名称一样
    @RabbitListener(queues = "queue1")
    public void springRabbitListener(String message){
        System.out.println("消费者接收到的消息:" + message);
    }

    @RabbitListener(queues = "workQueue")
    public void listenerWorkQueueConsumer1(String message) throws InterruptedException {
        System.out.println("=====消费者1接收到的消息:" + message + LocalDateTime.now());
        Thread.sleep(20);
    }

    @RabbitListener(queues = "workQueue")
    public void listenerWorkQueueConsumer2(String message) throws InterruptedException {
        System.err.println("=====费者2接收到的消息:" + message + LocalDateTime.now());
        Thread.sleep(200);
    }
}

在这里插入图片描述

Spring AMQP实现发布、订阅消息模型(Fanout)

  • 发布订阅模式与之前的区别是允许将同一消息发送给多个消费者。通过交换机实现

  • exchange(交换机),路由转发消息时可能会失败,造成消息丢失

    • Fanout: 广播
    • Direct: 路由
    • Topic:话题
  • 交换机绑定队列: 注意不要忘记加@Bean注解

    • @Configuration: 相当于,@Bean用在加了@Configuration的类内,是从Spring单例池中拿对象,而不是每次新new一个类对象出来
    • @Bean:相当于,告诉我们方法会返回一个对象,这个对象要注册为Spring应用上下文中的bean,@Bean 需要在配置类中使用,即类上需要加上@Configuration注解
    • @Component:表明一个类会作为组件类,并告知Spring要为这个类创建bean,@Bean用在加了@Component的类内,,不是从Spring单例池中拿对象,而是每次新new一个类对象出来

在这里插入图片描述

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

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 15:32
 */
@Configuration
public class FanoutConfig {
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("konglz.fanout");
    }

    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanoutQueue1");
    }

    @Bean
    public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue1)
                .to(fanoutExchange);
    }

    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanoutQueue2");
    }

    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue2)
                .to(fanoutExchange);
    }

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 消费者
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {

    @RabbitListener(queues = "fanoutQueue1")
    public void fanoutQueue1(String message){
        System.out.println("fanoutQueue1消费者接收到的消息:" + message);
    }

    @RabbitListener(queues = "fanoutQueue2")
    public void fanoutQueue2(String message){
        System.out.println("fanoutQueue2消费者接收到的消息:" + message);
    }
}
  • 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void fanout(){
        String exchangeName = "konglz.fanout";
        String message = "今日有雨,请带伞!";
        //通过交换机与队列的绑定关系,将消息发送给每一个消费者
        rabbitTemplate.convertAndSend(exchangeName,"",message);
    }

}

在这里插入图片描述

Spring AMQP实现发布、订阅消息模型(Direct)

  • 将消息更加规则路由到指定Queue,常被称为路由模式

  • 每一个Queue都与Exchange设置一个BindKey

  • 发送消息时指定RoutingKey

  • Exchang将消息路由到BindingKey与RoutingKey一样的队列

  • 绑定关系

在这里插入图片描述

  • 消费者:通过@RabbitListener注解绑定交换机、队列、routingKey,可以根据提示写绑定关系

在这里插入图片描述

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "directQueue1"),
            exchange = @Exchange(name = "konglz.direct",type = ExchangeTypes.DIRECT),
            key = {"user","role"}
    ))
    public void listenDirectQueue1(String message){
        System.out.println("directQueue1消费者接收到的消息:" + message);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "directQueue2"),
            exchange = @Exchange(name = "konglz.direct",type = ExchangeTypes.DIRECT),
            key = {"user","menu"}
    ))
    public void listenDirectQueue2(String message){
        System.out.println("directQueue2消费者接收到的消息:" + message);
    }
}

在这里插入图片描述

  • 消费者
package com.konglz.publisher;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void direct(){
        String exchangeName = "konglz.direct";
        String message = "hello i am direct exchange";
        //只发送给routingKey为role的队列
        //rabbitTemplate.convertAndSend(exchangeName,"role",message);

        //只发送给routingKey为user的队列
        rabbitTemplate.convertAndSend(exchangeName,"user",message);
    }

}

在这里插入图片描述

Spring AMQP实现发布、订阅消息模型(Topic)

  • TopicExchange和DirectExchange类似,区别是topic可以带通配符

  • #: 代指0个或多个单词

  • *: 代指一个单词

  • 绑定关系

在这里插入图片描述

  • 消费者
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "topicQueue1"),
            exchange = @Exchange(name = "konglz.topic", type = ExchangeTypes.TOPIC),
            key = {"user.#"}
    ))
    public void listenTopicQueue1(String message){
        System.out.println("topicQueue1消费者接收到的消息:" + message);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "topicQueue2"),
            exchange = @Exchange(name = "konglz.topic", type = ExchangeTypes.TOPIC),
            key = {"#.log"}
    ))
    public void listenTopicQueue2(String message){
        System.out.println("topicQueue2消费者接收到的消息:" + message);
    }
}
  • 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void topic(){
        String exchangeName = "konglz.topic";
        String message = "模块正在更新!";
        //user.# topicQueue1能收到模块正在更新
        //rabbitTemplate.convertAndSend(exchangeName,"user.admin", message);
        //#.log topicQueue2收到模块正在更新
        //rabbitTemplate.convertAndSend(exchangeName,"log", message);
        //user.#、#.log topicQueue1、topicQueue2收到模块正在更新
        rabbitTemplate.convertAndSend(exchangeName,"user.log", message);
    }

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Spring AMQP消息转换器

  • Spring AMQP发送消息的类型都是Object,底层是jdk实现的有些缺点,一般是哟个json代替

    • 性能差
    • 存在安全性问题
    • 序列化的字符串太长
  • 生命一个objectQueue的队列

package com.konglz.consumer.config;

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

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 15:32
 */
@Configuration
public class FanoutConfig {
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("konglz.fanout");
    }

    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanoutQueue1");
    }

    @Bean
    public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue1)
                .to(fanoutExchange);
    }

    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanoutQueue2");
    }

    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue2)
                .to(fanoutExchange);
    }

    @Bean
    public Queue objectQueue(){
        return new Queue("objectQueue");
    }

}

在这里插入图片描述

  • 生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class PublisherApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void ObjectQueue(){
        Map<String,Object> message = new HashMap<>();
        message.put("name","konglz");
        message.put("age", "3");
        rabbitTemplate.convertAndSend("objectQueue", message);
    }

}

在这里插入图片描述

  • 有上图所知:rabbitmq将我们的对象做了序列化的处理,常见的ObjectInputStream

    • 性能差
    • 存在安全性问题
    • 序列化的字符串太长
  • 使用 Json 序列化代替自带的序列化

      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson-databind.version}</version>
      </dependency>
  • Json消息转换器注册到spring
@SpringBootApplication
public class PublisherApplication {

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

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}
  • 消费者
//Json消息转换器注册到spring
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);
    }

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

}
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * @Description
 * @Author konglz
 * @Data 2022/9/28 14:14
 */
@Component
public class SpringRabbitListener {

    @RabbitListener(queues = "objectQueue")
    public void listenObjectQueue(Map<String,Object> message){
        System.out.println("objectQueue接收到消息:" + message);
    }
}

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值