O padrão de roteamento do RabbitMQ (modo Direto) em Java utiliza o tipo de troca DirectExchange. A diferença do padrão de publicação-subscrição é que a troca direta entrega mensagens para filas com parâmetros de roteamento que correspondem totalmente. A arquitetura é mostrada na imagem abaixo:
Dica: Independentemente do modo de funcionamento do RabbitMQ utilizado, a diferença reside no tipo de troca utilizado e nos parâmetros de roteamento.
1. Tutoriais Prévios
Por favor, leia as seguintes seções para entender o conhecimento relacionado:
- Conceitos Básicos do RabbitMQ
- Princípio do Modo de Roteamento do RabbitMQ
- Início Rápido para Java com RabbitMQ (Leitura obrigatória, pois as seções subsequentes não duplicarão o código, apenas mostrarão o código-chave)
- Padrão de Publicação-Subscrição para Java com RabbitMQ (Leitura obrigatória, pois a estrutura do código é quase a mesma, apenas o tipo de troca e os parâmetros de roteamento diferem)
2. Definir a Troca Direta
No Spring AMQP, a classe correspondente à troca direta é DirectExchange. Definimos a troca por meio de uma classe de configuração do Spring Boot.
package com.tizi365.rabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueConfig {
@Bean
public DirectExchange direct() {
// Definir a troca
// O parâmetro é o nome da troca, que deve ser único
return new DirectExchange("tizi365.direct");
}
}
Dica: Tanto o produtor quanto o consumidor de mensagens requerem uma troca.
3. Enviar Mensagens
Enviamos mensagens para a troca, que depois entrega as mensagens para as filas correspondentes com base nas regras de roteamento.
package com.tizi365.rabbitmq.service;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class SendService {
@Autowired
private RabbitTemplate template;
@Autowired
private DirectExchange direct;
// Para demonstração, utilizamos uma tarefa agendada para enviar uma mensagem a cada segundo
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void send() {
// Conteúdo da mensagem
String message = "Olá Mundo!";
// Enviar a mensagem
// O primeiro parâmetro é o nome da troca
// O segundo parâmetro é a chave de roteamento. Com uma troca direta, a mensagem é entregue à fila cuja chave de roteamento corresponde a "tizi365"
// O terceiro parâmetro é o conteúdo da mensagem, que suporta qualquer tipo, desde que possa ser serializado
template.convertAndSend(direct.getName(), "tizi365", message);
System.out.println("Mensagem enviada '" + message + "'");
}
}
Dica: Preste atenção ao segundo parâmetro no método convertAndSend, pois este é um parâmetro crítico.
4. Receber Mensagens
4.1 Definir Filas e Vincular Troca
Para consumir mensagens de uma fila, é necessário primeiro definir a fila e depois vinculá-la à troca de destino. O código a seguir define duas filas e as vincula à mesma troca:
package com.tizi365.rabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueConfig {
@Bean
public DirectExchange direct() {
// Definir a troca
// O parâmetro é o nome da troca, que deve ser único
return new DirectExchange("tizi365.direct");
}
@Bean
public Queue queue1() {
// Definir fila 1
return new Queue("tizi365.direct.queue1");
}
@Bean
public Queue queue2() {
// Definir fila 2
return new Queue("tizi365.direct.queue2");
}
@Bean
public Binding binding1(DirectExchange direct, Queue queue1) {
// Definir um vínculo para vincular a fila 1 à troca direta com uma chave de roteamento "tizi365"
// Quando a chave de roteamento corresponder a "tizi365", a troca enviará mensagens para a fila 1
return BindingBuilder.bind(queue1).to(direct).with("tizi365");
}
@Bean
public Binding binding2(DirectExchange direct, Queue queue2) {
// Definir um vínculo para vincular a fila 2 à troca direta com uma chave de roteamento "baidu"
// Quando a chave de roteamento corresponder a "baidu", a troca enviará mensagens para a fila 2
return BindingBuilder.bind(queue2).to(direct).with("baidu");
}
}
4.2 Definir Ouvintes de Fila
Defina ouvintes de mensagem usando a anotação RabbitListener para consumir mensagens de filas específicas:
package com.tizi365.rabbitmq.listener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
// Deixe o Spring gerenciar a classe atual
@Component
public class DemoListener {
// Defina um ouvinte para consumir mensagens da fila 1
@RabbitListener(queues = "tizi365.direct.queue1")
public void receive1(String msg) {
System.out.println("Mensagem recebida da fila 1: " + msg);
}
// Defina um ouvinte para consumir mensagens da fila 2
@RabbitListener(queues = "tizi365.direct.queue2")
public void receive2(String msg) {
System.out.println("Mensagem recebida da fila 2: " + msg);
}
}
Como apenas a fila 1 tem uma chave de roteamento "tizi365" ao se vincular à troca, apenas a fila 1 pode receber mensagens. A fila 2, por não corresponder à chave de roteamento, não receberá nenhuma mensagem.