【JAVA實現websocket】

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;你都可以嘗試替換。數…