Springboot怎么实现WebSocket通信(一)

news2025/7/21 10:08:15
文章示例环境配置信息
jdk版本:1.8
开发工具:Intellij iDEA 2020.1
springboot:2.3.9.RELEASE

什么是WebSocket?

WebSocket,是HTML5下一种新的协议,支持web浏览器和服务器端之间双向全双工通信 ,基于TCP协议实现。

WebSocket主要特性

1、WebSocket是一种全新的协议,不属于http无状态协议,协议名为“ws”;

2、WebSocket是基于TCP的,属于可靠性传输协议,按OSI网络模型划分,归属应用层协议;

3、WebSocket是双向通信协议,可以双向发送或接受信息,与http相比最明显的区别就是允许服务端向客户端浏览器主动推送数据,而HTTP是单向的,只能由客户端发起请求,服务端针对客户端请求作出响应;

4、使用WebSocket通信前,浏览器和服务器端需要先进行握手建立连接;

5、WebSocket在握手建立连接的时候,数据是通过HTTP传输的,但是在建立连接之后,真正传输数据的时候是不需要HTTP协议的;

6、WebSocket建立连接后,数据是以帧序列的形式传输,浏览器端与服务器端的发送和接受消息是在同一个持久连接上发起,即浏览器端与服务器端的WebSocket连接未断开时,不需要重新发起连接请求就可以多次发送和接受消息;在并发及交互负载流量大的情况下,极大节省了网络带宽资源,有明显的性能优势,实现了真正的“长连接”;

WebSocket基本使用演示

通过WebSocket功能特性来看,WebSocket是一个非常重要的有实际应用意义的通信协议,下面以单机模式下的Springboot项目中集成WebSocket,来学习一下WebSocket使用方法及主要功能特性。

后端

1、引入WebSocket所需要starter模块依赖包;

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、定义WebSocketConfig配置类,引入WebSocket的Springboot的自动配置类ServerEndpointExporter,这个配置类主要用于扫描WebSocket相关的注解;

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

3、定义一个WebSocket类,使用@Component注解把WebSocket类注册到Spring容器中,使用@ServerEndpoint注解把当前类定义成一个服务器端并标记好客户端发起WebSocket连接请求的URL;在WebSocket类内用到了四个注解:@Open、@Close、@OnMessage、@OnError:

@Open:当WebSocket连接建立成功后会触发这个注解修饰的方法;

@Close:当WebSocket连接关闭或中断后会触发这个注解修饰的方法;

@OnMessage:当客户端发送消息到服务端时,会触发这个注解修饰的方法;

@OnError:当 websocket 建立连接时出现异常会触发这个注解修饰的方法;

@Component
@ServerEndpoint("/websocket/{userId}")
@Slf4j
public class WebSocket {
    private Session session;
    private static Map<String, WebSocket> webSocketMap = new ConcurrentHashMap<>();
    /**
     * 客户端发起websocket连接请求成功建立连接时触发
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.webSocketMap.put(userId, this);
        log.info("【websocket消息】有新的连接, 总数:{}", webSocketMap.size());
    }

    /**
     * 客户端关闭时websocket连接时触发
     */
    @OnClose
    public void onClose(@PathParam("userId") String userId) throws IOException {
        session.close();
        this.webSocketMap.remove(userId);
        log.info("【websocket消息】连接断开, 总数:{}", webSocketMap.size());
    }

    /**
     * 客户端向服务端发送消息时触发
     * @param session
     * @param message
     * @throws IOException
     */
    @OnMessage
    public void onMessage(Session session,  String message) throws IOException {
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        String userId = requestParameterMap.get("userId").get(0);
        log.info("【websocket消息】收到客户端发来的消息:{}", message);
        if (message.startsWith("hello")) {
            session.getBasicRemote().sendText("你好,"+userId+"!信息已经收到,欢迎光临" + message.replace("hello", ""));
        }
    }
    /**
     * 当 websocket 建立连接时出现异常会触发
     * @param session
     */
    @OnError
    public void onError(Session session){
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        String userId = requestParameterMap.get("userId").get(0);
        log.info("连接异常,请求参数:"+userId);
    }
}

前端

在resources目录下的静态资源目录static下,新建一个index.html;

index.html的逻辑很简单,就是在页面上放三个按钮,分别用于建立websocket连接、关闭websocket连接、向服务端发送文本消息;具体的实现步骤是这样的:

1、引入jquery.js,这样就可以使用"$"符号了;

2、在body标签内分别放置三个按钮,标签id分别是open、close、send;

3、定义一个div标签,用来显示操作信息和从服务端发送过来的文本消息;

4、在<scrip>标签内,声明websocket变量,然后在open按钮的点击事件触发进,向服务端发起连接请求,这里要特别注意一下,请求的URL是:“ws://172.18.229.61/websocket/gaox2”;与http请求类似的是,http请求的开头是http,websocket请求的开头是ws;

5、与服务端比较类似的是,客户端在websocket连接建立后,也会注册websocket连接事件在连接成功建立、连接发生错误、接收到服务端消息、连接关闭时的回调方法;

