SpringBoot+WebSocket

SpringBoot+WebSocket

1.导入依赖:

-- Spring Boot 2.x 使用 javax.websocket-- Spring Boot 3.x 使用 jakarta.websocket<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
</dependency>
package com.js.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** websocket配置类中*/
@Configuration
public class WebSocketConfig {/***  第一个配置是因为使用springboot内置容器,自己开发时需要配置,如果有独立的容器需要将其注释掉,* 也就意味着,如果将项目打成WAR包,部署到服务器,使用Tomcat启动时,需要注释掉ServerEndpointExporter配置;* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}/*** MyEndpointConfigure配置是因为我的需求需要,需要在websocket类中注入service层或者dao层的接口,* MyEndpointConfigure配置就是为了解决websocket无法注入的问题,如果没有需要可以不用配置* @return*/@Beanpublic MyEndpointConfigure newConfigure() {return new MyEndpointConfigure();}
}
package com.js.httpclenlient;
import com.hy.core.toolkit.util.CollectionUtil;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;/*** @author* @Description: WebSocket服务端代码,包含接收消息,推送消息等接口*/
@Component
@ServerEndpoint(value = "/socket/{archivecode}")
public class WebSocketServer {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static AtomicInteger online = new AtomicInteger();//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象的session。private static Map<Long, List<Session>> sessionPools = new HashMap<>();@Resourceprivate RemoteAccessClient remoteAccessClient;/*** 发送消息方法* @param sessions 客户端与socket建立的会话* @param message 消息* @throws IOException*/public void sendMessage(List<Session> sessions, String message) throws IOException{if(CollectionUtil.isNotEmpty(sessions)){sessions.stream().forEach(session-> {try {session.getBasicRemote().sendText(message);} catch (IOException e) {throw new RuntimeException(e);}});}}/*** 连接建立成功调用* @param session 客户端与socket建立的会话* @param archivecode 客户端的archivecode*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "archivecode") Long archivecode){List<Session> sessions = sessionPools.get(archivecode);if(CollectionUtil.isNotEmpty(sessions)){sessions.add(session);sessionPools.put(archivecode, sessions);}else {List<Session> sessionList = new ArrayList<>();sessionList.add(session);sessionPools.put(archivecode, sessionList);}addOnlineCount();System.out.println(archivecode + "加入webSocket!当前人数为" + online);try {sendMessage( sessions, "欢迎" + archivecode + "加入连接!");} catch (IOException e) {throw new IllegalArgumentException("webSocket建立连接失败");}}/*** 关闭连接时调用* @param 关闭连接的客户端的session*/@OnClosepublic void onClose(Session session,@PathParam(value = "archivecode") String archivecode){Set<Long> sessionkey = sessionPools.keySet();for (Long key : sessionkey) {List<Session> sessions = sessionPools.get(key);boolean contains = sessions.contains(session);if(contains){sessions.remove(session);}}sessionPools.remove(archivecode);subOnlineCount();System.out.println(archivecode + "断开webSocket连接!当前人数为" + online);}/*** 收到客户端消息时触发(群发)* @param message* @throws IOException*/@OnMessagepublic void onMessage(String message) throws IOException{Set<Long> companyIds = sessionPools.keySet();for (Long companyid : companyIds) {List<Session> sessions = sessionPools.get(companyid);try {sendMessage(sessions, message);} catch(Exception e){e.printStackTrace();}}}/*** 发生错误时候* @param session* @param throwable*/@OnErrorpublic void onError(Session session, Throwable throwable){System.out.println("发生错误");throwable.printStackTrace();}/*** 给指定用户发送消息* @param archivecode 用户名* @param message 消息* @throws IOException*/public void sendInfo(Long archivecode, String message){List<Session> sessions = sessionPools.get(archivecode);try {sendMessage(sessions, message);}catch (Exception e){e.printStackTrace();}}/*** 根据用户名获取session会话对象* @param archivecode* @return*/public  List<Session> getSession(Long archivecode){List<Session> sessions = sessionPools.get(archivecode);return sessions;}public static void addOnlineCount(){online.incrementAndGet();}public static void subOnlineCount() {online.decrementAndGet();}}
package com.js.controller;import cn.hutool.json.JSONUtil;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;/***  6.密集架报警信息实时更新获取*/@RequestMapping(value = "/denseRack/alarm", method = RequestMethod.POST)public void testSocket1(@RequestBody FilealertInformation dto) throws JsonProcessingException {Long archiveCompanyId = ThreadLocalUtil.getArchiveCompanyId();dto.setPageRefreshType("warning");String s = JSONUtil.toJsonStr(dto);webSocketServer.sendInfo(archiveCompanyId, s);}

测试发送

在这里插入图片描述

结果

在这里插入图片描述

Spring boot接入websocket时,启动报错

Spring Boot 2.x

javax.websocket.server.ServerContainer not available

Spring Boot 3.x

jakarta.websocket.server.ServerContainer not available

问题原因

1. 因为spring boot内带tomcat,tomcat中的websocket会有冲突。
解决方案:​ spring boot启动时排除tomcat依赖包即可<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
</dependency>

@SpringBootTest启动时没有启动servlet

解决方案:@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

Spring Boot 与WebSocket API版本不对应

Spring Boot 2.x 使用 javax.websocketSpring Boot 3.x 使用 jakarta.websocket解决方案:<!-- SpringBoot3 引入以下依赖,并删除之前的 javax.websocket依赖 -->
<dependency><groupId>jakarta.websocket</groupId><artifactId>jakarta.websocket-api</artifactId><version>2.1.0</version>
</dependency>

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

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

相关文章

国产Apple Find My认证芯片哪里找,伦茨科技ST17H6x芯片可以帮到您

深圳市伦茨科技有限公司&#xff08;以下简称“伦茨科技”&#xff09;发布ST17H6x Soc平台。成为继Nordic之后全球第二家取得Apple Find My「查找」认证的芯片厂家&#xff0c;该平台提供可通过Apple Find My认证的Apple查找&#xff08;Find My&#xff09;功能集成解决方案。…

使用java获取nvidia显卡信息

前言 AI开发通常使用到GPU&#xff0c;但通常使用的是python、c等语言&#xff0c;java用的则非常少。这也导致了java在gpu相关的库比较少。现在的需求是要获取nvidia显卡的使用情况&#xff0c;如剩余显存。这里给出两种较简单的解决方案。 基于nivdia-smi工具 显卡是硬件&a…

算法(1)——双指针

双指针 我们常见的双指针的形式有两种&#xff0c;一种是对撞指针&#xff0c;一种是快慢指针&#xff01; 对撞指针&#xff1a;一般用于顺序结构中&#xff0c;也称左右指针。 1、对撞指针从两端向中间移动。一个指针从最左端开始&#xff0c;另一个从最右端开始&#xff0c…

2024年【起重机司机(限门式起重机)】考试题库及起重机司机(限门式起重机)模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 起重机司机(限门式起重机)考试题库考前必练&#xff01;安全生产模拟考试一点通每个月更新起重机司机(限门式起重机)模拟考试题题目及答案&#xff01;多做几遍&#xff0c;其实通过起重机司机(限门式起重机)复审模拟…

21 3GPP中 5G NR高速列车通信标准化

文章目录 信道模型实验——物理层设计相关元素μ(与子载波间隔有关)设计参考信号(DMRS) 本文提出初始接入、移动性管理、线性小区设计等高层技术。描述3GPP采用HST场景的评估参数&#xff0c;阐释了HST应用的物理层技术&#xff0c;包括数字通信和参考信号设计&#xff0c;链路…

互联网中的商品超卖问题及其解决方案:Java中Redis结合UUID的应用

前言 在设计商品下单和库存扣减&#xff0c;你一定遇到过这样的问题&#xff0c;库存扣减为0了&#xff0c;可是消费者还能下单&#xff0c;并将订单信息保存到了数据库里&#xff0c;针对商品超卖问题&#xff0c;作此篇以解决。 随着互联网商业的飞速发展&#xff0c;商品超…

移动云捐赠三款开源项目,加速新一代基础软件生态繁荣

随着云计算、大数据、人工智能等新领域新信息技术的发展&#xff0c;我国基础软件的自主可控极大程度地影响着产业链上下游的多样性和技术创新的发展空间。移动云作为中国移动涉云业务的主入口&#xff0c;一直坚持共享开源价值&#xff0c;积极推动中国开源软件生态的繁荣发展…

SpringData JPA 整合Springboot

1.导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…

7-1 单身狗(PTA - 数据结构)

由于这道题在留的作业中&#xff0c;排序和查找都有&#xff0c;所以我先写这道题&#xff08;图的先放放&#xff09; “单身狗”是中文对于单身人士的一种爱称。本题请你从上万人的大型派对中找出落单的客人&#xff0c;以便给予特殊关爱。 输入格式&#xff1a; 输入第一行…

域架构下的功能安全思考

来源&#xff1a;联合电子 随着整车电子电气架构的发展&#xff0c;功能域控架构向整车集中式区域控制演进。新的区域控制架构下&#xff0c;车身控制模块(BCM)&#xff0c;整车控制单元&#xff08;VCU&#xff09;&#xff0c;热管理系统&#xff08;TMS&#xff09;和动力底…

python实现贪吃蛇游戏

文章目录 1、项目说明2、项目预览3、开发必备4、贪吃蛇代码实现4.1、窗口和基本参数实现4.2、绘制背景4.3、绘制墙壁4.4、绘制贪吃蛇4.5、绘制食物4.6、实现长度信息显示4.7、定义游戏暂停界面4.8、定义贪吃蛇死亡界面4.9、实现贪吃蛇碰撞效果4.10、实现添加食物功能4.11、实现…

elementui中的el-table,当使用fixed属性时,table主体会遮挡住滚动条的大半部分,导致很难选中。

情况&#xff1a; 解决&#xff1a; el-table加个类&#xff0c;这里取为class"table" 然后是样式部分&#xff1a; <style scoped lang"scss"> ::v-deep.table {// 滚动条高度调整::-webkit-scrollbar {height: 15px;}// pointer-events 的基本信…

处理HTTP响应状态码和错误处理

在Web开发的世界里&#xff0c;HTTP响应状态码和错误处理是不可或缺的一部分。它们就像是道路上的交通信号灯&#xff0c;指导着我们前进的方向&#xff0c;确保我们的应用程序能够正常运行。 HTTP响应状态码是Web服务器返回给客户端的数字代码&#xff0c;用于表示请求的处理…

以编程方式向 App 设计工具添加 UI 组件

App 设计工具组件库中提供了大多数 UI 组件&#xff0c;可以将它们拖放到画布上。有时&#xff0c;可能需要在代码视图中以编程方式添加组件。以下是一些常见情况&#xff1a; 创建在组件库中未提供的组件。例如&#xff0c;用于显示某对话框的 App 必须调用适当的函数来显示该…

Volta简单介绍

Volta是一款强大的JavaScript工具管理器&#xff0c;它简化了命令行工具的安装和管理。通过Volta&#xff0c;开发者可以轻松地在多个项目中切换和配置Node.js、npm以及其它JavaScript工具版本&#xff0c;提高开发效率和环境一致性。 什么是 Volta Volta 是一种管理 JavaScri…

数据之门:使用IPIDEA开启网络自由之旅~

本文目录 前言一、网络代理IP简介二、IPIDEA 优势2.1 多种类型IP代理2.2 海量纯净代理池2.3 稳定高效数据收集架构2.4 个人IP管理中心 三、IP代理实操小Tips3.1 查看本地网络IP3.2 使用浏览器IP代理3.3 使用IPIDEA进行爬虫实操 四、总结 前言 各位友友&#xff0c;大家好&…

ASP.NET MVC+EntityFramework图片头像上传

1&#xff0c;先展示一下整体的效果 2&#xff0c;接下来展示用户添加以及上传头像代码、添加用户界面 前端代码如下&#xff1a; <div class"form-group">Html.LabelFor(model > model.img, "头像&#xff1a;", htmlAttributes: new { class &…

【计算机组成与体系结构Ⅱ】多处理器部分讨论题目

多处理机课堂讨论 1.并行计算体系结构有哪些? SIMD、MIMD 2.多处理机的存储结构有哪些? 对称式共享存储器结构、分布式共享存储结构 3.什么是多处理机的一致性? 如果对某个数据项的任何读操作均可得到其最新写入的值&#xff0c;则认为这个存储系统是一致的。 4.监听协议的工…

UCloud + 宝塔 + PHP = 个人网站

UCloud 宝塔 PHP 个人网站 文章目录 1.概要2.UCloud使用教程&#xff08;租用云端服务器&#xff09;3.宝塔使用教程&#xff08;免费服务器运维面板&#xff09;4.总结 1.概要 今天主要是想教大家如何将在网络上白嫖到源码&#xff08;特指PHP源码!!!&#xff09;搭建运行…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…