Как я могу использовать @RabbitListener в нескольких классах? - PullRequest
2 голосов
/ 13 января 2020

У меня есть приложение Spring, использующее RabbitMQ (spring-boot-starter-amqp).

Я хотел знать, возможно ли использовать аннотацию @RabbitListener для разных классов.

В настоящее время у меня есть два класса: Receiver и DeadLetterQueue

Receiver.java:

@Component
@Slf4j
public class Receiver {

  private final Logger logger = LoggerFactory.getLogger(this.getClass());

  @RabbitListener(queues = "queueName")
  public void receiveMessage(String message) throws Exception {
    logger.info("Received <{}>" + message.toString());

    throw new Exception("Error with the message");
  }

DeadLetterQueue.java:

@Component
@Slf4j
public class DeadLetterQueue {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RabbitListener(queues = "otherQueueName")
    public void processFailedMessages(String message) {
        logger.info("Received failed message<{}>:" + message.toString());
    }
}

RabbitMqConfig.java:

@Data
@Configuration
@ConfigurationProperties(prefix = "rabbitmq")
public class RabbitMqConfig {

  private String host;
  private int port;
  private String username;
  private String password;
  private String queue;
  private String exchange;
  private String dlq;
  private String dlx;
  private String routingKey;

  @Bean
  Queue incomingQueue() {
    return QueueBuilder.durable(queue)
            .withArgument("x-dead-letter-exchange", dlx)
            .build();
  }

  @Bean
  FanoutExchange deadLetterExchange() {
    return new FanoutExchange(dlx);
  }

  @Bean
  Queue deadLetterQueue() {
    return QueueBuilder.durable(dlq).build();
  }

  @Bean
  Binding deadLetterBinding() {
    return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
  }

  @Bean
  DirectExchange incomingQueueExchange() {
    return new DirectExchange(exchange);
  }

  @Bean
  Binding incomingQueueBinding() {
    return BindingBuilder.bind(incomingQueue()).to(incomingQueueExchange()).with(queue);
  }

Когда я использую инструмент управления RabbitMQ для отправки сообщения в FanoutExchange, processFailedMessages внутри класса DeadLetterQueue ничего не регистрирует на консоли. Однако, если этот метод находится внутри класса Receiver, все работает нормально. Это привело меня к предположению, что @RabbitListener не может работать в нескольких классах, если нет какой-то конфигурации, которую мне не хватает.

Другая информация:

  • Я использую Docker для запуска сервера RabbitMQ
  • Странно, если я добавлю метод receiveMessage() в DeadLetterQueue класс, ожидания не оправдываются.

Итак: можно ли определить очереди в нескольких классах с помощью @RabbitListener?

1 Ответ

0 голосов
/ 13 января 2020

Да, вы можете иметь столько @RabbitListener, сколько хотите, либо в одном классе, либо в нескольких классах, если эти классы используются в бобах Spring.

Поскольку у вас есть @Component в обоих случаях он должен работать просто отлично, если DeadLetterQueue не находится в пакете, который не сканируется Spring Boot.

Boot просматривает только те пакеты и подпакеты, в которых находится основной @SpringBootApplication.

Вы можете включить DEBUG logging для org.springframework для регистрации всего создания компонента во время инициализации приложения.

Я использую Docker для запуска RabbitMQ Server

Местоположение брокера не имеет значения.

...