手把手搭建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进行消息的订阅。