java rabbitmq动态注册,监听实现

java rabbitmq动态注册,监听实现

最近项目中用到rabbitmq,将rabbitmq动态注册、监听、发送消息、接收消息进行封装,方便调用

话不多说,直接上代码

程序员不骗程序员

1.配置类代码

@EnableRabbit
@Configuration
public class RabbitConfig {

private static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class) ;
@Autowired
MqQueueConfigService mqQueueConfigService;

private List<MqQueueConfig> queueConfigList;

@Autowired
private ApplicationContext applicationContext;

@Autowired
private MqMessageHandleListener mqMessageHandleListener;

public static  Map<String, List<ReflectVo>> queueMap=new HashMap<>();

@Bean
@ConditionalOnMissingBean
public RabbitConfigInitializer rabbitModuleInitializer(AmqpAdmin amqpAdmin) {
    queueConfigList=mqQueueConfigService.selectList();
    return new RabbitConfigInitializer(amqpAdmin, queueConfigList);
}

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


@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {

    RabbitTemplate rabbitTemplate = new RabbitTemplate();
    rabbitTemplate.setConnectionFactory(connectionFactory);
    rabbitTemplate.setMandatory(true);

    rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
    });

    rabbitTemplate.setReturnsCallback(returnedMessage -> {

    });
    rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
    return rabbitTemplate;
}


@Bean
public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    container.setDefaultRequeueRejected(false);
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    container.setExposeListenerChannel(true);
    List<String> queueNames=getQueueNames() ;
    for (String queueName:queueNames) {
        container.addQueueNames( queueName);
    }
    container.setMessageListener(new ChannelAwareMessageListener() {
        @Override
        public void onMessage(Message message, Channel channel) throws Exception {
        
            String   key=message.getMessageProperties().getConsumerQueue()+message.getMessageProperties().getReceivedRoutingKey();
            if (!CollectionUtils.isEmpty( queueMap.get(key))){
                Gson gson = new Gson();
                MqMessage mqMessage  = gson.fromJson(msg, MqMessage.class);
               try {
                    mqMessageHandleListener.handleMessage(queueMap.get(key),mqMessage);
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException e) {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                    e.printStackTrace();
                }
            }

        }


    });
    return container;
}



private List<String> getQueueNames(){
    List<String> queueNames=new ArrayList<>();
    Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(MqConfigInterface.class);
    List<ReflectVo>  reflectVoList=null;
    ReflectVo reflectVo=null;
    for (Object bean : beanMap.values()) {
        Class<?> clazz = bean.getClass();
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(MqConfigMethod.class)) {
                MqConfigMethod annotation = declaredMethod.getDeclaredAnnotation(MqConfigMethod.class);
                String key=annotation.queues()+annotation.routingKey();
                reflectVo=new ReflectVo();
                reflectVo.setClassName(clazz.getName());
                reflectVo.setQueueName(annotation.queues());
                reflectVo.setRoutingKey(annotation.routingKey());
                reflectVo.setMethodName(declaredMethod.getName());

                queueNames.add(annotation.queues());
                if (null !=queueMap&& null!= queueMap.get(key)){
                    reflectVoList=queueMap.get(key);
                    reflectVoList.add(reflectVo);
                    queueMap.put(key,reflectVoList);
                }else {
                    reflectVoList=new ArrayList<>();
                    reflectVoList.add(reflectVo);
                    queueMap.put(key,reflectVoList);
                }
            }
        }

    }

    return queueNames;
}

}

2.监听处理类

@Component
public class MqMessageHandleListener {

private static final Logger logger = LoggerFactory.getLogger(MqMessageHandleListener.class) ;

public  void  handleMessage(List<ReflectVo> reflectVoList, MqMessage mqMessage) throws Exception{

      for (ReflectVo reflectVo:reflectVoList) {
        Class clazz = Class.forName(reflectVo.getClassName());

        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.getName().equals(reflectVo.getMethodName())){

                Object obj = clazz.newInstance();
                Object[] values = new Object[1];
                values[0] = mqMessage;
                //解除成员属性的私有限制
                declaredMethod.setAccessible(true);
                declaredMethod.invoke(obj,values);

            }
        }
    }
}

}

