Mô phỏng lại pattern Java RabbitMQ sử dụng TopicExchange, khác với pattern định tuyến (Direct) ở chỗ tham số định tuyến hỗ trợ kết nối mờ hơn. Vì sự linh hoạt của kết nối định tuyến, đây là mẫu phổ biến hơn. Kiến trúc được minh họa trong sơ đồ sau:
Gợi ý: Bất kể sử dụng mẫu làm việc RabbitMQ nào, sự khác biệt nằm ở loại sàn và các tham số định tuyến.
1. Bài hướng dẫn tiên quyết
Vui lòng đọc các phần sau đây trước để hiểu kiến thức liên quan:
- Các Khái Niệm Cơ Bản của RabbitMQ
- Nguyên Tắc Mẫu Chủ Đề của RabbitMQ
- Bắt Đầu Nhanh với Java và RabbitMQ (Phải đọc, vì các phần sau sẽ không lặp lại mã, chỉ hiển thị mã chính)
- Phần Mẫu Phát-Đăng ký cho Java RabbitMQ (Phải đọc, vì cú pháp mã gần như giống nhau, chỉ có loại sàn và các tham số định tuyến khác nhau)
2. Xác định Sàn Đề Tài
Trong Spring AMQP, lớp tương ứng với sàn Direct là TopicExchange. Chúng ta xác định sàn thông qua một lớp cấu hình 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() {
// Xác định sàn
// Tham số là tên sàn, phải là duy nhất
return new TopicExchange("tizi365.topic");
}
}
Gợi ý: Cả nhà sản xuất và người tiêu dùng thông điệp đều cần sàn.
3. Gửi Tin Nhắn
Chúng ta gửi thông điệp đến sàn, và sàn chuyển thông điệp đến các hàng đợi tương ứng dựa trên quy tắc định tuyến.
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;
// Cho mục đích minh họa, công việc lập lịch được sử dụng ở đây để gửi một tin nhắn mỗi giây
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void send() {
// Nội dung tin nhắn
String message = "Xin chào các bạn!";
// Gửi tin nhắn
// Tham số đầu tiên là tên sàn
// Tham số thứ hai là khóa định tuyến. Sàn đề tài chuyển thông điệp đến các hàng đợi phù hợp với khóa định tuyến
// Tham số thứ ba là nội dung thông điệp, hỗ trợ bất kỳ loại nào miễn là có thể được tuần tự hóa
template.convertAndSend(topic.getName(), "www.tizi365.com", message);
System.out.println("Tin nhắn được gửi: '" + message + "'");
}
}
Gợi ý: Chú ý đến tham số thứ hai "www.tizi365.com" trong phương thức convertAndSend, vì đó là một tham số quan trọng.
4. Nhận Tin Nhắn
4.1 Định nghĩa Hàng đợi & Liên kết Trao đổi
Để tiêu thụ các tin nhắn từ hàng đợi, bạn cần định nghĩa trước một hàng đợi và sau đó liên kết hàng đợi với trao đổi đích. Dưới đây, hai hàng đợi được định nghĩa và liên kết với cùng một trao đổi.
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() {
// Định nghĩa trao đổi
// Tham số là tên trao đổi, phải là duy nhất
return new TopicExchange("tizi365.topic");
}
@Bean
public Queue queue1() {
// Định nghĩa hàng đợi 1
return new Queue("tizi365.topic.queue1");
}
@Bean
public Queue queue2() {
// Định nghĩa hàng đợi 2
return new Queue("tizi365.topic.queue2");
}
@Bean
public Binding binding1(TopicExchange topic, Queue queue1) {
// Định nghĩa mối quan hệ liên kết, liên kết hàng đợi 1 với trao đổi chủ đề với một khóa định tuyến là: *.tizi365.com
return BindingBuilder.bind(queue1).to(topic).with("*.tizi365.com");
}
@Bean
public Binding binding2(TopicExchange topic, Queue queue2) {
// Định nghĩa mối quan hệ liên kết, liên kết hàng đợi 2 với trao đổi chủ đề với một khóa định tuyến là: *.baidu.com
return BindingBuilder.bind(queue2).to(topic).with("*.baidu.com");
}
}
Mẹo: Khi liên kết hàng đợi 1 và hàng đợi 2 với trao đổi, các khóa định tuyến được thiết lập đều sử dụng ký tự * (sao đổi chỗ), khớp với một từ duy nhất. Nếu thay đổi thành # (ký hiệu số thứ tự), nó sẽ khớp với nhiều từ.
4.2 Định nghĩa Người nghe Hàng đợi
Định nghĩa người nghe tin nhắn bằng cách sử dụng chú thích RabbitListener để tiêu thụ các tin nhắn từ các hàng đợi cụ thể.
package com.tizi365.rabbitmq.listener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
// Cho Spring quản lý lớp hiện tại
@Component
public class DemoListener {
// Định nghĩa người nghe, xác định hàng đợi nào để nghe qua tham số hàng đợi
@RabbitListener(queues = "tizi365.topic.queue1")
public void receive1(String msg) {
System.out.println("Nhận tin nhắn từ hàng đợi 1: " + msg);
}
// Định nghĩa người nghe, xác định hàng đợi nào để nghe qua tham số hàng đợi
@RabbitListener(queues = "tizi365.topic.queue2")
public void receive2(String msg) {
System.out.println("Nhận tin nhắn từ hàng đợi 2: " + msg);
}
}
Vì chỉ hàng đợi 1 có khóa định tuyến là *.tizi365.com khi liên kết với trao đổi, nó sẽ khớp với tin nhắn có khóa định tuyến (www.tizi365.com). Do đó, chỉ hàng đợi 1 sẽ nhận được tin nhắn, trong khi hàng đợi 2 sẽ không nhận được bất kỳ tin nhắn nào do không khớp khóa định tuyến.