SpringBoot框架下RabbitMQ消息接受功能的实现

一.概念

RabbitMQ是一个开源的实现AMQP的产品,SpringBoot为了实现RabbitMQ客户端的功能,提供了名字为spring-boot-starter-amqp的starter,开发者在pom或gradle文件中添加这个starter的依赖即可。

二.如何实现接受功能

为实现接受消息的功能,需要向springboot框架注册处理消息的方法,框架为此提供了两种利用java代码注册的方式

1.编程式注册处理消息。注册一个bean,实现RabbitListenerConfigurer接口

@Configuration          
          public class RabbitListenerConfig {                  
              return new RabbitListenerConfigurer() {
                  @Override
                  public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
                      SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
                      endpoint.setQueueNames("myQueue1", "myQueue2");
                      endpoint.setConcurrency("2");
                      endpoint.setMessageListener(message -> {
                           System.out.println("收到消息"+new String(message.getBody()));
                       });
                       registrar.registerEndpoint(endpoint);
                  }
              }
          }

2. 注册式处理消息的方法。使用@RabbitListener注解,在注册参数中设置需要监听的队列名字

@Component
public class MyRabbitReceiver {

    @RabbitListener(queues = {"myQueue1", "myQueue2"}, concurrency = "2")
    public void processMessage(Message message) {
        System.out.println("收到消息"+new String(message.getBody()));
    }
}

三.为什么能实现接收功能

  • springboot项目启动时,默认扫描根目录下的META-INF/spring.factory文件,然后找到org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的加载类,文件部分内容如下

    文件部分内容如下:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
    org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
    

    可以看到框架会自动加载RabbitAutoConfiguration类

  • RabbitAutoConfiguration伪代码如下:

    @Configuration  //表示这个是一个配置类
    @ConditionalOnClass({RabbitTemplate.class, Channel.class})  //表示classpath是否存在RabbitTemplate.class, Channel.class
    @EnableConfigurationProperties({RabbitProperties.class}) // 根据配置初始化RabbitProperties.class
    @Import({RabbitAnnotationDrivenConfiguration.class}) // 引入RabbitAnnotationDrivenConfiguration.class,用于初始化配置消息接收功能
    public class RabbitAutoConfiguration {
           //初始化ConnectionFactory bean
           @Configuration
           @ConditionalOnMissingBean(ConnectionFactory.class)
           protected static class RabbitConnectionFactoryCreator {
           }
           
           //初始化rabbitTemplate, RabbitAdmin bean
           @Configuration
           @Import({RabbitAutoConfiguration.RabbitConnectionFactoryCreator.class})
           protected static class RabbitTemplateConfiguration {
           }
           
           //初始化RabbitMessagingTemplate bean
           @Configuration
           @ConditionalOnClass({RabbitMessagingTemplate.class})
           @ConditionalOnMissingBean({RabbitMessagingTemplate.class})
           @Import({RabbitAutoConfiguration.RabbitTemplateConfiguration.class})
           protected static class MessagingTemplateConfiguration {
           }
       }
    
    • 初始化ConnectionFactory
    • 初始化rabbitTemplate、rabbitAdmin
    • 初始化rabbitMessagingTemplate

    RabbitAutoConfiguration还引入RabbitAnnotationDrivenConfiguration类

  • RabbitAnnotationDrivenConfiguration

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({EnableRabbit.class})
    class RabbitAnnotationDrivenConfiguration {
        @Bean(
            name = {"rabbitListenerContainerFactory"}
        )
        @ConditionalOnMissingBean(
            name = {"rabbitListenerContainerFactory"}
        )
        @ConditionalOnProperty(
            prefix = "spring.rabbitmq.listener",
            name = {"type"},
            havingValue = "simple",
            matchIfMissing = true
        )
        SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory, ObjectProvider<ContainerCustomizer<SimpleMessageListenerContainer>> simpleContainerCustomizer) {
        }
    
        @Configuration(
            proxyBeanMethods = false
        )
        @EnableRabbit
        @ConditionalOnMissingBean(
            name = {"org.springframework.amqp.rabbit.config.internalRabbitListenerAnnotationProcessor"}
        )
        static class EnableRabbitConfiguration {
            EnableRabbitConfiguration() {
            }
        }
    }
    

    添加了@EnableRabbit注解

  • @EnableRabbit注解中通过导入RabbitListenerConfigurationSelector后导入了RabbitBootstrapConfiguration

    RabbitBootstrapConfiguration中想容器中添加了RabbitListenerAnnotationBeanPostProcessor实例

  • RabbitListenerAnnotationBeanPostProcessor

    • 实现了SmartInitializingSingleton的接口,在IOC容器实例加载完成后,会调用afterSingletonsInstantiated方法,对应了编程式的消息接受实现

      public void afterSingletonsInstantiated() {
              this.registrar.setBeanFactory(this.beanFactory);
              if (this.beanFactory instanceof ListableBeanFactory) {
                  Map<String, RabbitListenerConfigurer> instances = ((ListableBeanFactory)this.beanFactory).getBeansOfType(RabbitListenerConfigurer.class);
                  Iterator var2 = instances.values().iterator();
      
                  while(var2.hasNext()) {
                      RabbitListenerConfigurer configurer = (RabbitListenerConfigurer)var2.next();
                      configurer.configureRabbitListeners(this.registrar);
                  }
              }
          }
      
    • 实现了BeanPostProcessor的postProcessAfterInitialization方法,在每个实例初始化完成后会调用postProcessAfterInitialization方法。

      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          Class<?> targetClass = AopUtils.getTargetClass(bean);
          RabbitListenerAnnotationBeanPostProcessor.TypeMetadata metadata = (RabbitListenerAnnotationBeanPostProcessor.TypeMetadata)this.typeCache.computeIfAbsent(targetClass, this::buildMetadata);
          RabbitListenerAnnotationBeanPostProcessor.ListenerMethod[] var5 = metadata.listenerMethods;
          int var6 = var5.length;
      
          for(int var7 = 0; var7 < var6; ++var7) {
              RabbitListenerAnnotationBeanPostProcessor.ListenerMethod lm = var5[var7];
              RabbitListener[] var9 = lm.annotations;
              int var10 = var9.length;
      
              for(int var11 = 0; var11 < var10; ++var11) {
                  RabbitListener rabbitListener = var9[var11];
                  this.processAmqpListener(rabbitListener, lm.method, bean, beanName);
              }
          }
      
          if (metadata.handlerMethods.length > 0) {
              this.processMultiMethodListeners(metadata.classAnnotations, metadata.handlerMethods, bean, beanName);
          }
      
          return bean;
      }
      

