Chuyển tới nội dung chính

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

PropertyMô tảMặc định
govex.notification.enabledBật/tắt dependency thông báo.true
govex.notification.websocket.enabledBật/tắt WebSocket realtime.true
govex.notification.websocket.endpointĐường dẫn WebSocket./api/v1/ws/notifications
govex.notification.websocket.allowed-origin-patternsPattern origin được phép (phân tách bằng dấu phẩy).*
govex.notification.websocket.max-text-message-sizeKích thước tối đa text message (bytes).65536
govex.notification.websocket.max-binary-message-sizeKích thước tối đa binary message (bytes).65536
govex.notification.websocket.send-time-limitThời gian gửi tối đa cho một session (ms).10000
govex.notification.websocket.send-buffer-size-limitGiới hạn buffer gửi (bytes).524288
govex.notification.websocket.max-session-idle-timeoutIdle 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/sendNoticeWithResult chống trùng theo idempotencyKey hoặc notificationRequestId: 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=FAILED cùng errorCode=TEMPLATE_DISABLED.

REST API cho client (prefix /api/v1/notices):

MethodEndpointMô tả
POST/api/v1/noticesTạo thông báo trực tiếp.
POST/api/v1/notices/sendGửi theo template.
POST/api/v1/notices/delivery-callbackBộ chuyển gửi cập nhật trạng thái gửi.
GET/api/v1/noticesDanh sách thông báo của người dùng hiện tại.
GET/api/v1/notices/iconDanh sách cho icon chuông (ưu tiên chưa đọc).
GET/api/v1/notices/statisticsThố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}/deleteXoá mềm thông báo.
GET/api/v1/notices/categoriesDanh 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ảng user_notices, notice_templates phả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-timeout hiệ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-broadcast do dependency định nghĩa; dependency không tự consume topic này.