Il modello di routing RabbitMQ (modalità Direct) in Java utilizza il tipo di scambio DirectExchange. La differenza rispetto al modello di pubblicazione-sottoscrizione sta nel fatto che lo scambio diretto invia messaggi alle code con parametri di routing completamente corrispondenti. L'architettura è mostrata nell'immagine qui sotto:

RabbitMQ Direct Mode

Suggerimento: Indipendentemente dalla modalità di funzionamento di RabbitMQ utilizzata, la differenza sta nel tipo di scambio utilizzato e nei parametri di routing.

1. Tutorial Prerequisiti

Ti preghiamo di leggere le seguenti sezioni per comprendere le conoscenze correlate:

2. Definire lo scambio diretto

In Spring AMQP, la classe corrispondente allo scambio diretto è DirectExchange. Definiamo lo scambio attraverso una classe di configurazione 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() {
        // Definire lo scambio
        // Il parametro è il nome dello scambio, che deve essere univoco
        return new DirectExchange("tizi365.direct");
    }
}

Suggerimento: Entrambi il produttore di messaggi e il consumatore richiedono uno scambio.

3. Inviare messaggi

Inviare messaggi allo scambio, che quindi li invierà alle code corrispondenti in base alle regole di routing.

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;

    // Per scopi dimostrativi, utilizziamo un'attività pianificata per inviare un messaggio ogni secondo
    @Scheduled(fixedDelay = 1000, initialDelay = 1000)
    public void send() {
        // Contenuto del messaggio
        String messaggio = "Ciao mondo!";
        // Inviare il messaggio
        // Il primo parametro è il nome dello scambio
        // Il secondo parametro è la chiave di routing. Con uno scambio diretto, il messaggio viene inviato alla coda il cui routing key corrisponde a "tizi365"
        // Il terzo parametro è il contenuto del messaggio, che supporta qualsiasi tipo purché possa essere serializzato
        template.convertAndSend(direct.getName(), "tizi365", messaggio);
        System.out.println("Messaggio inviato '" + messaggio + "'");
    }
}

Suggerimento: Presta attenzione al secondo parametro nel metodo convertAndSend, poiché si tratta di un parametro critico.

4. Ricevere messaggi

4.1 Definire Code e Collegare lo Scambio

Per consumare messaggi da una coda, è necessario prima definire una coda e quindi collegarla allo scambio di destinazione. Il seguente codice definisce due code e le collega allo stesso scambio:

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() {
        // Definisci lo scambio
        // Il parametro è il nome dello scambio, che deve essere univoco
        return new DirectExchange("tizi365.direct");
    }

    @Bean
    public Queue queue1() {
        // Definisci la coda 1
        return new Queue("tizi365.direct.queue1");
    }

    @Bean
    public Queue queue2() {
        // Definisci la coda 2
        return new Queue("tizi365.direct.queue2");
    }

    @Bean
    public Binding binding1(DirectExchange direct, Queue queue1) {
        // Definisci un collegamento per collegare la coda 1 allo scambio diretto con una routing key di "tizi365"
		// Quando la routing key corrisponde a "tizi365", lo scambio invierà messaggi alla coda 1
        return BindingBuilder.bind(queue1).to(direct).with("tizi365");
    }

    @Bean
    public Binding binding2(DirectExchange direct, Queue queue2) {
        // Definisci un collegamento per collegare la coda 2 allo scambio diretto con una routing key di "baidu"
		// Quando la routing key corrisponde a "baidu", lo scambio invierà messaggi alla coda 2
        return BindingBuilder.bind(queue2).to(direct).with("baidu");
    }
}

4.2 Definire i Listener delle Code

Definire i listener dei messaggi utilizzando l'annotazione RabbitListener per consumare messaggi da code specifiche:

package com.tizi365.rabbitmq.listener;

import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

// Fai in modo che Spring gestisca la classe corrente
@Component
public class DemoListener {
    // Definire un listener per consumare messaggi dalla coda 1
    @RabbitListener(queues = "tizi365.direct.queue1")
    public void receive1(String msg) {
        System.out.println("Messaggio ricevuto dalla coda 1: " + msg);
    }

    // Definire un listener per consumare messaggi dalla coda 2
    @RabbitListener(queues = "tizi365.direct.queue2")
    public void receive2(String msg) {
        System.out.println("Messaggio ricevuto dalla coda 2: " + msg);
    }
}

Poiché solo la coda 1 ha una routing key di "tizi365" quando è collegata allo scambio, solo la coda 1 può ricevere messaggi. La coda 2, poiché la routing key non corrisponde, non riceverà alcun messaggio.