6、websocket连接建立成功后,在发送信息、关闭连接按钮被触发时,编写相应的处理逻辑;

<!DOCTYPE HTML>
<html lang="en">
<head>
    <title>websocket测试</title>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="message"></div>
<input type="button" name="" id="open" value="建立连接"/>
<input type="button" name="" id="close" value="关闭连接">
<input type="button" name="" id="send" value="发送信息">
</body>
<script type="text/javascript">
    var websocket = null;
    $("#open").click(function () {
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            websocket = new WebSocket("ws://172.18.229.61/websocket/gaox2");
        } else {
            alert('Not support websocket')
        }
        //连接发生错误的回调方法
        websocket.onerror = function () {
            document.getElementById('message').innerHTML += ("发生错误") + '<br/>';
        };
        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            document.getElementById('message').innerHTML += ("建立连接") + '<br/>';
        }
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            console.log(event.data);
            document.getElementById('message').innerHTML += event.data + '<br/>';
        }
        //连接关闭的回调方法
        websocket.onclose = function () {
            document.getElementById('message').innerHTML += ("关闭连接") + '<br/>';
        }
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            alert("已关闭连接");
            websocket.close();
        }
    })
    var i = 0;
    $("#send").click(function () {
        i = i + 1;
        websocket.send("hello" + i);
    })
    $("#close").click(function () {
        websocket.close();
    })
</script>
</html>

测试结果

总结

至此,在Springboot项目中,如何使用WebSocket进行数据交互的基本方法就是这样了。其实还是挺简单的,主要就是两部分:1、前端如何发起请求和处理服务端发回的消息;2、后端处理如何处理前端发起的websocket请求以及如何主动发消息给浏览器端;

但是大家有没有发现一个问题:单机模式下,浏览器端向服务端发起websocket请求,服务端处理请求并主动发消息给浏览器端,这种点对点的通信确实不复杂,但是实际的业务场景中,大部分项目都是分布式部署的,一个工程布署了多个服务节点,前端并不直接请求具体服务节点,而是先到nginx或其他代理服务器,通过nginx的负载均衡机制再转发到具体的服务节点,浏览器端在发起websocket连接时,直接连接到具体的服务节点显然不太合适的,那么向nginx发起websocket连接,再由其转发到具体的节点是否可以呢?又是怎么配置的呢?另外服务端向客户端发送消息时,用到了session,当然这里的session和servlet的session不是一个session,servlet中的session是jvm级别的,本身是不支持跨节点共享的,那websocket的session是否支持跨节点共享?如果不支持,则用什么办法实现session的共享?

这篇文章和大家一块简单学习一下websocket的基本使用方法,下一篇文章再来和大家一块分享一下,如何把websocket应用到实际的业务开发中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/395203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

console使用方法介绍

console是在写前端Javascript时经常会使用到&#xff0c;我平时使用最多的是console.log&#xff0c;相比大多数人也是如此吧&#xff01; 下面一起来看一下强大的console吧&#xff01; 01函数&#xff08;属性&#xff09; 包含如下函数 / 属性&#xff1a;memory、assert、c…

2023年最新最全 VSCode 插件推荐

Visual Studio Code 是由微软开发的一款免费的、针对于编写现代Web和云应用的跨平台源代码编辑器。它包含了一个丰富的插件市场&#xff0c;提供了很多实用的插件。下面就来分享 2023 年前端必备的 VS Code 插件&#xff01; 前端框架 ES7 React/Redux/React-Native snippets …

洗地机哪个牌子比较好?家用洗地机推荐

洗地机是可以做到扫地的同时把地也拖了&#xff0c;可以做到高效清洁&#xff0c;减轻家务负担。还具有杀菌功能&#xff0c;不用担心拖完地之后地面还有细菌滋生啦&#xff0c;洗地机可以做到即洗即干&#xff0c;无需等待拖完地之后还潮湿不能走路&#xff0c;尤其对于木地板…

简述下 React 的事件代理机制?

React 并不会把所有的处理函数直接绑定在真实的节点上。而是把所有的事件绑定到结构的最外层&#xff0c;使用一个统一的事件监听器&#xff0c;这个事件监听器上维持了一个映射来保存所有组件内部的事件监听和处理函数。 当组件挂载或卸载时&#xff0c;只是在这个统一的事件…

LIN资料整理(一):LIN入门简介

目录 一、LIN是什么 1、LIN简介 2、LIN的适用场景 3、LIN协议版本 4、LIN的主从机节点、主从机任务与LIN总线特点 一、LIN是什么 1、LIN简介 LIN 是Local Interconnect Network 的缩写&#xff0c;是基于UART/SCI(Universal Asynchronous Receiver-Transmitter / Serial…

2023级社科院与杜兰大学金融管理硕士还有少量名额,期待与你共谱人生新篇章

我们都是平凡人&#xff0c;过着平凡的生活&#xff0c;但若能有所热爱有所坚持&#xff0c;便会发出自己的光芒。就像我们在社科院与杜兰大学金融管理硕士项目读研&#xff0c;通过更加系统的学习&#xff0c;不仅丰富了我们的知识&#xff0c;还提升了我们的思维&#xff0c;…

