JAVA实现websocket

  • 背景
    • 依赖
    • 问题
    • 代码实现
    • 测试

背景

近期项目中需要用到websocket,实现即时通信。

依赖

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

问题

使用websocket网页测试时,发现websocket连接不上,因为spring.security的问题,需要账号密码,可以在启动类中移除SecurityAutoConfiguration.class。
在这里插入图片描述

代码实现

onMessage方法用来接收消息,可以根据自己业务需要定义正常的心跳处理以及业务处理逻辑。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.travelsky.config.WebSocketConfigurator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
@Component
@ServerEndpoint(value = "/websocket", configurator = WebSocketConfigurator.class)
public class WebSocketServer {//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;private static final AtomicInteger OnlineCount = new AtomicInteger(0);// concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。public static ConcurrentHashMap<String, WebSocketServer> serverMap = new ConcurrentHashMap<>();private static final String LOCALHOST = "127.0.0.1";private final String ipAddress = LOCALHOST;/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session) {this.session = session;log.info("开始建立websocket方法连接,获取Session为:{}", session);log.info("连接建立 - Session ID: {}, Query: {}",session.getId(), session.getRequestURI().getQuery());// 如果已有连接,先关闭旧连接if (serverMap.containsKey(this.ipAddress)) {WebSocketServer oldServer = serverMap.get(this.ipAddress);try {oldServer.session.close();} catch (IOException e) {log.error("关闭旧连接失败", e);}}serverMap.put(this.ipAddress, this);int cnt = OnlineCount.incrementAndGet();log.info("有连接加入,当前连接数为:{},当前连接id为:{}", cnt, this.ipAddress);sendMessage("连接成功");log.info("{},已上线!", this.ipAddress);}@OnMessagepublic void onMessage(String message, Session session) {try {log.info("服务器收到了用户:{},发来的消息:{},当前ip集合为:{}", ipAddress, message, JSON.toJSONString(serverMap));//方便前端测试JSONObject jsonObject = JSON.parseObject(message);Object modeCode = jsonObject.get("ModeCode");log.info("获取到前端发送消息为:{}", modeCode);String string = modeCode.toString();sendMessage("pong");if (!string.contains("ping"))  {//处理其它业务逻辑log.info("ModeCode为空则表示正常数据");//ModeCode为空则表示正常数据 处理其他消息Map map = JSON.parseObject(message, Map.class);log.info("打印JSON字符串:{}", JSON.toJSONString(map));}} catch (Exception e) {log.error("处理数据异常", e);onError(session, e);}}/*** 给ip地址为ip的客户端发送消息** @param ip      ip地址* @param message 消息*/public static Boolean sendMessage(String ip, String message) {log.info("开始发送消息,serverMap数据为:{},ip为:{},消息为:{}", serverMap, ip, message);if (serverMap.containsKey(ip)) {WebSocketServer webSocketServer = serverMap.get(ip);webSocketServer.sendMessage(message);log.info("发送成功:{},当前连接数为:{}", ip, OnlineCount);return false;} else {log.error("发送失败,客户端未连接: {}", ip);return true;}}/*** 服务器主动发送消息** @param message 消息*/public void sendMessage(String message) {try {this.session.getBasicRemote().sendText(message);} catch (IOException e) {log.error("发送消息异常:{}", e.getMessage());}}@OnClosepublic void onClose(Session session, CloseReason closeReason) {log.info("连接关闭 - Session ID: {}, Reason: {} (Code: {})",session.getId(),closeReason.getReasonPhrase(),closeReason.getCloseCode());if (serverMap.containsKey(ipAddress)) {serverMap.remove(ipAddress);int cnt = OnlineCount.decrementAndGet();log.info("有连接退出,当前连接数为:{},当前;退出id为:{}", cnt, this.ipAddress);log.info("{},已下线!", ipAddress);}}@OnErrorpublic void onError(Session session, Throwable throwable) {log.info("连接异常 - Session ID: {}", session.getId());if (serverMap.containsKey(ipAddress)) {serverMap.remove(ipAddress);int cnt = OnlineCount.decrementAndGet();log.error("用户{}发生了错误,具体如下:{},已下线!,当前连接数为:{}", ipAddress, throwable.getMessage(), cnt);}}private static synchronized void subOnlineCount() {OnlineCount.decrementAndGet();}public static synchronized void addOnlineCount() {OnlineCount.incrementAndGet();}public static WebSocketServer get(String ipAddress) {return serverMap.get(ipAddress);}public static ConcurrentHashMap<String, WebSocketServer> getMap() {return serverMap;}public static boolean isOnline(String ipAddress) {return serverMap.containsKey(ipAddress);}/*** 通用处理空格** @param s String*/private static String processDataSpace(String s, int length) {if (s == null || s.isEmpty()) {// 如果为空,直接返回空格return String.format("%-" + length + "s", s);}//如果长度超过则截取 不足则用空格补齐if (s.length() > length) {// 超过位则截断return s.substring(0, length);} else {// 不足位右补空格return String.format("%-" + length + "s", s);}}
}

