Message hay Event là một khái niệm hay được dùng để mô tả các dữ liệu, sự kiện để gửi nhận trong hệ thống nội bộ để phân biệt với khái niệm Request - Response gửi nhận giữa client và server, chúng ta đừng nhầm lẫn với message trong ứng dụng chat. Trong bài này Dũng sẽ cùng các bạn đi tìm hiểu về spring messaging, một thư viện common hoá việc xử lý message nhé.
Khởi tạo module
Chúng ta sẽ khởi tạo module có tên messaging.
Cấu hình dự án
Chúng ta sẽ bổ sung thư viện spring-messaging vào tập tin messaging/pom.xml như sau:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>vn.techmaster</groupId>
<artifactId>mastering-spring-boot</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>messaging</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
Ở đây chúng ta vẫn sẽ sử dụng thư viện spring-context để quản lý các singleton.
Khai báo một kênh
Về bản chất thì spring-message sử dụng observer design pattern và quản lý các observer thông qua các lớp channel. Chúng ta có thể khai báo một channel như sau:
package vn.techmaster.messaging.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
import java.util.concurrent.Executors;
@Configuration
public class MessagingConfig {
@Bean
public SubscribableChannel messageChannel() {
return new ExecutorSubscribableChannel(
Executors.newSingleThreadExecutor()
);
}
}
Ở đây chúng ta khai báo một kênh có kiểu là ExecutorSubscribableChannel, kênh này sử dụng một đối tượng Executor, mỗi message có thể được xử lý bởi một luồng riêng biệt tuỳ theo số lượng thread mà chúng ta cung cấp cho Excecutor, ở đây mình đang sử dụng newSingleThreadExecutor tức là chỉ có 1 luồng mà thôi. Khi cung cấp nhiều luồng các bạn cũng cần phải để ý đến các vấn đề của xử lý đa luồng nhé.
Khai báo một lớp nguồn cấp Message
Một mô hình message bao giờ cũng có một nguồn cấp và một nguồn tiêu thụ, chúng ta có thể cài đặt lớp nguồn cấp MessageProducer như sau:
package vn.techmaster.messaging.producer;
import lombok.AllArgsConstructor;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class MessageProducer {
private final MessageChannel messageChannel;
public void sendMessage(String message) {
messageChannel.send(MessageBuilder.withPayload(message).build());
}
}
Lớp này chỉ đơn giản là sử dụng một kênh và gửi message vào kênh đó mà không cần xử lý gì thêm.
Cài đặt lớp tiêu thụ Message
Khi message đi vào một kênh, kênh đó sẽ phân phối đến các đối tượng tiêu thụ mà nó quản lý, cụ thể ở đây chúng ta có thể cài đặt một lớp MessageConsumer như sau:
package vn.techmaster.messaging.handler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;
@Component
public class MessageConsumer implements MessageHandler {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("Received message: " + message.getPayload());
}
}
Lớp này sẽ cài đặt giao diện MessageHandler mà spring cung cấp và tiêu thu message mà nó nhận được.
Khởi chạy chương trình
Chúng ta có thể khởi chạy chương trình thông qua lớp MessagingStartUp có mã nguồn như sau:
package vn.techmaster.messaging;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.messaging.SubscribableChannel;
import vn.techmaster.messaging.handler.MessageConsumer;
import vn.techmaster.messaging.producer.MessageProducer;
public class MessagingStartUp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(
"vn.techmaster.messaging"
);
SubscribableChannel channel = context.getBean(SubscribableChannel.class);
MessageConsumer handler = context.getBean(MessageConsumer.class);
channel.subscribe(handler);
MessageProducer producer = context.getBean(MessageProducer.class);
producer.sendMessage("Hello, Techmaster!");
}
}
Ơi đây chúng ta sẽ đăng ký đối tượng tiêu thụ tin nhắn với kênh, sau khi một message được gửi đi bởi nguồn cấp, đối tượng tiêu thụ sẽ nhận và xử lý tin nhắn này, kết quả chúng ta nhận được khi chạy chương trình sẽ như sau:
Received message: Hello, Techmaster!
Tổng kết
Như vậy chúng ta đã cùng nhau:
- Tìm hiểu về bản chất của spring messaging.
- Khai báo một kênh, một nguồn phát, một lớp tiêu thụ.
- Thử gửi một message.
Sách tham khảo
Bạn có thể tìm hiểu thêm về observer design pattern thông qua cuốn sách làm chủ các mẫu thiết kế kinh điển trong lập trình và đừng quên nhập mã giảm giá Tech10 để được giảm giá 10% nhé.
Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:
- Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
- Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
- Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a
Bình luận
10 điểm