springboot创建websocket服务端
springboot创建websocket服务端
1.配置类
package com.neusoft.airport.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author dume* @create 2023-07-24 17:11**/
@Configuration
//@ConditionalOnWebApplication
public class WebSocketConfig {/*** ServerEndpointExporter 作用** 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint** @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}/*** 通信文本消息和二进制缓存区大小* 避免对接 第三方 报文过大时,Websocket 1009 错误* @return*/@Beanpublic ServletServerContainerFactoryBean createWebSocketContainer() {ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();// 在此处设置bufferSizecontainer.setMaxTextMessageBufferSize(10240000);container.setMaxBinaryMessageBufferSize(10240000);container.setMaxSessionIdleTimeout(15 * 60000L);return container;}}
2.通讯类server
package com.neusoft.airport.websocket;import com.alibaba.fastjson.JSONObject;import com.neusoft.caeid.upms.license.LicenseSetting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** @author dume* @create 2023-07-24 17:11**/@Component
@ServerEndpoint("/webSocket/{sid}")
public class WebSocketServer implements EnvironmentAware {private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static int onlineCount = 0;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();private ScheduledExecutorService executor= Executors.newSingleThreadScheduledExecutor();private static Environment globalEnvironment;//接收sidprivate String sid="";//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;@Autowiredprivate Environment environment;/*** 连接建立成功调用的方法** @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic void onOpen(Session session,@PathParam("sid") String sid) throws IOException {//防止重复连接for (WebSocketServer item : webSocketSet) {if (item.sid.equals(sid)) {webSocketSet.remove(item);subOnlineCount(); //在线数减1break;}}this.session = session;this.environment = globalEnvironment;webSocketSet.add(this); //加入set中addOnlineCount(); //在线数加1log.info("有新用户连接,连接名:"+sid+",当前在线人数为" + getOnlineCount());this.session.getAsyncRemote().sendPing(ByteBuffer.wrap(new byte[0]));this.sid=sid;}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this); //从set中删除subOnlineCount(); //在线数减1log.info("连接关闭:"+sid+"当前在线人数为" + getOnlineCount());}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息* @param session 可选的参数*/@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自:"+sid+"的信息:"+message);
// //群发消息for (WebSocketServer item : webSocketSet) {try {LicenseSetting.CheckParams checkParams = LicenseSetting.getCheckParams();//当前license信息log.info("当前证书信息: "+ JSONObject.toJSONString(checkParams));if(null!=checkParams.getLicenseParams()){checkParams.getLicenseParams().setSysMessageInfo(null);}String sendMessageStr = JSONObject.toJSONString(checkParams);if(checkParams.getStatus()==0){log.info("证书验证成功!");}else {log.error("证书验证失败!");}item.sendMessage(sendMessageStr);} catch (IOException e) {log.error("推送消息到:"+sid+",推送内容出错",e);continue;}}}/*** 发生错误时调用*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发生错误",error);}// 接收心跳消息@OnMessagepublic void onPong(PongMessage pong, Session session, @PathParam("sid") String sid) {executor.schedule(() -> {try {// 发送空的Ping消息session.getAsyncRemote().sendPing(ByteBuffer.wrap(new byte[0]));} catch (IOException e) {// 处理发送失败的情况log.error("Ping 用户:{} 心跳异常,关闭会话,错误原因:{}", sid, e.getMessage());onClose();}}, 10, TimeUnit.SECONDS);}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。*/public void sendMessage(String message) throws IOException {//this.session.getBasicRemote().sendText(message);this.session.getAsyncRemote().sendText(message);}/*** 群发自定义消息* */public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {//log.info("推送消息到窗口"+sid+",推送内容:"+message);for (WebSocketServer item : webSocketSet) {try {log.info("推送消息到:"+item.sid+",推送内容:"+message);//这里可以设定只推送给这个sid的,为null则全部推送if(sid==null||sid.length()==0) {item.sendMessage(message);}else if(item.sid.equals(sid)){item.sendMessage(message);}} catch (IOException e) {log.error("发生错误",e);continue;}}}//推送给指定sidpublic static boolean sendInfoBySid(@PathParam("sid") String sid,String message) throws IOException {//log.info("推送消息到窗口"+sid+",推送内容:"+message);boolean result=false;if(webSocketSet.size()==0){result=false;}for (WebSocketServer item : webSocketSet) {try {if(item.sid.equals(sid)){item.sendMessage(message);log.info("推送消息到:"+sid+",推送内容:"+message);result=true;}} catch (IOException e) {log.error("发生错误",e);continue;}}return result;}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}public static synchronized void subOnlineCount() {if(WebSocketServer.onlineCount>0){WebSocketServer.onlineCount--;}}@Overridepublic void setEnvironment(final Environment environment) {this.environment = environment;if (globalEnvironment == null && environment != null) {globalEnvironment = environment;}}
}相关文章:
springboot创建websocket服务端
springboot创建websocket服务端 1.配置类 package com.neusoft.airport.websocket;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndp…...
网络安全攻防实战:探索互联网发展史
大家好,我是沐尘而生。 互联网发展史:数字世界的壮阔画卷 从早期的ARPANET到今天的万物互联,互联网经历了漫长的发展过程。然而,随着技术的进步,网络安全问题也随之而来。我们不仅要探索互联网的壮阔历程,…...
pwm接喇叭搞整点报时[keyestudio的8002模块]
虽然现在查看时间很方便,但是其实好像我的时间观念却越来越差。于是决定搞一个整点报时,时常提醒自己时光飞逝,不要老是瞎墨迹。 这篇主要讲一下拼装方式和配置,就差不多了。不涉及什么代码。3针的元器件,去掉正负接线…...
配置listener tcps加密 enable SSL encryption for Oracle SQL*Net
一 配置客户端和服务端的wallet 2端配置方法一致,相互添加证书 orapki wallet create -wallet “/u01/oracle/wallet” -pwd Wdkf984jkkgekj434FKFD -auto_login_local orapki wallet add -wallet “/u01/oracle/wallet” -pwd Wdkf984jkkgekj434FKFD -dn “CNho…...
【Sklearn】基于逻辑回归算法的数据分类预测(Excel可直接替换数据)
【Sklearn】基于逻辑回归算法的数据分类预测(Excel可直接替换数据) 1.模型原理2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果1.模型原理 逻辑回归是一种用于二分类问题的统计学习方法,尽管名字中含有“回归”,但实际上是一种分类算法。它的基本原理是通…...
自然数的拆分问题
题目描述 任何一个大于 11 的自然数 n,总可以拆分成若干个小于 n 的自然数之和。现在给你一个自n,要求你求出 n 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。 输…...
du -mh命令
du 命令查看每个文件夹大小(du 命令用法详解),du 命令的英文全拼是 disk usage,意思是占用的磁盘空间,该命令可以显示目录或文件的大小。 在执行“ du ”命令时,使用“ -h ”参数会以“人类可读格式”显示…...
MySQL 8 group by 报错 this is incompatible with sql_mode=only_full_group_by
文章目录 sql_mode配置ONLY_FULL_GROUP_BYSTRICT_TRANS_TABLESNO_ZERO_IN_DATENO_ZERO_DATEERROR_FOR_DIVISION_BY_ZERONO_AUTO_CREATE_USERNO_ENGINE_SUBSTITUTION 局部修改配置windows修改配置Linux修改配置 sql_mode配置 ONLY_FULL_GROUP_BY 用于控制是否允许对查询结果进…...
Mongodb (四十一)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、概述 1.1 相关概念 1.2 特性 二、应用场景 三、安装 四、目录结构 五、默认数据库 六、 数据库操作 6.1 库操作 6.2 文档操作 七、MongoDB数据库备份 7.1 备…...
16 dlsys GAN
和有监督的分类工作不同,生成任务的目标更不明确。难以评价生成结果的好坏。 Oracle discriminator 假设我们有一个先知判别器oracle discriminator可以分辨我们生成的内容是真还是假。 D(x) 表示判别数据为真的概率。 我们想让生产成的结果足够真实,所…...
css3-flex布局:基础使用 / Flexbox布局
一、理解flex 二、理解Flex布局(又称Flexbox布局) Flex布局(又称Flexbox布局)是一种基于Web的CSS3布局模式,其目的是为了更加灵活和自适应地布置各种各样的网页元素。Flex布局通过将一个父容器分割为一个或多个弹性项…...
MYSQL-习题掌握
文章目录 SQL基本操作1 设计表操作1.1 关系表字段1.2 关系表创建1.3 关系表数据1.4 关系表关系 2 SQL操作2.1 SQL 1-102.2 SQL 11-202.3 SQL 21-302.4 SQL 31-402.5 SQL 41-50 SQL基本操作 1 设计表操作 1.1 关系表字段 1 学生表 student s_ids_names_births_sex学生编号学…...
Python-迭代
1、迭代器 迭代器是一个对象,它可以记录遍历的相关信息,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器有两个基本的方法:iter() 和 next()。我们都过命令行工具,了解一下python的底层迭代…...
【论文阅读】DEPCOMM:用于攻击调查的系统审核日志的图摘要(SP-2022)
Xu Z, Fang P, Liu C, et al. Depcomm: Graph summarization on system audit logs for attack investigation[C]//2022 IEEE Symposium on Security and Privacy (SP). IEEE, 2022: 540-557. 1 摘要 提出了 DEPCOMM,这是一种图摘要方法,通过将大图划…...
大语言模型之一 Attention is all you need ---Transformer
大语言模型已经在很多领域大显身手,其应用包括只能写作、音乐创作、知识问答、聊天、客服、广告文案、论文、新闻、小说创作、润色、会议/文章摘要等等领域。在商业上模型即产品、服务即产品、插件即产品,任何形态的用户可触及的都可以是产品,…...
数字鸿沟,让气候脆弱者更脆弱
随着科技的飞速发展,数字化正在改变我们的生活方式和社会结构。然而,数字鸿沟(Digital Divide)这一长期存在的问题,却在某些方面加剧了社会的不平等现象。在此,我们将探讨数字鸿沟如何加剧了气候脆弱者的脆…...
Tomcat 部署优化
Tomcat Tomcat 开放源代码web应用服务器,是由java代码开发的 tomcat就是处理动态请求和基于java代码的页面开发 可以在html当中写入java代码,tomcat可以解析html页面当中的iava,执行动态请求 动态页面机制有问题:不对tomcat进行优…...
Django框架-使用celery(一):django使用celery的通用配置,不受版本影响
目录 一、依赖包情况 二、项目目录结构 2.1、怎么将django的应用创建到apps包 三、celery的配置 2.1、celery_task/celery.py 2.2、celery_task/async_task.py 2.3、celery_task/scheduler_task.py 2.4、utils/check_task.py 四、apps/user中配置相关处理视图 4.1、基本…...
nvue语法与vue的部分区别
文章目录 1、仅支持flex布局2、字体样式3、高度问题 1、仅支持flex布局 仅支持flex布局。而且默认的是 flex-direction: column; 2、字体样式 字体的样式,必须要写在 text 标签内,才能生效 错误示例: <!-- 错误示例 --> <div cl…...
Java 开发工具 IntelliJ IDEA
1. IntelliJ IDEA 简介 IntelliJ IDEA 是一款出色的 Java 集成开发环境(IDE),提供了丰富的功能和工具,支持多种语言和框架的开发,如 Java、Kotlin、Scala、 Android、Spring、Hibernate 等。IntelliJ IDEA 专注于提高…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