测试

websocket在线测试
在这里插入图片描述
该链接可以在线测试websocket是否正常,数据格式需要满足自定义的要求。

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

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

相关文章

2.6 提示词调优编码实战(一)

目录 写在前面 一,需求定义 二,简单提示词 2.1 代码示例 2.2 输出结果 三,提示词模版 3.1 提示词 3.1.1 任务描述 3.1.2 用户输入 3.1.3 模型输出格式 3.1.4 Prompt模版 3.2 输出结果 写在前面 前面我们总结了提示词对于模型的意义,接下来我们来通过向模型输入…

使用Stone 3D快速制作第一人称视角在线小游戏

首先得有个怪物模型&#xff0c;怪物带有idle, attack动作 然后有个场景模型&#xff0c;把怪物&#xff08;如果模型较大&#xff0c;建议使用remote-mesh来加载&#xff09;摆放到想放的位置。 给相机加上fps-controls和character组件 给所有怪物加上character组件 可以在…

嵌入式第三十七课!!!TCP机制与HTTP协议

TCP的其他机制TCP头部标志位SYN&#xff1a;请求建立连接标志位 ACK&#xff1a;响应报文标志位 PSH&#xff1a;携带数据标志位&#xff0c;通知接收方该从缓冲区读数据 FIN&#xff1a; 请求断开连接标志位 RST&#xff1a;复位标志位 URG: 紧急数据标志…

【测试】pytest测试环境搭建

使用pytest进行API测试&#xff0c;vscode运行 创建虚拟环境&#xff0c;安装pytest&#xff0c;httpx&#xff0c;requests&#xff0c;dotenvvscode中ctrlshiftp&#xff0c;选择python: Configure Tests&#xff0c;选择pytest&#xff0c;目录左侧插件testing里面可以看到有…

javaweb开发笔记——微头条项目开发

第八章 微头条项目开发 一 项目简介 1.1 微头条业务简介 微头条新闻发布和浏览平台,主要包含业务如下 用户功能 注册功能 登录功能 头条新闻 新闻的分页浏览 通过标题关键字搜索新闻 查看新闻详情 新闻的修改和删除 权限控制 用户只能修改和自己发布的头条新闻 1.…

Linux(二十二)——服务器初始化指南

文章目录前言一、配置国内 Yum 源&#xff08;加速软件安装&#xff09;二、更新系统与安装必备工具三、网络连接验证四、配置主机名五、同步时间六、配置防火墙6.1 使用 iptables6.1.1 整体思路6.1.2 详细步骤6.1.3 完整配置脚本示例6.1.4 常用管理命令6.2 使用 firewalld总结…

我用Photoshop Firefly+Blender,拯救被环境毁掉的人像大片

今日阳光正好。这样的天气对于摄影师来说是种馈赠&#xff0c;但也让我想起了这个行业最普遍也最无奈的痛点&#xff1a;我们精心策划了一场拍摄&#xff0c;模特的表现、光线的质感都近乎完美&#xff0c;但最终却因为一个平淡的阴天、一处杂乱的背景&#xff0c;或是一个无法…

【线性代数】常见矩阵类型

目录 1. 方阵(Square Matrix) 2. 对称矩阵(Symmetric Matrix) 3. 反对称矩阵 / 斜对称矩阵(Skew-Symmetric Matrix) 4. 对角矩阵(Diagonal Matrix) 5. 三角矩阵 6. 正交矩阵(Orthogonal Matrix) 7. 幂等矩阵(Idempotent Matrix) 8. 正定矩阵 / 半正定矩阵 …

达梦数据库统计信息收集

达梦数据库统计信息收集 检查统计信息收集情况 如何手动收集统计信息 查看统计信息收集结果 统计信息手动收集策略 统计信息的自动收集 检查统计信息收集情况 检查最近一次统计信息收集时间: --表的最近一次统计信息收集时间 SQL> select owner,table_name,last_analyzed…