​ 至此mq消息接受功能的实现完成。

后续将会对Springboot和Rabbit如何建立connection,建立多少个connection,connection和channel的关系,接受功能中相关参数的意义及实现,接受消息的方法是否需要考虑线程安全问题,以及AMQP协议的深入学习!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ 中,消息的接收和转换可以通过消息消费者(Consumer)来实现消息消费者可以订阅一个或多个队列,并在队列中有消息时接收、处理并转换消息消息的接收和转换通常包括以下步骤: 1. 建立连接:使用 AMQP 协议连接到 RabbitMQ 服务器,并创建一个信道(channel)。 2. 订阅队列:使用信道的 basic_consume 方法订阅一个队列,并指定一个消费者回调函数。当队列中有消息时,回调函数会被调用,处理消息并进行转换。 3. 接收消息:在消费者回调函数中,使用信道的 basic_deliver 方法接收消息。该方法的返回值是一个 Delivery 对象,包含消息的内容、属性等信息。 4. 处理消息:从 Delivery 对象中获取消息的内容和属性,并进行必要的处理。根据消息的格式和内容进行转换,比如将 JSON 格式的消息转换为 Java 对象等等。 5. 确认消息:在消息处理完成后,使用信道的 basic_ack 方法确认消息已经被处理。否则,消息将一直留在队列中,直到被确认或超时。 6. 关闭连接:在消息处理完成后,关闭信道和连接。 需要注意的是,在接收和转换消息的过程中,要注意消息的格式和编码方式。如果消息是以二进制格式发送的,需要进行解码;如果是以 JSON 或其他格式发送的,需要进行解析和转换。同时,还需要注意消息的大小、内容安全等问题,避免出现消息被篡改或者超出处理能力的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值