3.初始化注册类

public class RabbitConfigInitializer implements SmartInitializingSingleton {

private static final Logger logger = LoggerFactory.getLogger(RabbitConfigInitializer.class) ;

private AmqpAdmin amqpAdmin;

private List<MqQueueConfig> queueConfigList;

public RabbitConfigInitializer(AmqpAdmin amqpAdmin, List<MqQueueConfig> queueConfigList) {
    this.amqpAdmin = amqpAdmin;
    this.queueConfigList = queueConfigList;
}

@Override
public void afterSingletonsInstantiated() {
    declareRabbitModule();
}
private void declareRabbitModule() {
    if (CollectionUtil.isEmpty(queueConfigList)) {
        return;
    }
    for (MqQueueConfig  queueConfig : queueConfigList) {
        configParamValidate(queueConfig);
        Queue queue = convertQueue(queueConfig);
        Exchange exchange = convertExchange(queueConfig);
        String routingKey = queueConfig.getRoutingKey();
        String queueName = queueConfig.getQueueName();
        String exchangeName = queueConfig.getExchangeName();
        Binding binding = new Binding(queueName, Binding.DestinationType.QUEUE, exchangeName, routingKey, null);
        amqpAdmin.declareQueue(queue);
        amqpAdmin.declareExchange(exchange);
        amqpAdmin.declareBinding(binding);
    }
}

public void configParamValidate(MqQueueConfig  queueConfig) {

    String routingKey = queueConfig.getRoutingKey();

    Assert.isTrue(StrUtil.isNotBlank(routingKey), "RoutingKey 未配置");

    Assert.isTrue(StrUtil.isNotBlank(queueConfig.getExchangeName()), "routingKey:{}未配置exchange的name属性");

    Assert.isTrue(StrUtil.isNotBlank(queueConfig.getQueueName()), "routingKey:{}未配置exchange的name属性");

}

public Queue convertQueue(MqQueueConfig  queueConfig) {
    Map<String, Object> arguments = new HashMap<>();

    return new Queue(queueConfig.getQueueName().trim(), true, false, false, arguments);
}

public Exchange convertExchange(MqQueueConfig  queueConfig) {
    AbstractExchange exchange = null;
    String exchangeName = queueConfig.getExchangeName();
    boolean isDurable = true;
    boolean isAutoDelete = false;
    Map<String, Object> arguments =new HashMap<>();
    switch (queueConfig.getExchangeType()) {
        case "DIRECT":// 直连交换机
            exchange = new DirectExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
            break;
        case "TOPIC": // 主题交换机
            exchange = new TopicExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
            break;
        case "FANOUT": //扇形交换机
            exchange = new FanoutExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
            break;
        case "HEADERS": // 头交换机
            exchange = new HeadersExchange(exchangeName.trim(), isDurable, isAutoDelete, arguments);
            break;
    }
    return exchange;
}

}

以上是最主要的三个类,有问题欢迎指正,多交流,多沟通

后面整理了一份完整版的代码,有需要可以自行下载!