【目标检测】论文阅读4

Fast and accurate object detector for autonomous driving based on improved YOLOv5 发表时间&#xff1a;2023年&#xff1b;期刊&#xff1a;scientific reports 论文地址 摘要 自动驾驶是人工智能的一个重要分支&#xff0c;实时准确的目标检测是保证自动驾驶车辆安全稳…

wpf之DockPanel

前言 DockPanel是一个容器控件&#xff0c;容器中的子控件通过设置DockPanel.Dock属性来调整位置 1、DockPanel.Dock DockPanel.Dock的值有Left、Right、Top、Bottom 1.1 Left 指示控件靠左停靠 1.2 Right 指示控件靠右停靠 1.3 Top 指示控件靠上停靠 1.4 Bottom 指示…

解决VSCode中Cline插件的Git锁文件冲突问题

文章目录 问题现象 错误分析 解决方案 方法一:手动删除锁文件(推荐) 方法二:检查并终止Git进程 方法三:重置检查点目录 方法四:完全重新初始化 预防措施 总结 在使用VSCode进行开发时,许多开发者会选择安装Cline插件来提升工作效率。然而,在使用过程中,可能会遇到一些…

视频合成素材视频-多合一功能-青柠剪吧

剪辑繁琐耗时&#xff1f;这款工具正在改变创作者的日常。最近很多人都在用的剪辑神器&#xff0c;叫青柠剪吧。它尤其适合需要批量处理视频的朋友&#xff0c;内置40多项功能&#xff0c;从替换、分割到对齐、导出&#xff0c;基本覆盖了剪辑全流程。操作简单&#xff0c;哪怕…

未成功:使用 Nginx 搭建代理服务器(正向代理 HTTPS 网站)

下载 nginx: download 解压配置http 编译conf/nginx.conf http {server {listen 8080; # 代理服务器监听端口resolver 8.8.8.8; # DNS 解析器location / {proxy_pass $scheme://$host$request_uri; # 转发请求proxy_set_header Host $host;proxy_set_header X-Real-IP $…

【Python】新手入门:Python标准库有哪些常用模块?

🌈 个人主页:(时光煮雨) 🔥 高质量专栏:vulnhub靶机渗透测试 👈 希望得到您的订阅和支持~ 💡 创作高质量博文(平均质量分95+),分享更多关于网络安全、Python领域的优质内容!(希望得到您的关注~) 🌵文章目录🌵 前言 💡一、操作系统接口 📝二、文件通配符…

从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑

public class SFTPUtil {// 16 usages&#xff08;注释为截图中的使用统计&#xff0c;实际代码无需保留&#xff09;private static ChannelSftp sftp;// 6 usages&#xff08;注释为截图中的使用统计&#xff0c;实际代码无需保留&#xff09;private volatile static SFTPUt…

Win10部署ElasticSearch、Logstash、Kibana

一、本地部署 ElasticSearch 1、下载 Elasticsearch 安装包 点此下载 Elasticsearch 2、解压到指定目录 3、winR 输入 cmd&#xff0c;进入 Elasticsearch 安装目录运行 .bat 文件 4、浏览器输入 https://localhost:9200 &#xff0c;并进行身份验证 在 Elasticsearch 的 bi…

解决Visual Studio中UWP设计器无法显示的问题:需升级至Windows 11 24H2

一则清晰的错误提示&#xff0c;指明了前进的方向。近日&#xff0c;我在使用Visual Studio进行UWP应用开发时遇到了一个棘手问题——MainPage.xaml的设计视图无法正常显示&#xff0c;取而代之的是一个明确的系统提示。本文将详细分析这一问题及其解决方案。 问题现象 当在Vis…

PINN物理信息神经网络多变量回归预测,Matlab实现

前言 物理信息神经网络&#xff08;Physics-Informed Neural Networks, PINNs&#xff09;是一种结合深度学习与物理定律的神经网络方法&#xff0c;旨在解决涉及偏微分方程&#xff08;PDEs&#xff09;的问题。以下是对该问题的详细解答&#xff1a;物理信息神经网络的定义与…

SagooIoT 产品国产化

国产化说明&#xff0c;支持的国产化数据库、服务器、操作系统以及国产化中间件。操作系统统一uos操作系统红旗Linux麒麟V10操作系统中天鲲鹏欧拉版本操作系统服务器华为泰山服务器海光服务器华为鲲鹏服务器只要是能兼容Linux操作系统的服务器&#xff0c;你都可以尝试替换。数…