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:

Modo Direto RabbitMQ

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:

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.