Thông báo in-app
govex-cloud-notification đóng gói toàn bộ phần thông báo trong ứng dụng: tạo thông báo trực tiếp hoặc theo template, REST API cho danh sách/đọc/xoá, và đẩy realtime tới client qua WebSocket. Dependency còn định nghĩa contract trạng thái gửi để phối hợp gửi đa kênh (in-app, email, SMS) với service gửi bên ngoài.
Khi nào sử dụng
- Ứng dụng cần chuông thông báo cho người dùng: danh sách, số chưa đọc, đánh dấu đã đọc, xoá mềm.
- Cần quản lý mẫu thông báo trong database và sinh nội dung theo biến thay vì hard-code.
- Cần đẩy thông báo realtime qua WebSocket ngay khi bản ghi được tạo.
- Cần contract trạng thái gửi (
channel,delivery_status,idempotency_key...) để nối với bộ chuyển gửi đa kênh.
Cài đặt
Thêm dependency vào pom.xml — không khai version vì đã được quản lý qua BOM:
<dependency>
<groupId>vn.govex.cloud</groupId>
<artifactId>govex-cloud-notification</artifactId>
</dependency>
Nếu ứng dụng chưa dùng parent/BOM của Govex Cloud, xem hướng dẫn tại Cài đặt.
Cấu hình
| Property | Mô tả | Mặc định |
|---|---|---|
govex.notification.enabled | Bật/tắt dependency thông báo. | true |
govex.notification.websocket.enabled | Bật/tắt WebSocket realtime. | true |
govex.notification.websocket.endpoint | Đường dẫn WebSocket. | /api/v1/ws/notifications |
govex.notification.websocket.allowed-origin-patterns | Pattern origin được phép (phân tách bằng dấu phẩy). | * |
govex.notification.websocket.max-text-message-size | Kích thước tối đa text message (bytes). | 65536 |
govex.notification.websocket.max-binary-message-size | Kích thước tối đa binary message (bytes). | 65536 |
govex.notification.websocket.send-time-limit | Thời gian gửi tối đa cho một session (ms). | 10000 |
govex.notification.websocket.send-buffer-size-limit | Giới hạn buffer gửi (bytes). | 524288 |
govex.notification.websocket.max-session-idle-timeout | Idle timeout của session (ms). | 300000 |
Sử dụng
Cấu hình tối thiểu:
govex:
notification:
enabled: true
websocket:
enabled: true
endpoint: /api/v1/ws/notifications
Tạo thông báo trực tiếp:
@Service
@RequiredArgsConstructor
public class TaskNotifier {
private final NoticeService noticeService;
public String notifyAssigned(String userId, String taskName) {
NoticeCreateRequest request = new NoticeCreateRequest();
request.setTargetUserId(userId);
request.setCategory("TASK");
request.setNoticeType("TASK_ASSIGNED");
request.setTitle("Bạn có công việc mới");
request.setContent("Công việc " + taskName + " đã được gán cho bạn");
return noticeService.createNotice(request);
}
}
Gửi theo template — biến trong template có dạng ${key} và được thay từ variables:
NoticeSendRequest request = new NoticeSendRequest();
request.setTemplateType("TASK_ASSIGNED");
request.setTargetUserId("user-123");
request.setVariables(Map.of("taskId", "456", "taskName", "Review hồ sơ"));
NoticeDeliveryResult result = noticeService.sendNoticeWithResult(request);
createNotice/sendNoticeWithResultchống trùng theoidempotencyKeyhoặcnotificationRequestId: bản ghi đã tồn tại được trả lại thay vì tạo mới.- Template bị vô hiệu hoá trả
deliveryStatus=FAILEDcùngerrorCode=TEMPLATE_DISABLED.
REST API cho client (prefix /api/v1/notices):
| Method | Endpoint | Mô tả |
|---|---|---|
POST | /api/v1/notices | Tạo thông báo trực tiếp. |
POST | /api/v1/notices/send | Gửi theo template. |
POST | /api/v1/notices/delivery-callback | Bộ chuyển gửi cập nhật trạng thái gửi. |
GET | /api/v1/notices | Danh sách thông báo của người dùng hiện tại. |
GET | /api/v1/notices/icon | Danh sách cho icon chuông (ưu tiên chưa đọc). |
GET | /api/v1/notices/statistics | Thống kê số chưa đọc. |
POST | /api/v1/notices/{id}/read, /read, /read-all | Đánh dấu đã đọc một/nhiều/tất cả. |
POST | /api/v1/notices/{id}/unread | Đánh dấu chưa đọc. |
POST | /api/v1/notices/{id}/delete | Xoá mềm thông báo. |
GET | /api/v1/notices/categories | Danh mục thông báo. |
Quản lý mẫu thông báo qua /api/v1/notice-templates (tìm kiếm, chi tiết theo id/type, tạo, sửa, xoá mềm, bật/tắt trạng thái).
Kết nối WebSocket từ client tới ws://{host}/api/v1/ws/notifications. Sau khi kết nối thành công client nhận event notice.connected; mỗi thông báo mới nhận event notice.created kèm dữ liệu NoticeVO; gửi text ping để nhận notice.pong. Kết nối được xác thực ngay ở bước handshake nên client cần gửi kèm thông tin đăng nhập.
Lưu ý
- Cần có
govex-cloud-data-jpa,govex-cloud-security,govex-cloud-web; các bảnguser_notices,notice_templatesphải tồn tại trước khi dùng — dependency có sẵn script SQL cho MariaDB và Oracle, không kèm changelog Liquibase. - Các API đọc/đánh dấu/xoá lấy người dùng hiện tại từ security context; thiếu user sẽ ném lỗi
NOTICE_004. - API mẫu thông báo yêu cầu quyền
notice-template(list,detail,create,edit,delete) — cần cấu hình phân quyền của ứng dụng host. - Xoá thông báo là soft delete; thông báo đã xoá không còn trong danh sách nhưng vẫn giữ bản ghi.
- Realtime chỉ được đẩy sau khi transaction tạo thông báo commit, và chỉ khi
pushRealtime=true(mặc định) cùng WebSocket đang bật. max-session-idle-timeouthiện được khai báo trong cấu hình nhưng chưa được áp dụng khi đăng ký WebSocket.- Muốn gửi đa kênh, service thông báo bên ngoài có thể consume payload broadcast qua Kafka topic
notice-broadcastdo dependency định nghĩa; dependency không tự consume topic này.