NB-IOT宣传这么多年,这次总算用好了吧

一、方案概述随着实体经济快速发展&#xff0c;石化、港口、货场、工地等区域规模日益扩大&#xff0c;厂区面积广阔、环境复杂、作业人员和车辆众多&#xff0c;如无法实时掌握工作人员状态及外来人员位置、外来车辆情况等问题&#xff0c;将存在非常大的安全隐患。今天小编介…

ChatGPT在工业领域的用法

在工业数字化时代&#xff0c;我们需要怎么样的ChatGPT&#xff1f; 近日&#xff0c;ChatGPT热度高居不下&#xff0c;强大的人机交互能力令人咋舌&#xff0c;在国内更是掀起一股讨论热潮。一时间&#xff0c;这场由ChatGPT引起的科技飓风&#xff0c;使得全球最顶尖科技力量…

notepad++学习小技巧

不要小瞧了notepadd 这个可是我们的cv好帮手。。。 实战1背景&#xff0c;我找一个同事要表结构 结果他给我了一个xml。顿时一懵&#xff0c;我也不知道为啥好像是从前端扣下来的。 建表我只需要 columnName, displayName当作是comment&#xff0c; dataTypeNamecolumnType借鉴…

【计算机视觉】Visual grounding系列

文章目录一、任务简介二、Visual grounding常用数据集与评估指标2.1 常用数据集2.2 评估指标三、Visual grounding主流做法一、任务简介 Visual grounding涉及计算机视觉和自然语言处理两个模态。 简要来说&#xff0c;输入是图片&#xff08;image&#xff09;和对应的物体描…

市场营销书籍推荐:《经理人参阅:市场营销》

要学好市场营销有什么好方法&#xff1f;答案是看书&#xff01;比起碎片化地去阅读一些文章或看一些相关视频&#xff0c;读书来得更实在些。倘若能静下心来好好读上一本系统性的市场营销书籍&#xff0c;学好营销管理将不会再是一件难事。然而&#xff0c;问题的关键是&#…

大模型分布式系统

背景&#xff1a;模型越来越大&#xff0c;训练复杂度越来越高&#xff0c;需要训练的时间也是越来越长。那么我们该如何在现有的硬件基础上对模型做训练呢。模型规模的扩大&#xff0c;对硬件&#xff08;算力、内存&#xff09;的发展提出要求。然而&#xff0c;因为 内存墙 …

2023年襄阳中级工程师职称评审通知出来了哟

襄阳市职称改革工作领导小组办公室关于做好2022年度襄阳市非公企业工程系列中级任职资格评审工作的通知 各县&#xff08;市、区&#xff09;人力资源和社会保障局&#xff08;职改办&#xff09;&#xff1a; 根据市职改办《关于做好2022年度全市职称评审工作的通知》&#x…

IT女神节(致敬中国IT界永远的女神严蔚敏-数据结构)

我们都知道程序数据结构算法。相信很多人都学过严蔚敏的数据结构的课程。作为一个码农&#xff0c;在这不管是3.7女神节&#xff0c;还是3.8妇女节。我觉得都有必要向这些教育界的老前辈致敬。今天我就梳理梳理&#xff0c;最经典的数据结构教材。 严蔚敏介绍&#xff08;来自…

HTML学习笔记入门到精通day01

零、 复习昨日 见代码 一、二阶段介绍 第一阶段 java基本语法 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aY95CV7t-1678153713499)(D:\前锋学习笔记\笔记\image-20230307094126248.png)] 二、HTML 2.1 HTML概念 ​ 网页&#xff0c;是网站中的一…

MS python学习(7)

Managing Keys - dotenv Managing keys usage of .env module 项目地址&#xff1a;https://github.com/theskumar/python-dotenv Reads the key,value pair from .env and adds them to environment variable. 将key明文&#xff08;hard code&#xff09;形式写在script里…

java开发基础了解

Java 2023-03-07 1、开发工具 &#xff08;1&#xff09;jdk1.8 ,11,17,从11开始不免费 java纯面向对象------面向对象&#xff08;对象&#xff09;面向过程&#xff08;函数&#xff09;。就和JavaScript语言。 &#xff08;2&#xff09;Mysql8.0 &#xff08;3&#xff…

MySQL是怎样运行的——如何正确的使用索引

序言 下边我们将唠叨许多种让B树索引发挥最大效能的技巧和注意事项&#xff0c;不过大家要清楚&#xff0c;所有的技巧都是源自你对B树索引本质的理解&#xff0c;所以如果你还不能保证对B树索引充分理解&#xff0c;那么再次建议回过头把前边的内容看完了再来&#xff0c;要不…

TouchBoard 使用教程

一. 硬件采购: 其实我是想买原版的TouchBoard的,但是售罄了, 只能买国产的了,这是淘宝唯一一家提供技术支持的店铺(下面的库文件直接找店家要就行) https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.3c3a645epX97Bf&ft=t&id=706464470339 其他硬件…

Day10-网页布局实战CSS3

一 补充 1 画三角形 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevi…