SpringBoot整合RabbitMq源码解析(前奏)

542 阅读2分钟

1:RabbitMq基本的使用

public static void main(String[] args) throws Exception{
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("localhost");
        try(Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel()) {
            //创建交换机
            channel.exchangeDeclare(
                             "exchange-test",
                                BuiltinExchangeType.TOPIC,
                              true,
                            false,
                           null
            );
            //创建队列
            channel.queueDeclare(
                    "queue-text",
                    true,
                    false,
                    false,
                    null
            );
            //绑定
            channel.queueBind("queue-text","exchange-test","test.key");
            String message = "hello";
            //发送消息
            channel.basicPublish("exchange-test","test.key",null,message.getBytes());
        }
    }

2:RabbitMq整合SpringBoot

  • 但是自从有了SpringBoot之后,我们当然不会再像上面这样编写代码了,我们声明队列,交换机会使用一个配置类

      @Bean
      public Exchange exchange1() {
          return new DirectExchange("exchange.order.restaurant",true,false,null);
      }
      
      @Bean
      public Queue queue1() {
          return new Queue("queue.order",true,false,false,args);
      }
      
      @Bean
      public Binding binding1() {
          return new Binding(
                  "queue.order",
                  Binding.DestinationType.QUEUE,
                  "exchange.order.restaurant",
                  "key.order",
                  null);
      }
      
    
  • 配置RabbitAdmin,ConnectionFactory,RabbitTemplate

    @Bean
        public ConnectionFactory connectionFactory() {
            CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
            connectionFactory.setHost("localhost");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("guest");
            connectionFactory.setPassword("guest");
            /**
             * 需要开启消息确认和返回机制
             */
            connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
            connectionFactory.setPublisherReturns(true);
            return connectionFactory;
        }
    
      @Bean
      public RabbitAdmin rabbitAdmin(@Autowired ConnectionFactory connectionFactory) {
          RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
          rabbitAdmin.setAutoStartup(true);
          return rabbitAdmin;
      }
    
      @Bean
      public RabbitTemplate rabbitTemplate(@Autowired ConnectionFactory connectionFactory) {
          RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
          rabbitTemplate.setMandatory(true);
          rabbitTemplate.setReturnsCallback((returnedMessage)->{
                  log.info("消息:{}",returnedMessage);
          });
          rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
              @Override
              public void confirm(CorrelationData correlationData, boolean ack, String s) {;
                  log.info("correlationData:{},ack:{},s:{}",correlationData,ack,s);
              }
          });
          return rabbitTemplate;
      }
      
    
  • 配置消息监听,

         @Bean
         public SimpleMessageListenerContainer listenerContainer(ConnectionFactory connectionFactory) {
             SimpleMessageListenerContainer messageListenerContainer = new SimpleMessageListenerContainer(connectionFactory);
             messageListenerContainer.setQueueNames("queue.order");
             //设置并发消费者数量
             messageListenerContainer.setConcurrentConsumers(3);
             messageListenerContainer.setMaxConcurrentConsumers(5);
             //设置消息自动确认机制
             messageListenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
             messageListenerContainer.setMessageListener(new MessageListener() {
                 @Override
                 public void onMessage(Message message) {
                     log.info("消息内容为:{}",new String(message.getBody()));
                }
             });
             //消费端限流
             messageListenerContainer.setPrefetchCount(1);
             return messageListenerContainer;
         }
    
  • 发送消息

    rabbitTemplate.send("exchange.order.restaurant","key.order",message,correlationData);
    
  • 结果测试

3:为什么要写第二步呢??

  • 我们除了使用 @RabbitListener来监听消息,其实也可以使用 SimpleMessageListenerContainer 来监听消息
  • 为什么SimpleMessageListenerContainer可以监听消息
    • 因为SimpleMessageListenerContainer有一个setMessageListener方法,需要传递一个MessageListener对象
    • MessageListener是一个侦听器接口,用于接收Amqp消息的异步传递,简单来说就是可以接受Amqp中的消息

4:那么现在对于 @RabbitListener 的实现你有没有一个大胆的想法呢??

  • 我们大胆猜测一下,@RabbitListener 这个注解的底层是不是也是使用 SimpleMessageListenerContainer这个监听容器来监听消息的呢

5:文末

  • 这里主要是解释一下如何使用 SimpleMessageListenerContainer 来监听消息,这对于后面分析 @RabbitListener 这个注解有很大帮助