SpringBoot WebSocket之多人聊天室实现

  • WebSocket简介
    • 什么是WebSocket?
    • 为什么使用WebSocket?
    • WebSocket的技术特点:
    • WebSocket的技术优点:
    • WebSocket事件:
  • 实现聊天室的功能
    • 功能解析
      • 首先实现页面搭建:
      • 引入相关的依赖
      • 创建 WebSocketUtils 工具类
      • 创建接受消息类(ChatRoomServerEndpoint)
      • 在启动类中加入@EnableWebSocket 开启 WebSocket 功能
      • 实现界面如下图所示:

WebSocket简介

什么是WebSocket?

WebSocket 协议是基于 TCP 的一种网络协议,它实现了浏览器器与服务器全双工(Full-duplex)通信——允许服务器主动发送信息给客户端。

为什么使用WebSocket?

以前,很多网站为了了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每 1 秒),由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断地向服务器发出请求,然而 HTTP 请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。在这种情况下,HTML 5 定义了WebSocket 协议,能更好得节省服务器资源和带宽,并且能够更实时地进行通讯。WebSocket 协议在 2008年诞生,2011 年成为国际标准,现在主流的浏览器都已经支持。

WebSocket的技术特点:

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebSocket的技术优点:

(1)较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有 2 至 10 字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的 4 字节的掩码。相对于 HTTP 请求每次都要携带完整的头部,此项开销显著减少了。
(2)更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于 HTTP 请求需要等待客户端发起请求服务端才能响应,延迟明显更更少;即使是和 Comet 等类似的长轮询比较,其也能在短时间内更更多次地传递数据。
(3)保持连接状态。与 HTTP 不同的是,Websocket 需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息,而 HTTP 请求可能需要在每个请求都携带状态信息(如身份认证等)。
(4)更好的二进制支持。Websocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容。 可以支持扩展。Websocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
(5)更好的压缩效果。相对于 HTTP 压缩,Websocket 在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

WebSocket事件:

(1)Websocket 使⽤用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。例如:ws://example.com/wsapi;wss://secure.example.com/
(2)Websocket 使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用80 端口;运行在 TLS 之上时,默认使用 443 端⼝。
(3)WebSocket事件的描述详解:

实现聊天室的功能

功能解析

(1)支持用户加入聊天室,对应到 Websocket 技术就是建立连接 onopen
(2)支持用户退出聊天室,对应到 Websocket 技术就是关闭连接 onclose
(3)支持用户在聊天室发送消息,对应到 Websocket 技术就是调用 onmessage 发送消息
(4)支持异常时提示,对应到 Websocket 技术 onerror

首先实现页面搭建:

  • 利用前端框架 Bootstrap 渲染页面,使用 HTML 搭建页面结构。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>chat room websocket</title><link rel="stylesheet" href="bootstrap.min.css"><script src="jquery-3.2.1.min.js" ></script>
</head>
<body class="container" style="width: 60%">
<div class="form-group" ></br><h5>聊天室</h5><textarea id="message_content"  class="form-control"  readonly="readonly" cols="50" rows="10"></textarea>
</div>
<div class="form-group" ><label for="in_user_name">用户姓名 &nbsp;</label><input id="in_user_name" value="" class="form-control" /></br><button id="user_join" class="btn btn-success" >加入聊天室</button><button id="user_exit" class="btn btn-warning" >离开聊天室</button>
</div>
<div class="form-group" ><label for="in_room_msg" >群发消息 &nbsp;</label><input id="in_room_msg" value="" class="form-control" /></br><button id="user_send_all" class="btn btn-info" >发送消息</button>
</div>
</body>
</html>

其中下面这段代码的功能主要是监听三个按钮的点击事件,当用户登录、离开、发送消息是调用对应的 WebSocket 事件,将信息传送给服务端。同时打开页面时创建了了 WebSocket 对象,页面会监控 WebSocket 事件,如果后端服务和前端通讯室将对应的信息展示在页面。

