手把手搭建WebSocket多人在線聊天室,就是這麼強

原文地址:https://dwz.cn/Z1O56dnu

前言

本文中搭建了一個簡易的多人聊天室,使用了WebSocket的基礎特性。

https://www.callicoder.com/spring-boot-websocket-chat-example/

本文內容摘要:

初步理解WebSocket的前後端交互邏輯手把手使用 SpringBoot + WebSocket 搭建一個多人聊天室Demo代碼源碼及其解釋前端展示頁面

此外,在下一篇文章中,我們將做到:

對該WebSocket聊天室進行分佈式改造,同時部署多臺機器來作為集群,支撐高併發。保存用戶session,並且在集群上實現session同步,比如實時展示當前在線的用戶!

正文

WebSocket多人在線聊天室

本文工程源代碼:

https://github.com/qqxx6661/springboot-websocket-demo


新建工程

我們新建一個SpringBoot2的項目工程,在默認依賴中,添加websocket依賴:

<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-websocket/<artifactid>
/<dependency>


WebSocket 配置

我們先來設置websocket的配置,新建config文件夾,在裡面新建類WebSocketConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.*;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
}


代碼解釋:

@EnableWebSocketMessageBroker用於啟用我們的WebSocket服務器。

我們實現了WebSocketMessageBrokerConfigurer接口,並實現了其中的方法。

在第一種方法中,我們註冊一個websocket端點,客戶端將使用它連接到我們的websocket服務器。

withSockJS()是用來為不支持websocket的瀏覽器啟用後備選項,使用了SockJS。

方法名中的STOMP是來自Spring框架STOMP實現。STOMP代表簡單文本導向的消息傳遞協議。它是一種消息傳遞協議,用於定義數據交換的格式和規則。為啥我們需要這個東西?因為WebSocket只是一種通信協議。它沒有定義諸如以下內容:如何僅向訂閱特定主題的用戶發送消息,或者如何向特定用戶發送消息。我們需要STOMP來實現這些功能。

在configureMessageBroker方法中,我們配置一個消息代理,用於將消息從一個客戶端路由到另一個客戶端。

第一行定義了以“/app”開頭的消息應該路由到消息處理方法(之後會定義這個方法)。

第二行定義了以“/topic”開頭的消息應該路由到消息代理。消息代理向訂閱特定主題的所有連接客戶端廣播消息。

在上面的示例中,我們使用的是內存中的消息代理。

之後也可以使用RabbitMQ或ActiveMQ等其他消息代理。


創建 ChatMessage 實體

ChatMessage用來在客戶端和服務端中交互

我們新建model文件夾,創建實體類ChatMessage。

實體中,有三個字段:

type:消息類型content:消息內容sender:發送者

類型有三種:

CHAT: 消息JOIN:加入LEAVE:離開


創建Controller來接收和發送消息

創建controller文件夾,在controller文件夾添加類ChatController

代碼解釋:

我們在websocket配置中,從目的地以/app開頭的客戶端發送的所有消息都將路由到這些使用@MessageMapping註釋的消息處理方法。

例如,具有目標/app/chat.sendMessage的消息將路由到sendMessage()方法,並且具有目標/app/chat.addUser的消息將路由到addUser()方法


添加WebSocket事件監聽

完成了上述代碼後,我們還需要對socket的連接和斷連事件進行監聽,這樣我們才能廣播用戶進來和出去等操作。

創建listener文件夾,新建WebSocketEventListener類

代碼解釋:

我們已經在ChatController中定義的addUser()方法中廣播了用戶加入事件。因此,我們不需要在SessionConnected事件中執行任何操作。

在SessionDisconnect事件中,編寫代碼用來從websocket會話中提取用戶名,並向所有連接的客戶端廣播用戶離開事件。


創建前端聊天室頁面

我們在src/main/resources文件下創建前端文件,結構類似這樣:

static
└── css
└── main.css
└── js
└── main.js
└── index.html


1. HTML文件 index.html

HTML文件包含用於顯示聊天消息的用戶界面。它包括sockjs和stomp 兩個js庫。

SockJS是一個WebSocket客戶端,它嘗試使用本機WebSockets,併為不支持WebSocket的舊瀏覽器提供支持。STOMP JS是javascript的stomp客戶端。

筆者在文件裡使用了國內的CDN源

2. JavaScript main.js

添加連接到websocket端點以及發送和接收消息所需的javascript。

代碼解釋:

connect()函數使用SockJS和stomp客戶端連接到我們在Spring Boot中配置的/ws端點。

成功連接後,客戶端訂閱/topic/public,並通過向/app/chat.addUser目的地發送消息將該用戶的名稱告知服務器。

stompClient.subscribe()函數採用一種回調方法,只要消息到達訂閱主題,就會調用該方法。

其它的代碼用於在屏幕上顯示和格式化消息。

3. CSS main.css

整個項目結構如下:

啟動

啟動SpringBoot項目

效果入下:

補充:使用RabbitMQ代替內存作為消息代理

添加依賴:

然後將WebSocketConfig類中configureMessageBroker方法改為使用RabbitMq,完成!

如此一來,便可以通過RabbitMq進行消息的訂閱。