53、springboot对websocket的支持有两种方式-------1、基于注解开发 WebSocket ,简洁实现多人聊天界面

news2024/9/22 11:38:33

基于注解开发 WebSocket

–注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些

★ WebSocket的两种开发方式

▲ Spring Boot为WebSocket提供了两种开发方式:

  • 基于spring-boot-starter-websocket.jar开发WebSocket

  • 基于Spring WebFlux开发WebSocket

两种方式对比:
springboot API
在这里插入图片描述

Socket:套接字。
插座。
在通信的两端分别建立虚拟的Socket(插座),网络协议就会负责在两个Socket之间建立虚拟线路。然后通信的两端即可通过该虚拟线路进行实时的、可靠的通信。

WebSocket 就是在服务器与客户端浏览器之间的建立双向通信的Socket。从而保证服务器与客户端浏览器之间可进行实时的双向通信。

▲ 传统Web应用: 请求 - 响应。 这种模型没办法让服务器主动将数据推送客户端的浏览器。 还有比如SSE(服务器事件机制)

★ 基于Spring Boot自动配置来开发WebSocket

两步:

(1)定义一个WebSocket处理类

该处理类有两种开发方式(历史原因造成):

第一种方式:   - 直接使用JDK提供的 WebSocket注解 修饰处理方法,
                并使用 @ServerEndpoint  注解修饰该处理类即可。
                WebSocket注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些
  ——这种方式下方法签名可以随便写,方法参数也可以自行定义,非常灵活。
  官方也推荐尽量使用第一种方式

第二种方式:    - 实现WebSocketHandler接口、并实现该接口中定义的各种处理方法。
  ——Java语法规定,实现接口时,实现的方法必须与接口中定义的方法有相同的方法签名。
  ——这种方式就不够灵活。

(2)配置或导出WebSocket处理类

如果采用注解方式开发WebSocket处理类,
这一步只需要在 Spring容器 中配置一个ServerEndpointExporter Bean  (导出器)即可。
该导出器会负责将容器中所有的@ServerEndpoint注解修饰的处理Bean都导出成WebSocket。
因此无论程序有多少个WebSocket处理Bean,导出器Bean只要配置一个即可。
——非常简单、方便。

如果采用是实现接口的方式开发WebSocket处理类,
这一步就需要使用WebSocketConfigurer来配置WebSocket。

代码演示

创建项目
在这里插入图片描述

开发websocket的两步。
在这里插入图片描述

注解:@PathParam()

属于 WebSocket 的,用于获取路径上的参数。
在这里插入图片描述

发送消息的简单解释:
在这里插入图片描述

完整代码:

前端页面
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title> 基于WebSocket的多人聊天 </title>
	<script type="text/javascript">
		// 定义Web Socket对象
		var webSocket = null;
		let sendMsg = function()
		{
			if (webSocket == null || webSocket.readyState != 1)
			{
				document.getElementById('show').innerHTML
					+= "还未连接服务器,请先连接WebSocket服务器<br>";
				return;
			}
			let inputElement = document.getElementById('msg');
			// 发送消息
			webSocket.send(inputElement.value);
			// 清空单行文本框
			inputElement.value = "";
		}
		let connect = function()
		{
			let name = document.getElementById('name').value.trim();
			if (name == null || name == "")
			{
				document.getElementById('show').innerHTML
					+= "用户名不能为空<br>";
				return;
			}
			if (webSocket && webSocket.readyState == 1)
			{
				webSocket.close();
			}
			webSocket = new WebSocket("ws://127.0.0.1:8080/websocket/" + name);
			webSocket.onopen = function()
			{
				document.getElementById('show').innerHTML
					+= "恭喜您,连接服务器成功!<br>";
				document.getElementById('name').value = "";
				// 为onmessage事件绑定监听器,接收消息
				webSocket.onmessage= function(event)
				{
					// 接收、并显示消息
					document.getElementById('show').innerHTML
						+= event.data + "<br>";
				}
			};
		}
	</script>
</head>
<body>
<input type="text" size="20" id="name" name="name"/>
<input type="button" value="连接" onclick="connect();"/>
<div style="width:600px;height:240px;
	overflow-y:auto;border:1px solid #333;" id="show"></div>
<input type="text" size="80" id="msg" name="msg"/>
<input type="button" value="发送" onclick="sendMsg();"/>
</body>
</html>
MyWebSocketHandler 注解开发各方法
package cn.ljh.app.websocket;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


//基于注解开发 WebSocket --注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些

@Component
//这个注解需要指定指定映射地址
@ServerEndpoint("/websocket/{name}")
@Slf4j
public class MyWebSocketHandler
{
    //可以用注解来修饰不同的处理方法

    //假设是一个聊天室,map 中的key 是每个用户的 Session , value 是用户的name
    //创建一个线程安全的map ,用这个map来保存各用户的Session与name之间的对应关系
    public final static Map<Session,String> myClients = new ConcurrentHashMap<>();

