Le motif de sujet RabbitMQ en Java, en utilisant le type d'échange TopicExchange, diffère du motif de routage (Direct) par le fait que les paramètres de routage prennent en charge la correspondance floue. En raison de sa flexibilité, la correspondance de routage est un motif plus couramment utilisé. L'architecture est illustrée dans le diagramme suivant :
Astuce : Peu importe le motif de travail RabbitMQ utilisé, la différence réside dans le type d'échange utilisé et les paramètres de routage.
1. Tutoriel préalable
Veuillez lire les sections suivantes en premier afin de comprendre les connaissances pertinentes :
- Concepts de base de RabbitMQ
- Principes du motif de sujet RabbitMQ
- Démarrage rapide pour Java avec RabbitMQ (À lire absolument, car les sections suivantes ne répéteront pas le code, mais montreront uniquement le code clé)
- Section Patron de publication-abonnement en Java pour RabbitMQ (À lire absolument, car la syntaxe du code est presque identique, seuls le type d'échange et les paramètres de routage diffèrent)
2. Définition de l'échange de sujet
En Spring AMQP, la classe correspondant à l'échange Direct est TopicExchange. Nous définissons l'échange à travers une classe de configuration 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() {
// Définir l'échange
// Le paramètre est le nom de l'échange, qui doit être unique
return new TopicExchange("tizi365.topic");
}
}
Astuce : Les producteurs et les consommateurs de messages ont tous deux besoin de l'échange.
3. Envoi de messages
Nous envoyons des messages à l'échange, et l'échange distribue les messages aux files correspondantes en fonction des règles de routage.
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;
// À des fins de démonstration, une tâche planifiée est utilisée ici pour envoyer un message chaque seconde
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void send() {
// Contenu du message
String message = "Bonjour le monde !";
// Envoyer le message
// Le premier paramètre est le nom de l'échange
// Le deuxième paramètre est la clé de routage. L'échange de sujet distribue les messages aux files qui correspondent à la clé de routage
// Le troisième paramètre est le contenu du message, prenant en charge n'importe quel type tant qu'il peut être sérialisé
template.convertAndSend(topic.getName(), "www.tizi365.com", message);
System.out.println("Message envoyé : '" + message + "'");
}
}
Astuce : Faites attention au deuxième paramètre "www.tizi365.com" dans la méthode convertAndSend, car il s'agit d'un paramètre crucial.
4. Réception des messages
4.1 Définir les Files d'attente et lier les échanges
Pour consommer des messages des files d'attente, vous devez d'abord définir une file d'attente puis la lier à l'échange cible. Ci-dessous, deux files d'attente sont définies et liées au même échange.
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() {
// Définir l'échange
// Le paramètre est le nom de l'échange, qui doit être unique
return new TopicExchange("tizi365.topic");
}
@Bean
public Queue queue1() {
// Définir la file d'attente 1
return new Queue("tizi365.topic.queue1");
}
@Bean
public Queue queue2() {
// Définir la file d'attente 2
return new Queue("tizi365.topic.queue2");
}
@Bean
public Binding binding1(TopicExchange topic, Queue queue1) {
// Définir une relation de liaison, en liant la file d'attente 1 à l'échange de sujet avec une clé de routage de: *.tizi365.com
return BindingBuilder.bind(queue1).to(topic).with("*.tizi365.com");
}
@Bean
public Binding binding2(TopicExchange topic, Queue queue2) {
// Définir une relation de liaison, en liant la file d'attente 2 à l'échange de sujet avec une clé de routage de: *.baidu.com
return BindingBuilder.bind(queue2).to(topic).with("*.baidu.com");
}
}
Astuce : Lors de la liaison de la file d'attente 1 et de la file d'attente 2 à l'échange, les clés de routage définies utilisent toutes deux le * (astérisque) joker, qui correspond à un seul mot. Si remplacé par # (dièse), cela correspondrait à plusieurs mots.
4.2 Définir les écouteurs de file d'attente
Définissez les écouteurs de message en utilisant l'annotation RabbitListener pour consommer des messages à partir de files d'attente spécifiques.
package com.tizi365.rabbitmq.listener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
// Laisser Spring gérer la classe actuelle
@Component
public class DemoListener {
// Définir un écouteur, en spécifiant à quelle file d'attente écouter via le paramètre des files d'attente
@RabbitListener(queues = "tizi365.topic.queue1")
public void receive1(String msg) {
System.out.println("Message reçu de la file d'attente 1 : " + msg);
}
// Définir un écouteur, en précisant à quelle file d'attente écouter via le paramètre des files d'attente
@RabbitListener(queues = "tizi365.topic.queue2")
public void receive2(String msg) {
System.out.println("Message reçu de la file d'attente 2 : " + msg);
}
}
Étant donné que seule la file d'attente 1 a une clé de routage de *.tizi365.com lors de la liaison à l'échange, elle correspondra aux messages avec la clé de routage (www.tizi365.com). Par conséquent, seule la file d'attente 1 pourra recevoir des messages, tandis que la file d'attente 2 n'en recevra aucun en raison d'une clé de routage non adaptée.