百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

SpringBoot 使用WebSocket打造在线聊天室(基于注解)

bigegpt 2024-10-19 02:52 11 浏览

原文地址:https://dwz.cn/87Mq3Br1

作者:yizhiwazi

推荐WebSocket的三大理由:

  • 1、采用全双工通信,摆脱传统HTTP轮询的窘境。
  • 2、采用W3C国际标准,完美支持HTML5。
  • 3、简单高效,容易上手。

学习目标

快速学会通过WebSocket编写简单聊天功能。

温馨提示:

1、WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

2、浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

3、当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

使用教程

一、打造 WebSocket 聊天客户端

温馨提示:得益于W3C国际标准的实现,我们在浏览器JS就能直接创建WebSocket对象,再通过简单的回调函数就能完成WebSocket客户端的编写,非常简单!接下来让我们一探究竟。

使用说明:

使用步骤:1、获取WebSocket客户端对象。

例如: var webSocket = new WebSocket(url);

使用步骤:2、获取WebSocket回调函数。

例如:webSocket.onmessage = function (event) {console.log('WebSocket收到消息:' + event.data);

使用步骤:3、发送消息给服务端

例如:webSokcet.send(jsonStr) 结合实际场景 本案例采用JSON字符串进行消息通信。

具体实现:

下面是本案例在线聊天的客户端实现的JS代码,附带详细注释。

<script>
 /**
 * WebSocket客户端
 *
 * 使用说明:
 * 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
 * 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
 */
 function getWebSocket() {
 /**
 * WebSocket客户端 PS:URL开头表示WebSocket协议 中间是域名端口 结尾是服务端映射地址
 */
 var webSocket = new WebSocket('ws://localhost:8080/chat');
 /**
 * 当服务端打开连接
 */
 webSocket.onopen = function (event) {
 console.log('WebSocket打开连接');
 };
 /**
 * 当服务端发来消息:1.广播消息 2.更新在线人数
 */
 webSocket.onmessage = function (event) {
 console.log('WebSocket收到消息:%c' + event.data, 'color:green');
 //获取服务端消息
 var message = JSON.parse(event.data) || {};
 var $messageContainer = $('.message-container');
 //喉咙发炎
 if (message.type === 'SPEAK') {
 $messageContainer.append(
 '<div class="mdui-card" style="margin: 10px 0;">' +
 '<div class="mdui-card-primary">' +
 '<div class="mdui-card-content message-content">' + message.username + ":" + message.msg + '</div>' +
 '</div></div>');
 }
 $('.chat-num').text(message.onlineCount);
 //防止刷屏
 var $cards = $messageContainer.children('.mdui-card:visible').toArray();
 if ($cards.length > 5) {
 $cards.forEach(function (item, index) {
 index < $cards.length - 5 && $(item).slideUp('fast');
 });
 }
 };
 /**
 * 关闭连接
 */
 webSocket.onclose = function (event) {
 console.log('WebSocket关闭连接');
 };
 /**
 * 通信失败
 */
 webSocket.onerror = function (event) {
 console.log('WebSocket发生异常');
 };
 return webSocket;
 }
 var webSocket = getWebSocket();
 /**
 * 通过WebSocket对象发送消息给服务端
 */
 function sendMsgToServer() {
 var $message = $('#msg');
 if ($message.val()) {
 webSocket.send(JSON.stringify({username: $('#username').text(), msg: $message.val()}));
 $message.val(null);
 }
 }
 /**
 * 清屏
 */
 function clearMsg(){
 $(".message-container").empty();
 }
 /**
 * 使用ENTER发送消息
 */
 document.onkeydown = function (event) {
 var e = event || window.event || arguments.callee.caller.arguments[0];
 e.keyCode === 13 && sendMsgToServer();
 };
</script>

========================================================================

二、打造 WebSocket 聊天服务端

温馨提示:得益于SpringBoot提供的自动配置,我们只需要通过简单注解@ServerEndpoint就就能创建WebSocket服务端,再通过简单的回调函数就能完成WebSocket服务端的编写,比起客户端的使用同样非常简单!

使用说明:

首先在POM文件引入spring-boot-starter-websocket 、thymeleaf 、FastJson等依赖。

使用步骤:1、开启WebSocket服务端的自动注册。

【这里需要特别提醒:ServerEndpointExporter 是由Spring官方提供的标准实现,用于扫描ServerEndpointConfig配置类和@ServerEndpoint注解实例。使用规则也很简单:1.如果使用默认的嵌入式容器 比如Tomcat 则必须手工在上下文提供ServerEndpointExporter。2. 如果使用外部容器部署war包,则不要提供提供ServerEndpointExporter,因为此时SpringBoot默认将扫描服务端的行为交给外部容器处理。】

@Configuration
public class WebSocketConfig {
 @Bean
 public ServerEndpointExporter serverEndpointExporter() {
 return new ServerEndpointExporter();
 }
}

使用步骤:2、创建WebSocket服务端。

核心思路:

  • ① 通过注解@ServerEndpoint来声明实例化WebSocket服务端。
  • ② 通过注解@OnOpen、@OnMessage、@OnClose、@OnError 来声明回调函数。
  • ③ 通过ConcurrentHashMap保存全部在线会话对象。
@Component
@ServerEndpoint("/chat")//标记此类为服务端
public class WebSocketChatServer {
 /**
 * 全部在线会话 PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
 */
 private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();
 /**
 * 当客户端打开连接:1.添加会话对象 2.更新在线人数
 */
 @OnOpen
 public void onOpen(Session session) {
 onlineSessions.put(session.getId(), session);
 sendMessageToAll(Message.jsonStr(Message.ENTER, "", "", onlineSessions.size()));
 }
 /**
 * 当客户端发送消息:1.获取它的用户名和消息 2.发送消息给所有人
 * <p>
 * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数!
 */
 @OnMessage
 public void onMessage(Session session, String jsonStr) {
 Message message = JSON.parseObject(jsonStr, Message.class);
 sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size()));
 }
 /**
 * 当关闭连接:1.移除会话对象 2.更新在线人数
 */
 @OnClose
 public void onClose(Session session) {
 onlineSessions.remove(session.getId());
 sendMessageToAll(Message.jsonStr(Message.QUIT, "", "下线了!", onlineSessions.size()));
 }
 /**
 * 当通信发生异常:打印错误日志
 */
 @OnError
 public void onError(Session session, Throwable error) {
 error.printStackTrace();
 }
 /**
 * 公共方法:发送信息给所有人
 */
 private static void sendMessageToAll(String msg) {
 onlineSessions.forEach((id, session) -> {
 try {
 session.getBasicRemote().sendText(msg);
 } catch (IOException e) {
 e.printStackTrace();
 }
 });
 }
}
  • ④ 通过会话对象 javax.websocket.Session 来发消息给客户端。
/**
 * WebSocket 聊天消息类
 */
package com.hehe.chat;
import com.alibaba.fastjson.JSON;
/**
 * WebSocket 聊天消息类
 */
public class Message {
 public static final String ENTER = "ENTER";
 public static final String SPEAK = "SPEAK";
 public static final String QUIT = "QUIT";
 private String type;//消息类型
 private String username; //发送人
 private String msg; //发送消息
 private int onlineCount; //在线用户数
 public static String jsonStr(String type, String username, String msg, int onlineTotal) {
 return JSON.toJSONString(new Message(type, username, msg, onlineTotal));
 }
 public Message(String type, String username, String msg, int onlineCount) {
 this.type = type;
 this.username = username;
 this.msg = msg;
 this.onlineCount = onlineCount;
 }
 //这里省略get/set方法 请自行补充
}

三、WebSocket在线聊天案例的视频演示

1、源码下载

至此,我们完成了客户端和服务端的编码,由于篇幅有限,本教程的页面代码并未完整贴上,想要完整的体验效果请在Github下载源码。

2、视频演示

上面一顿操作猛如虎,实际到底是啥样子呢,接下来由哈士奇童鞋为我们演示最终版的在线聊天案例:

四、全文总结

1、使用WebSocket用于实时双向通讯的场景,常见的如聊天室、跨系统消息推送等。

2、创建WebSocket客户端使用JS内置对象+回调函数+send方法发送消息。

3、创建WebSocket服务端使用注解声明实例+使用注解声明回调方法+使用Session发送消息。

相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...