    //当浏览器 与 Websocket 服务器建立连接的时候触发该方法
    //这个Session参数代表浏览器 与 WebSocket 服务器所建立连接会话,它用于通信。
    //这个 @PathParam() 相当于spring mvc 中的 @PathVariable,
    //都是用来获取路径中的参数--获取这个路径"/websocket/{name}" 中的name参数

    @OnOpen
    public void onOpen(Session session , @PathParam("name") String name)
    {
        //当用户登录的时候,把信息存进去
        myClients.put(session,name);
        log.debug("--------- onOpen ----------");
    }

    //当浏览器与WebSocket服务器 关闭的时候触发该方法
    @OnClose
    public void onClose(Session session)
    {
        //当连接关闭的时候,就将该客户端从map中删除
        myClients.remove(session);
        log.debug("--------- onClose ----------");
    }


    //当 WebSocket服务器 收到 浏览器 发送过来的消息时触发该方法
    @SneakyThrows
    @OnMessage
    public String onMessage(Session session, String message)
    {
        //收到消息,把消息广播给每个客户端      keySet()-->将map中的所有key存到set集合中
        for (Session client : myClients.keySet())
        {
            //此处的 client 就代表每个客户端
            //向client 发送信息,这个 client 代表了一个浏览器
            //getBasicRemote() 表示给客户端发送消息是同步的、阻塞的    ,   sendText()  发送消息
            client.getBasicRemote().sendText(myClients.get(session)+" 说:"+message);

        }
        log.debug("--------- onMessage ----------"+message);
        return null;
    }

    //但 WebSocket 服务器 与 浏览器通信出现异常时触发该方法
    //这个 Throwable 参数就代表了出现的异常
    @OnError
    public void onError(Session session, Throwable ex)
    {
        //当连接出现异常的时候,将该客户端从 Map 中栅除
        myClients.remove(session);
        log.debug("--------- onError ----------");
    }


}
MyWebSocketConfig 配置 WebSocket 导出器
package cn.ljh.app.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * author JH
 * date 2023/9/7  0007 12:28
 */

@Configuration
public class MyWebSocketConfig
{
    /*
     *配置 WebSocket 导出器
     *
     *   该导出器会负责将容器中所有的 @ServerEndpoint 注解修饰的 处理Bean 都导出成 WebSocket。
     *  因此无论程序有多少个 WebSocket 处理Bean,导出器Bean 只要配置一个即可。
     */

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

application.yml 配置日志级别
#给这个包设置日志级别为debug
logging:
  level:
    cn:
      ljh:
        app:
          websocket: debug

测试:

进行websocket连接
在这里插入图片描述

成功基于注解开发WebSocket 的多人聊天室
在这里插入图片描述

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

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

相关文章

常用消息中间件有哪些

RocketMQ 阿里开源&#xff0c;阿里参照kafka设计的&#xff0c;Java实现 能够保证严格的消息顺序 提供针对消息的过滤功能 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级消息堆积能力 RabbitMQ Erlang实现&#xff0c;非常重量级&#xff0c;更适…

只依赖OPENCV的工作服安全帽检测YOLOV8S

工地安全帽工作服检测Y8S&#xff0c;采用YOLOV8S训练模型&#xff0c;然后使用OPENCV的DNN调用&#xff0c;彻底拜托PYTORCH依赖&#xff0c;可以在C,PYTHON,ANDROID上跑。附件是C生成的效果测试&#xff08;只需解压将图片或者视频放入VIDEOS文件夹&#xff0c;文件夹没图片或…

宝宝餐椅儿童商品认证和ASTM F404检测标准的重要性

大家都知道儿童餐椅是宝宝饮食的重要伙伴。它们为宝宝提供了一个舒适的环境&#xff0c;让宝宝在吃饭的时候更愉快&#xff0c;更健康。然而&#xff0c;许多家长可能不知道&#xff0c;亚马逊美国站售卖的儿童餐椅需要进行一系列严格的认证&#xff0c;以保护我们宝贝们的安全…

平板触控笔哪款好用?好用的第三方apple pencil

而对于那些把ipad当做学习工具的人而言&#xff0c;苹果Pencil就成了必备品。但因为苹果Pencil太贵了&#xff0c;不少的学生们买不起。因此&#xff0c;最佳的选择还是平替电容笔&#xff0c;今天在这里整理了一些高性价比的电容笔&#xff01; 一、挑选电容笔的要点&#xf…

视频云存储/安防监控/AI分析/视频AI智能分析网关:占道经营算法

在国家倡导“地摊经济”的发展下&#xff0c;越来越多的人们投身于摆摊大潮&#xff0c;街道上都是随处可见的流动摊贩。虽然“地摊经济”有利于个人的经济增长&#xff0c;但有很多流动摊贩无视法规&#xff0c;随意摆摊或占道经营&#xff0c;这种行为不仅影响城市容貌&#…

Excel怎么批量生成文件夹

Excel怎么批量生成文件夹的链接: https://jingyan.baidu.com/article/ea24bc398d9dcb9b63b3312f.html

提升网络安全防御能力的几个方面

提升网络安全防御能力对于个人和组织来说都至关重要。网络安全是一个全面的概念&#xff0c;包括保护个人信息、防止恶意攻击和确保网络资源的安全。在这篇文章中&#xff0c;我将介绍几个方面来提高网络安全防御能力其中包括IP地址查询。 首先&#xff0c;IP地址查询是一种网…

Uniapp中使用uQRCode二维码跳转小程序页面

下载插件 uQRCode官网地址 引入插件 文件如下 //--------------------------------------------------------------------- // github https://github.com/Sansnn/uQRCode //---------------------------------------------------------------------let uQRCode = {};(functio…

colab使用(基础入门)——随手记

挂载到google drive 挂载目录/content/drive from google.colab import drive drive.mount(/content/drive) 图解colab读取Google Drive 文件 - 知乎 下载文件 !curl -L https://dl.fbaipublicfiles.com/imagebind/imagebind_huge.pth -o imagebind_ckpt参数&#xff1a;[-…

案例精选|菏泽公共交通集团日志审计系统建设方案

菏泽公共交通集团有限公司成立于1977年&#xff0c;是市属国有大型公益性企业。随着公交优先政策的出台和企业内部改革的不断深化&#xff0c;菏泽公交集团事业有了飞速发展。 随着5G、大数据、人工智能等数字化技术不断深化应用&#xff0c;近年来菏泽公交集团持续推进智慧公…

简述视频智能分析EasyCVR视频汇聚平台如何通过“AI+视频融合”技术规避八大特殊作业风险

视频智能分析EasyCVR视频汇聚平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上&#xff0c;视频云存储平台EasyCVR可实现视频实时直播、云端录像、视频云存储、视频存储磁盘阵列、录…

动态内存申请

动态内存申请 静态分配 1、 在程序编译或运行过程中&#xff0c;按事先规定大小分配内存空间的分配方式。int a [10] 2、 必须事先知道所需空间的大小。 3、 分配在栈区或全局变量区&#xff0c;一般以数组的形式。 4、 按计划分配 动态分配 1、在程序运行过程中&#xff0c…

十八、MySQL添加外键?

1、外键 外键是用来让两张表的数据之间建立联系&#xff0c;从而保证数据的一致性和完整性。 注意&#xff0c;主表被关联的字段类型&#xff0c;必须和副表被关联的字段类型一致。 2、实际操作 &#xff08;1&#xff09;初始化两张表格&#xff1a; &#xff08;2&#x…

线程、并发相关---第六篇

系列文章目录 文章目录 系列文章目录一、为什么用线程池?解释下线程池参数?二、简述线程池处理流程一、为什么用线程池?解释下线程池参数? 1、降低资源消耗;提高线程利用率,降低创建和销毁线程的消耗。 2、提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线…

银行卡四要素验证API接口文档:支持手机号归属地验证

随着互联网和电商业务的不断发展&#xff0c;人们对于数字化支付方式的需求越来越强烈&#xff0c;因此银行卡验证成为了重要的支付安全措施。银行卡四要素验证API接口&#xff0c;就是为了解决这一问题而开发的。本文将针对银行卡四要素验证API接口&#xff0c;以支持手机号归…

Jetsonnano B01 笔记2:GPIO库-Pycharm远程调试-点灯

今日继续我的Jetsonnano 学习之路,今日主要学习使用Pycharm远程调试Jetsonnano以及驱动使用Jetsonnano的GPIO库&#xff0c;最终尝试使用jetson点亮第一个LED。 本文搬运成分较多&#xff0c;因为Jetsonnano资料比较少&#xff0c;做这些笔记方便自己以及大家查阅。 目录 一…

什么是IIFE(Immediately Invoked Function Expression)?它有什么作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐IIFE 的基本语法⭐IIFE 的主要作用⭐如何使用 IIFE 来创建私有变量和模块封装⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅…

【Unity】Unity坑的集锦之RenderTexture打包黑屏

问题&#xff1a;Camera Output Texture设置RenderTexture后&#xff0c;打包用来Save PNG&#xff0c;黑屏 如果你打AB 包&#xff0c;然后是相机的OutputTexture是拖拽的话&#xff0c;记得将包一起打入 或者你可以代码赋值 Camera.targetTexture await Loader.LoadAsset&l…

实时测试工具 Visual Studio 扩展 NCrunch 4.18 Crack

NCrunch Visual Studio 扩展 .NET 的终极实时测试工具 在编码时查看实时测试结果和内联指标。 下载v4.18 发布于 2023 年 7 月 17 日 跳过视频至&#xff1a; 代码覆盖率 指标 分布式处理 配置 发动机模式 Visual Studio 自动并发测试 NCrunch 是一个完全自动化的测试扩展&a…

地理地形sdk:Tatuk GIS Developer Kernel for .NET Crack

Tatuk GIS Developer Kernel for .NET 是一个变体&#xff0c;它是受控代码和 .NET GIS SDK&#xff0c;用于为用户 Windows 操作系统创建专业 GIS 软件的过程。它被认为是一个完全针对Win Forms 的.NET CIL&#xff0c;WPF 框架是针对C# 以及VB.NET、VC、Oxy 以及最终与.NET 的…