<script type="text/javascript">$(document).ready(function(){var urlPrefix ='ws://localhost:8080/chat-room/';var ws = null;$('#user_join').click(function(){var username = $('#in_user_name').val();if(username==''){alert("请输入用户名!");return;}var url = urlPrefix + username;ws = new WebSocket(url);ws.onopen = function () {console.log("建立 websocket 连接...");};ws.onmessage = function(event){//服务端发送的消息$('#message_content').append(event.data+'\n');};ws.onclose = function(){$('#message_content').append('用户['+username+'] 已经离开聊天室!');console.log("关闭 websocket 连接...");}});//客户端发送消息到服务器$('#user_send_all').click(function(){var msg = $('#in_room_msg').val();if(msg==''){alert("请填写消息!");return;}if(ws && msg!=''){ws.send(msg);}});// 退出聊天室$('#user_exit').click(function(){if(ws){ws.close();}});})
</script>
  • 完整的整合代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>chat room websocket</title><link rel="stylesheet" href="bootstrap.min.css"><script src="jquery-3.2.1.min.js" ></script>
</head>
<body class="container" style="width: 60%">
<div class="form-group" ></br><h5>聊天室</h5><textarea id="message_content"  class="form-control"  readonly="readonly" cols="50" rows="10"></textarea>
</div>
<div class="form-group" ><label for="in_user_name">用户姓名 &nbsp;</label><input id="in_user_name" value="" class="form-control" /></br><button id="user_join" class="btn btn-success" >加入聊天室</button><button id="user_exit" class="btn btn-warning" >离开聊天室</button>
</div>
<div class="form-group" ><label for="in_room_msg" >群发消息 &nbsp;</label><input id="in_room_msg" value="" class="form-control" /></br><button id="user_send_all" class="btn btn-info" >发送消息</button>
</div>
</body><script type="text/javascript">$(document).ready(function(){var urlPrefix ='ws://localhost:8080/chat-room/';var ws = null;$('#user_join').click(function(){var username = $('#in_user_name').val();if(username==''){alert("请输入用户名!");return;}var url = urlPrefix + username;ws = new WebSocket(url);ws.onopen = function () {console.log("建立 websocket 连接...");};ws.onmessage = function(event){//服务端发送的消息$('#message_content').append(event.data+'\n');};ws.onclose = function(){$('#message_content').append('用户['+username+'] 已经离开聊天室!');console.log("关闭 websocket 连接...");}});//客户端发送消息到服务器$('#user_send_all').click(function(){var msg = $('#in_room_msg').val();if(msg==''){alert("请填写消息!");return;}if(ws && msg!=''){ws.send(msg);}});// 退出聊天室$('#user_exit').click(function(){if(ws){ws.close();}});})
</script></html>

引入相关的依赖

  • 其中要注意spring-boot-starter-parent版本必须是2.1.0版本以上,如果是以下可能会有错误。
     <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

创建 WebSocketUtils 工具类

== 在创建服务端消息接收功能之前,我们先创建一个 WebSocketUtils 工具类,用来存储聊天室在线的用户信息,以及发送消息的功能。==

package com.lipeiyu;import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;public class WebSocketUtils {// 创建一个集合,里面存放所有的在线用户public static final Map<String, Session> ONLINE_USER_SESSIONS =new ConcurrentHashMap<>();// 给客户端发送信息public static void sendMessage( Session session , String message ){// 如果会话是空的,则什么也不干if( session == null ){return ;}// 如果不是空,我要创建远端的客户端断点,进行消息发送final RemoteEndpoint.Basic basic = session.getBasicRemote();if( basic == null ){return;}try {basic.sendText(message);} catch (IOException e) {e.printStackTrace();}}// 群发信息给所有在线的人(在线的人在集合里面)public static void sendAllMessage(String message){Collection<Session> sessions = ONLINE_USER_SESSIONS.values();for (Session session : sessions) {sendMessage(session , message);}}
}

创建接受消息类(ChatRoomServerEndpoint)

package com.lipeiyu;import java.io.IOException;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;import org.springframework.web.bind.annotation.RestController;@ServerEndpoint("/chat-room/{username}")
@RestController
public class ChatRoomServerEndpoint {// 检测到客户端创建连接成功了,我需要将该客户端添加到我们集合中(就是存在在线会话的集合)@OnOpenpublic void openSession(@PathParam("username") String username, Session session) {WebSocketUtils.ONLINE_USER_SESSIONS.put(username, session);        String str = String.format("欢迎%s进入聊天室来聊天!", username);        WebSocketUtils.sendAllMessage(str);}@OnMessagepublic void onMessage(@PathParam("username") String username , String message){WebSocketUtils.sendAllMessage("用户[" + username + "] : " + message);}@OnClosepublic void onClose(@PathParam("username") String username ,Session session){WebSocketUtils.sendAllMessage("用户[" + username + "] : 离开聊天室" );WebSocketUtils.ONLINE_USER_SESSIONS.remove(username);try {session.close();} catch (IOException e) {e.printStackTrace();}}@OnErrorpublic void onError(Session session, Throwable throwable) {try {session.close();} catch (IOException e) {e.printStackTrace();}}
}

在启动类中加入@EnableWebSocket 开启 WebSocket 功能

@EnableWebSocket
@SpringBootApplication
public class Springboot011Application {public static void main(String[] args) {SpringApplication.run(Springboot011Application.class, args);}@Beanpublic ServerEndpointExporter  serverEndpointExporter(){return new ServerEndpointExporter();}}

完成后启动服务,不要tomcat服务器启动,要SpringBoot项目自带的服务器启动。

实现界面如下图所示:


聊天室首页
输入相关对应信息进行测试如下:

可以在打开一个浏览器进行相关测试如下 :

最终结果如下:

  • 通过上面的测试我们可以看出来多人聊天室完成了。上面的知识内容讲解都是在实训中拷贝老师的xmind文档,同时通过今天的学习,收获很多,对WebSocket的相关学习有了很深的理解和学习。如果上述内容有侵权,请联系本人给予删除。

SpringBoot WebSocket之多人聊天室实现相关推荐

  1. Nodejs+webSocket搭建多人聊天室

    NodeJs+webSocket搭建多人聊天室 准备的东西: 第一步:安装插件并且完善服务端 第二步 :搭建客户端并与服务端的通信 第三步 :添加CSS样式 第四步:总结 今天花了一个上午的时间去学习 ...

  2. 基于SpringBoot的websocket的多人聊天室项目

    文章目录 1.websocket 什么是websocket? 使用步骤 1.引入依赖 2.建立配置类 3.业务层 Web类 HTML 遇到的问题 项目github地址 1.websocket 什么是w ...

  3. JAVA利用websocket实现多人聊天室、私信(附源码)

    声明:此文为原创,转载请声明出处! 小编曾在毕业设计中用到了聊天室这个功能,现在稍作整理分享一下,希望能对大家有所帮助,有不足之处请指出 在学习websocket前,首先得知道它的一些基本操作,可参考 ...

  4. websocket多人聊天php,php-notes/基于websocket实现多人聊天室.md at master · dd-code-site/php-notes · GitHub...

    WebSocket 连接 断开 格式:ws://IP或域名:端口 发送 消息 var websocket; var wsUrl; function connect() { try { wsUrl = ...

  5. [项目] Vue+Element-Plus+SpringBoot+WebSocket 简洁好看的聊天室项目(附源码)

  6. SpringBoot——SpringBoot集成WebSocket实现简单的多人聊天室

    文章目录: 1.什么是WebSocket? 2.Java中的WebSocket API 2.1 WebSocket开发中的相关注解及API方法 2.2 前端技术对WebSocket的支持 3.多人聊天 ...

  7. WebSocket实现简易版的多人聊天室

    一.websocket简介           WebSocket是一种在单个TCP连接上进行全双工通信的协议.WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推 ...

  8. socket.io php 聊天室,WebSocket学习(一)——基于socket.io实现简单多人聊天室

    前言 什么是Websocket呢? 我们都知道在Http协议中,客户端与服务器端的通信是靠客户端发起请求,然后服务器端收到请求再进行回应,这个过程中,客户端是主动的,服务器端是被动的.Websocke ...

  9. SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室

    SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室 一.概述 WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 ...

最新文章

  1. centos 7.2 yum mysql_20191209_Centos7.2使用yum安装mysql
  2. Vue中添加新的路由并访问
  3. 《CLR Via C# 第3版》笔记之(十) - 可选参数和可变数量参数
  4. 关于cocos2d-x 和安卓之间的相互调用
  5. arcgis python-ArcGIS Python 资源收藏
  6. python输入语句-python2 和 pyhton3 输入语句写法
  7. 直播协议HTTP-FLV标准解读与技术实现
  8. FL-EM7688 Smart评估板openwrt开发环境搭建(linux固件部分)
  9. [转]jQuery Validate使用说明
  10. 在DOS命令行执行MYSQL语句
  11. 信息学奥赛一本通 1166:求f(x,n)
  12. 大数据学习笔记35:Hive - 内部表与外部表
  13. Bitdefender Total Security 2014 Free 6 Months 12 month License Key
  14. IOC容器-Autofac在MVC中实现json方式注入使用
  15. C/C++遍历目录下的所有文件(Windows篇)
  16. java setproperty 未生效_Java System类setProperty()方法及示例
  17. 2020央行全面降准,货币政策操作仍有较大空间
  18. Burp抓取MuMu模拟器数据包
  19. Verilog语言基础
  20. html母亲节主题网页源码jd

热门文章

  1. e级计算机 科学计算,E级超级计算机系统与类脑计算的应用与发展趋势
  2. PHP中在公用PHP文件中使用相对路径的正确方法
  3. 中国式报表——介绍信实现(润乾 vs 帆软)
  4. VMware虚拟机NAT模式配置静态IP
  5. 利用itext复制pdf模板并插入图片
  6. Ajax设置超时时长,jquery ajax超时设置
  7. Flash2Cocos2d-x
  8. unity  通过键盘控制角色的移动和旋转
  9. 利用LSTM作多元回归预测
  10. 【如何带领好一个团队】