Il modello di routing dei temi RabbitMQ in Java, utilizzando il tipo di scambio TopicExchange, si differenzia dal modello di routing (Direct) nel supportare la corrispondenza approssimativa dei parametri di routing. Poiché la corrispondenza del routing è più flessibile, è un modello più comunemente utilizzato. L'architettura è illustrata nel seguente diagramma:
Suggerimento: Indipendentemente dal pattern di lavoro di RabbitMQ utilizzato, la differenza sta nel tipo di scambio utilizzato e nei parametri di routing.
1. Tutorial Preliminare
Si prega di leggere prima le seguenti sezioni per comprendere le conoscenze rilevanti:
- Nozioni di base di RabbitMQ
- Principi del modello di routing dei temi RabbitMQ
- Avvio rapido per Java con RabbitMQ (Da leggere assolutamente, poiché le sezioni successive non ripeteranno il codice, mostreranno solo il codice chiave)
- Sezione Modello di Pubblicazione-Abbonamento RabbitMQ per Java (Da leggere assolutamente, poiché la sintassi del codice è quasi la stessa, differisce solo il tipo di scambio e i parametri di routing)
2. Definizione dello scambio dei temi
In Spring AMQP, la classe corrispondente allo scambio diretto è TopicExchange. Definiamo lo scambio attraverso una classe di configurazione di 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 TopicExchange topic() {
// Definire lo scambio
// Il parametro è il nome dello scambio, che deve essere unico
return new TopicExchange("tizi365.topic");
}
}
Suggerimento: Sia i produttori che i consumatori di messaggi hanno bisogno dello scambio.
3. Invio dei messaggi
Inviamo messaggi allo scambio e lo scambio consegna i messaggi alle code corrispondenti in base alle regole di routing.
package com.tizi365.rabbitmq.service;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.TopicExchange;
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 TopicExchange topic;
// A fini dimostrativi, qui viene utilizzato un compito pianificato per inviare un messaggio ogni secondo
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void send() {
// Contenuto del messaggio
String message = "Ciao Mondo!";
// Invia messaggio
// Il primo parametro è il nome dello scambio
// Il secondo parametro è la chiave di routing. Lo scambio dei temi consegna i messaggi alle code che corrispondono alla chiave di routing
// Il terzo parametro è il contenuto del messaggio, supportando qualsiasi tipo purché possa essere serializzato
template.convertAndSend(topic.getName(), "www.tizi365.com", message);
System.out.println("Messaggio inviato: '" + message + "'");
}
}
Suggerimento: Presta attenzione al secondo parametro "www.tizi365.com" nel metodo convertAndSend, poiché è un parametro cruciale.
4. Ricezione dei messaggi
4.1 Definire Code e Collegare Exchange
Per consumare messaggi dalle code, è necessario prima definire una coda e poi collegarla allo scambio di destinazione. Di seguito vengono definite due code e collegate allo stesso exchange.
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 TopicExchange topic() {
// Definire lo scambio
// Il parametro è il nome dello scambio, che deve essere univoco
return new TopicExchange("tizi365.topic");
}
@Bean
public Queue queue1() {
// Definire la coda 1
return new Queue("tizi365.topic.queue1");
}
@Bean
public Queue queue2() {
// Definire la coda 2
return new Queue("tizi365.topic.queue2");
}
@Bean
public Binding binding1(TopicExchange topic, Queue queue1) {
// Definire una relazione di collegamento, collegando la coda 1 allo scambio di argomento con una chiave di instradamento di: *.tizi365.com
return BindingBuilder.bind(queue1).to(topic).with("*.tizi365.com");
}
@Bean
public Binding binding2(TopicExchange topic, Queue queue2) {
// Definire una relazione di collegamento, collegando la coda 2 allo scambio di argomento con una chiave di instradamento di: *.baidu.com
return BindingBuilder.bind(queue2).to(topic).with("*.baidu.com");
}
}
Suggerimento: Quando si collegano la coda 1 e la coda 2 allo scambio, le chiavi di instradamento impostate utilizzano entrambe il * (asterisco) jolly, che corrisponde a una singola parola. Se cambiate a # (cancelletto), corrisponderebbe a più parole.
4.2 Definire Ascoltatori di Code
Definire gli ascoltatori 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;
// Consentire a Spring di gestire la classe corrente
@Component
public class DemoListener {
// Definire un ascoltatore, specificando a quale coda ascoltare attraverso il parametro delle code
@RabbitListener(queues = "tizi365.topic.queue1")
public void receive1(String msg) {
System.out.println("Ricevuto messaggio dalla coda 1: " + msg);
}
// Definire un ascoltatore, specificando a quale coda ascoltare attraverso il parametro delle code
@RabbitListener(queues = "tizi365.topic.queue2")
public void receive2(String msg) {
System.out.println("Ricevuto messaggio dalla coda 2: " + msg);
}
}
Poiché solo la coda 1 ha una chiave di instradamento di *.tizi365.com quando viene collegata allo scambio, corrisponderà ai messaggi con la chiave di instradamento (www.tizi365.com). Pertanto, solo la coda 1 sarà in grado di ricevere i messaggi, mentre la coda 2 non ne riceverà a causa di una chiave di instradamento non corrispondente.