程序员不骗程序员

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在 RabbitMQ 中,可以通过停止所有的消费者来停止监听队列。可以使用 `channel.basicCancel()` 方法,该方法可以取消指定消费者的订阅关系。如果要暂停所有消费者,则需要循环调用 `channel.basicCancel()` 方法来取消所有消费者的订阅。具体实现可以参考以下代码: ```java try { // 循环取消所有消费者的订阅 for (String consumerTag : channel.getConsumerTags()) { channel.basicCancel(consumerTag); } } catch (IOException e) { e.printStackTrace(); } ``` 在上述代码中,`channel.getConsumerTags()` 方法可以获取当前所有消费者的标识符,然后循环调用 `channel.basicCancel()` 方法来取消消费者的订阅。这样就可以暂停所有监听了。 ### 回答2: 在Java中使用RabbitMQ暂停所有监听可以通过以下步骤实现: 1. 首先,我们需要创建一个连接到RabbitMQ的连接工厂对象。可以使用以下代码创建连接工厂: ``` ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); ``` 2. 接下来,我们需要创建一个通道对象。可以使用以下代码创建通道对象: ``` Channel channel = connection.createChannel(); ``` 3. 然后,我们需要声明一个交换机和一个队列,并将它们绑定在一起。可以使用以下代码声明交换机和队列,并将它们绑定在一起: ``` String exchangeName = "my-exchange"; String queueName = "my-queue"; String routingKey = "my-routing-key"; channel.exchangeDeclare(exchangeName, "direct", true); channel.queueDeclare(queueName, true, false, false, null); channel.queueBind(queueName, exchangeName, routingKey); ``` 4. 最后,我们可以通过调用`basicConsume`方法来开始监听消息。通过指定一个消费者对象,可以在接收到消息时执行相应的操作。可以使用以下代码开始监听消息: ``` String consumerTag = channel.basicConsume(queueName, true, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println("Received message: " + message); // 执行其他操作... } }); ``` 如果要暂停所有监听,则可以调用`basicCancel`方法并传递消费者标签,如以下代码所示: ``` channel.basicCancel(consumerTag); ``` 这样,所有的监听操作将会被暂停,不再接收和处理消息。 ### 回答3: 在Java中,可以使用RabbitMQ的Java客户端库来暂停所有监听。要实现这一功能,可以使用RabbitMQ的Channel对象的basicConsume方法来设置消费者。通过使用basicConsume方法可以为每个消费者分配一个消费者标签,然后可以使用basicCancel方法来取消监听。以下是实现暂停所有监听的步骤: 1. 创建一个Connection对象并连接到RabbitMQ服务器。 2. 在Connection对象上创建一个Channel对象。 3. 使用Channel对象的basicConsume方法来设置消费者,获取消费者标签。 4. 将消费者标签存储在一个列表中,以供稍后使用。 5. 使用Channel对象的basicCancel方法来取消所有消费者。 6. 关闭Channel对象和Connection对象,释放资源。 以下是一个简单的示例代码,展示如何暂停所有监听: ```java import com.rabbitmq.client.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; public class RabbitMQPauseListeners { private static final String QUEUE_NAME = "my_queue"; private static final String HOST = "localhost"; private static final String USERNAME = "guest"; private static final String PASSWORD = "guest"; public static void main(String[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.setHost(HOST); factory.setUsername(USERNAME); factory.setPassword(PASSWORD); List<String> consumerTags = new ArrayList<>(); try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 设置第一个消费者 String consumerTag1 = channel.basicConsume(QUEUE_NAME, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { // 处理消息 System.out.println("Received message: " + new String(body)); channel.basicAck(envelope.getDeliveryTag(), false); } }); consumerTags.add(consumerTag1); // 设置第二个消费者 String consumerTag2 = channel.basicConsume(QUEUE_NAME, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { // 处理消息 System.out.println("Received message: " + new String(body)); channel.basicAck(envelope.getDeliveryTag(), false); } }); consumerTags.add(consumerTag2); // 暂停所有监听 for (String consumerTag : consumerTags) { channel.basicCancel(consumerTag); } System.out.println("Listeners paused."); } catch (TimeoutException | IOException e) { e.printStackTrace(); } } } ``` 在这个示例中,创建了两个消费者,它们同时监听同一个队列。然后使用basicCancel方法将它们暂停。通过在channel.basicConsume方法中设置noAck为false,并且在处理消息后调用channel.basicAck方法,可以实现手动确认消息的消费确认方式。 运行上述代码后,会输出"Listeners paused.",表示所有监听都已暂停。此时,消费者将不再接收到任何新的消息,直到调用basicConsume方法重新设置监听
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

客官酒来了

你的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值