Spring Boot 纯代码实现RabbitMQ的绑定,非注解

由于业务需要, 有的时候, 基于注解形式的代码, 不能满足业务需求.
必须动态变化的绑定和执行. 于是经过一番研究, 记录一下如何通过纯代码的形式Spring实现队列创建和Routingkey 绑定和 消息监听处理.

package com.qcd.SpringRebbitMQ.Consumer;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.qcd.DDD.RedisService;   
import com.qcd.db.service.SuanLiFenPeiConfigService;
import com.qcd.db.service.ThirdDataPoolService; 
import com.qcd.db.domain.Record; 
// import com.qcd.db.model.AppConfig; 
// import java.util.List;

import lombok.extern.slf4j.Slf4j;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;


import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
 
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;


/**
 *  
 * 监听来自MQ的 "CMD.WebAPI.TakeImage+gp" 事件 然后执行抓图. 
 */ 
 
 

@Slf4j
@Component 
public class Q_WebAPI_TakeImage  implements MessageListener, ApplicationRunner {
 
    
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // log.info("\t \033[1;32;40m  Q_WebAPI_TakeImage 抓图服务  已启动 \033[0m ");  
    }
  
    
    @Autowired
    SuanLiFenPeiConfigService suanLiFenPeiConfigService;
   
 

    // @Autowired
    // RabbitMQHelper rabbitMQHelper;

 
    
    @Autowired
    RabbitMQBindConfig_Local rabbitMQBindConfig_Local;
    
    
    
  @Value("${app.JQNum}")
  String JQNum;
 
   
  @Autowired
  public ApplicationContext applicationContext;
 
  @Autowired
  public ConnectionFactory connectionFactory;
 
  
   //开关是否启用本队列,  在配置文件中定义配置
   @Value("${switch.Q_WebAPI_TakeImage}")
   String switch_Function; 

   @Bean
   public void InitMQBindingTakeImage()
   {    
	   		this.DeclareQueue_CMDTakeImage();
            this.InitConsumer(); 
            log.info("\t \033[1;32;40m  Q_WebAPI_TakeImage 抓图服务  已启动 \033[0m "); 
   }
   

   
  /**
   * 定义队列 Q.WebAPI.TakeImage.on.OtherSys.CMDTakeImage
   * 还需要 InitConsumer() 进行动态绑定,
   */

  public Integer DeclareQueue_CMDTakeImage(){
        // log.info("配置抓图拍照队列 Q_WebAPI_TakeImage_on_OtherSys_CMDTakeImage ...");  
  
        TopicExchange com_qcd_ai =  new TopicExchange(exchange);

        ArrayList<SuanLiFenPeiConfig> suanliconfigs = suanLiFenPeiConfigService .FindByComputer_num(JQNum);  
        RabbitAdmin rabbitAdmin = new RabbitAdmin(this.rabbitTemplate.getConnectionFactory());
       
        rabbitAdmin.declareExchange(com_qcd_ai);

        // 多通道, 分布式.
        for (SuanLiFenPeiConfig slcfg : suanliconfigs) { 
            Integer gp =  slcfg.getBh_group();  // 线程ID
            int Priority = slcfg.getPriority(); // 优先级
             
            String queuename = "Q.WebAPI.TakeImage.on.OtherSys.CMDTakeImage." + gp;
            String event_routing_key = "E.*.CMDTakeImage." + gp;  
            String cmd_routing_key   = "CMD.WebAPI.TakeImage." + gp ; 

            log.info("抓图拍照"+ queuename+ "绑定" + event_routing_key + "和" + cmd_routing_key);
 
            Queue CMDTakeImageQueue =  new Queue(queuename); 
            rabbitAdmin.declareQueue(CMDTakeImageQueue); 

            Binding b1 =  BindingBuilder
            .bind(CMDTakeImageQueue)
            .to(com_qcd_ai)
            .with(event_routing_key);

            b1.addArgument("x-priority", Priority);
            
            Binding b2 =  BindingBuilder
            .bind(CMDTakeImageQueue)
            .to(com_qcd_ai)
            .with(cmd_routing_key);

            b2.addArgument("x-priority", Priority);


            //绑定两个routingkey
            rabbitAdmin.declareBinding(b1); 
            rabbitAdmin.declareBinding(b2);   
        }
        return 1; 
  }

   
  // 动态添加 处理类 因为需要gp参数,  所以必须是动态的.
  // @Bean
  public void InitConsumer() { 
      try {

          int  maxbhgroup = 10;  
       
          // 多通道, 分布式. 
          for (int gp=0; gp<= maxbhgroup;gp++)
          {
              this.AddHandler( "Q.WebAPI.TakeImage.on.OtherSys.CMDTakeImage." + gp,  1);
          }
          
      } catch (Exception e) {
        e.printStackTrace();
        log.error(e.getMessage()); 
      }
  }
  
  
  private void AddHandler(String queueName,  int onOfConsumer) throws Exception {
      // this.queueName = queueName;
      // this.routingKey = routingKey;
      // this.onOfConsumer = onOfConsumer;

      SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
      container.setConnectionFactory(connectionFactory);
      container.setQueueNames(queueName);
      //container.set
      container.setConcurrentConsumers(onOfConsumer);
      // 创建一个处理类的实例, 因为是 gp多实例的, 所以必须是 动态创建. 
      Q_WebAPI_TakeImage handler = applicationContext.getBean(Q_WebAPI_TakeImage.class);

      container.setMessageListener(handler);
      container.start(); 
      
      log.info(queueName +" 已启动监听 " );

  }
   
 
    // 抓图处理主代码
    @Override
    public void onMessage(org.springframework.amqp.core.Message message) {
         // 将消息转换成String类型然后打印 
         
         try { 
            String data = new String(message.getBody(),"utf-8");
            log.info("Q_WebAPI_TakeImage 接收到抓图消息=>"+ data);   
            com.qcd.db.domain.Record record = JSON.parseObject(data,com.qcd.db.domain.Record.class);
            
            // 这个地方是内部的mq接口, 所有不会传递参数 sysname
            //String roukingkey = message.getMessageProperties().getReceivedRoutingKey();
            //String sysname = roukingkey.split("[.]")[1]; //roukingkey 为 "E.{系统名}.CMDTakeImage"
            
            // JSONObject jsonRecord = new JSONObject();
            // record.setSysname(sysname); 
            // jsonRecord.put("record", record);   
            // String deviceId =  ljxconfig.getYun_id();
           ....
           .... 
         }
         catch (IOException ee) {
            log.error("抓图失败 超时", ee); 
         }catch (TimeoutException e) { 
            //  e.printStackTrace();
            log.error("抓图失败 超时", e); 
         } 
        //  catch (UnsupportedEncodingException e) { 
        //     // e.printStackTrace();
        //     log.error("抓图失败 不支持的编码", e); 
        //  }
        //  finally{
        //     //channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        //  }

    }
 
    

} 

