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:
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:
- Concetti di base di RabbitMQ
- Principio della modalità di routing di RabbitMQ
- Avvio rapido per Java con RabbitMQ (Da leggere assolutamente, poiché le sezioni successive non duplicheranno il codice, mostreranno solo il codice chiave)
- Modello di pubblicazione-sottoscrizione per Java con RabbitMQ (Da leggere assolutamente, poiché la struttura del codice è quasi la stessa, cambiano solo il tipo di scambio e i parametri di routing)
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.