首先队列的注册是在, 函数 InitMQBindingTakeImage() 中开始注册的, 具体实现代码是在 DeclareQueue_CMDTakeImage 中实现的.

绑定队列与代码之间的关系是在 InitConsumer中初始化的, 具体实现代码是在 AddHandler() 中.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要在Spring Boot项目中添加RabbitMQ的依赖。可以在pom.xml文件中添加下面的依赖: ```xml <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>2.3.11.RELEASE</version> </dependency> ``` 然后,你需要创建一个RabbitMQ配置类,配置连接工厂、交换机、队列等信息。可以参考下面的代码: ```java @Configuration public class RabbitMQConfig { @Value("${spring.rabbitmq.host}") private String host; @Value("${spring.rabbitmq.port}") private int port; @Value("${spring.rabbitmq.username}") private String username; @Value("${spring.rabbitmq.password}") private String password; @Value("${spring.rabbitmq.virtual-host}") private String virtualHost; @Value("${rabbitmq.exchange}") private String exchange; @Value("${rabbitmq.queue}") private String queue; @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory factory = new CachingConnectionFactory(); factory.setHost(host); factory.setPort(port); factory.setUsername(username); factory.setPassword(password); factory.setVirtualHost(virtualHost); return factory; } @Bean public DirectExchange directExchange() { return new DirectExchange(exchange); } @Bean public Queue queue() { return new Queue(queue); } @Bean public Binding binding() { return BindingBuilder.bind(queue()).to(directExchange()).with(queue()); } } ``` 在上面的代码中,我们使用@Value注解将一些配置信息从配置文件中读取出来,并将它们注入到相应的属性中。我们创建了一个连接工厂、一个直连交换机、一个队列,并将它们绑定在一起。 接下来,我们需要编写一个定时任务,每隔一段时间就发送一条消息RabbitMQ中。可以使用Spring Boot提供的@Scheduled注解实现定时任务。可以参考下面的代码: ```java @Component public class MessageSender { @Autowired private RabbitTemplate rabbitTemplate; @Value("${rabbitmq.exchange}") private String exchange; @Value("${rabbitmq.queue}") private String queue; @Scheduled(fixedDelay = 10000) public void sendMessage() { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String message = "Hello, it is now " + dateFormat.format(new Date()); rabbitTemplate.convertAndSend(exchange, queue, message); System.out.println("Sent message: " + message); } } ``` 在上面的代码中,我们创建了一个名为MessageSender的组件,并使用@Autowired注解将RabbitTemplate注入到它的属性中。我们还使用@Value注解将交换机和队列的名称从配置文件中读取出来。 我们使用@Scheduled注解来指定定时任务的执行时间。在本例中,我们每隔10秒钟发送一条消息。在sendMessage方法中,我们使用SimpleDateFormat类创建了一个格式化的时间字符串,并将它作为消息发送到了RabbitMQ中。 最后,我们需要在配置文件中添加一些RabbitMQ的配置信息,如下所示: ```properties spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.virtual-host=/ rabbitmq.exchange=notification-exchange rabbitmq.queue=notification-queue ``` 在上面的配置信息中,我们指定了RabbitMQ的连接信息,以及交换机和队列的名称。 现在,我们已经完成了利用Spring BootRabbitMQ实现定时发送通知功能的代码编写。当应用程序启动后,它会每隔10秒钟向RabbitMQ中发送一条消息。你可以在控制台输出中看到发送的消息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值