websocket聊天(全源碼)

區別:我認為的websocket和輪詢的區別

輪詢是客戶端定期向服務端發送請求,目的是獲取的信息

websocket則是服務端直接向客戶端發送想要獲取的信息

配置jdk17 idea 2022

代碼

pom

<?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.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>wsocket</artifactId><version>0.0.1-SNAPSHOT</version><name>wsocket</name><description>wsocket</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.32</version></dependency><!-- websocket消息推送 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-websocket</artifactId>-->
<!--            <version>6.0.9</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.tomcat.embed</groupId>-->
<!--            <artifactId>tomcat-embed-websocket</artifactId>-->
<!--            <version>10.1.20</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.tomcat.embed</groupId>-->
<!--            <artifactId>tomcat-embed-websocket</artifactId>-->
<!--            <version>9.0.78</version>-->
<!--        </dependency>--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.9</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-websocket</artifactId><version>10.1.20</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

?配置類

package com.example.wsocket.spring;import com.example.wsocket.java.WebSocketConfig;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/***/
@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {@ResourceMyWsHandler myWsHandler;@ResourceMyWsInterceptor myWsInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myWsHandler,"/myWs1").addInterceptors(myWsInterceptor).setAllowedOrigins("*");}//訪問的位置,設置攔截器,設置攔截范圍
}

websocket周期設置

package com.example.wsocket.spring;import cn.hutool.core.text.StrBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/**物理程序*/
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {private static Map<String,SessionBean> sessionBeanMap;private static AtomicInteger clientIdMaker;private static StringBuffer stringBuffer;//初始化static {sessionBeanMap = new ConcurrentHashMap<>();clientIdMaker = new AtomicInteger(0);stringBuffer = new StringBuffer();}@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {super.afterConnectionEstablished(session);SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());sessionBeanMap.put(session.getId(),sessionBean);log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立連接");stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"進入了群聊<br/>");sendMessage(sessionBeanMap);}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {super.handleTextMessage(session, message);log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");sendMessage(sessionBeanMap);}//異常時@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {super.handleTransportError(session, exception);if (session.isOpen()){session.close();}sessionBeanMap.remove(session.getId());}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {super.afterConnectionClosed(session, status);int clientId = sessionBeanMap.get(session.getId()).getClientId();sessionBeanMap.remove(session);log.info(clientId+"關閉了連接");stringBuffer.append(clientId+"退出了群聊<br/>");sendMessage(sessionBeanMap);}public void sendMessage(Map<String,SessionBean> sessionBeanMap){for(String key:sessionBeanMap.keySet()){{try {sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));} catch (IOException e) {log.info("出錯啦");}}}}//    //定時任務
//    @Scheduled(fixedDelay = 2000)//多少秒執行1次
//    public void sendMessage() throws IOException {
//        for (String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(":心跳"));
//        }
//    }
}

攔截器

package com.example.wsocket.spring;import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import java.util.Map;/*** @authorGH* @company www.1248163489.com*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {super.afterHandshake(request, response, wsHandler, ex);}
}

sessionBean


import jakarta.websocket.Session;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.server.WebSession;
import org.springframework.web.socket.WebSocketSession;/*** @authorGH* @company www.1248163489.com*/
@Data
@AllArgsConstructorpublic class SessionBean {/****@param*/private WebSocketSession webSocketSession;private Integer clientId;
}

前端頁面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<p style="border: 1px solid black;width: 400px;height: 600px" id="talkMsg"></p>
<input id="message" />
<button id="sendBtn" onclick="sendMsg()">發送</button>
</body>
<script>let ws = new WebSocket("ws://localhost:8080/myWs1")ws.onopen=function (){}ws.onmessage=function (message) {document.getElementById("talkMsg").innerHTML = message.data}function sendMsg() {ws.send(document.getElementById("message").value)document.getElementById("message").value=""}
</script>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/13892.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13892.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13892.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從BIO到NIO到AIO: Java全面IO模型解析

1. Java IO模型概述 Java IO&#xff08;輸入/輸出&#xff09;是Java編程語言中用于數據輸入和輸出的一組功能強大的API。這些API為文件IO、網絡IO以及系統資源IO提供了豐富的類和接口。由于IO操作直接與操作系統交互&#xff0c;因此理解Java IO模型與操作系統模型如何聯系是…

C++ | Leetcode C++題解之第108題將有序數組轉換為二叉搜索樹

題目&#xff1a; 題解&#xff1a; class Solution { public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nu…

算法學習:快速排序

&#x1f525; 個人主頁&#xff1a;空白詩 文章目錄 &#x1f680; 引言&#x1f4cc; 快速排序算法核心思想1. 選擇基準值&#xff08;Pivot&#xff09;2. 分區操作&#xff08;Partitioning&#xff09;3. 遞歸排序子序列 &#x1f4cc; JavaScript 實現1. 快速排序主函數2…

基于Perfetto 解讀一幀的生產消費流程 Android >= S Qualcomm

廣告 首先幫我朋友打個廣告 我們一起在運營一個視頻號 感興趣的可以幫忙點擊右邊這個小鈴鐺 鈴鐺 序 1.這個流程里面的東西如果展開其實是有很多的 內容其實還是比較淺顯的 sf處就不貼源碼了 關一個Vsync就有的解釋 當然筆者在流程上先形成一個思維閉環 2.如有小伙伴需要 筆…

Java方法的遞歸

Java方法的遞歸 前言一、遞歸的概念示例代碼示例 二、遞歸執行過程分析代碼示例執行過程圖 三、遞歸練習代碼示例按順序打印一個數字的每一位(例如 1234 打印出 1 2 3 4)遞歸求 1 2 3 ... 10寫一個遞歸方法&#xff0c;輸入一個非負整數&#xff0c;返回組成它的數字之和. …

零基礎學Java第二十一天之IIO流之對象流

IO流之對象流 1、對象流 1、理解 將對象寫入到文件&#xff0c;將文件里的對象讀取到程序中 class ObjectInputStream – 對象輸入流 class ObjectOutputStream – 對象輸出流 序列化/鈍化&#xff1a;程序里的對象 寫入到 文件中 反序列化/活化&#xff1a;文件中的對象 讀取…

【OpenCV實戰】OpenCV實現自動調整亮度和對比度

一,基于局部直方圖信息增強算法 對比度受限的自適應直方圖均衡化(Contrast Limited Adaptive Histogram Equalization,簡稱CLAHE)是一種用于圖像增強的技術,其原理主要基于自適應直方圖均衡化(Adaptive Histogram Equalization,簡稱AHE)但增加了對比度限制來避免過度放…

uniapp藍牙打印圖片

前言 這是個藍牙打印圖片的功能&#xff0c;業務是打印界面固定的demo范圍&#xff0c;這里通過html2canvas插件生成的圖片base64&#xff0c;然后圖片base64繪制到canvas中去后&#xff0c;獲取canvas中的像素信息&#xff0c;然后對像素信息進行一個灰度值處理&#xff0c;灰…

在Linux系統中解決Java生成海報文字亂碼和缺少字體文件的問題

在Linux系統中,如果缺少特定的字體文件,可以通過以下幾種方法來解決: 1. 安裝系統字體包 大多數Linux發行版提供了各種字體包,可以通過包管理器安裝這些字體包。例如,在Debian/Ubuntu系統上,可以使用以下命令安裝常見的字體包: # 安裝基本的字體包 sudo apt-get updat…

Java集合的組內平均值怎么計算

要計算Java集合&#xff08;例如List或Set中的Integer、Double或其他數值類型的對象&#xff09;的組內平均值&#xff0c;我們需要遍歷這個集合&#xff0c;累加所有的元素值&#xff0c;然后除以集合的大小&#xff08;即元素的數量&#xff09;。以下是一個詳細的步驟說明和…

opencl色域變換,處理傳遞顯存數據

在使用ffmpeg解碼后的多路解碼數據非常慢&#xff0c;還要給AI做行的加速方式是在顯存處理數據&#xff0c;在視頻拼接融合產品的產品與架構設計中&#xff0c;提出了比較可靠的方式是使用cuda&#xff0c;那么沒有cuda的顯卡如何處理呢 &#xff0c;比較好的方式是使用opencl來…

go語言的一些常見踩坑問題

開始之前&#xff0c;介紹一下?最近很火的開源技術&#xff0c;低代碼。 作為一種軟件開發技術逐漸進入了人們的視角里&#xff0c;它利用自身獨特的優勢占領市場一角——讓使用者可以通過可視化的方式&#xff0c;以更少的編碼&#xff0c;更快速地構建和交付應用軟件&#…

安卓手機APP開發__網絡連接性支持VPN

安卓手機APP開發__網絡連接性支持VPN 安卓提供了API給開發者,來創建一個虛擬的私有網絡(VPN)的解決方案. 根據這里的介紹,你能知道如何開發和測試你的針對安卓設備的VPN的客戶端. 概述 VPN允許設備為了安全地連接網絡,而沒有物理性的連接在一個網絡上. 安卓包括了一個內嵌的…

【無重復字符的最長子串】python,滑動窗口+哈希表

滑動窗口哈希表 哈希表 seen 統計&#xff1a; 指針 j遍歷字符 s&#xff0c;哈希表統計字符 s[j]最后一次出現的索引 。 更新左指針 i &#xff1a; 根據上輪左指針 i 和 seen[s[j]]&#xff0c;每輪更新左邊界 i &#xff0c;保證區間 [i1,j] 內無重復字符且最大。 更新結…

使用JSDOM安全截斷文章HTML內容

在Web開發中&#xff0c;經常需要處理大量的HTML內容&#xff0c;尤其是在展示文章預覽、動態加載內容或限制顯示長度等場景中。直接截斷HTML字符串可能會導致頁面布局混亂、樣式錯誤或標簽不完整等問題。為了安全地截斷HTML內容&#xff0c;我們可以利用jsdom庫來解析HTML&…

JVM學習-垃圾回收器(一)

垃圾回收器 按線程數分類 串行垃圾回收器 串行回收是在同一時間段內只允許有一個CPU用于執行垃圾回收操作&#xff0c;此時工作線程被暫停&#xff0c;直至垃圾收集工作結束 在諸如單CPU處理器或者較小的應用內存等硬件平臺不是特別優越的場合&#xff0c;串行回收器的性能表…

http和https的區別,怎么免費實現https(內涵教學)

超文本傳輸協議HTTP協議被用于在Web瀏覽器和網站服務器之間傳遞信息&#xff0c;HTTP協議以明文方式發送內容&#xff0c;不提供任何方式的數據加密&#xff0c;如果攻擊者截取了Web瀏覽器和網站服務器之間的傳輸報文&#xff0c;就可以直接讀懂其中的信息&#xff0c;因此&…

etcd 和 MongoDB 的混沌(故障注入)測試方法

最近在對一些自建的數據庫 driver/client 基礎庫的健壯性做混沌&#xff08;故障&#xff09;測試, 去驗證了解業務的故障處理機制和恢復時長. 主要涉及到了 MongoDB 和 etcd 這兩個基礎組件. 本文會介紹下相關的測試方法. MongoDB 中的故障測試 MongoDB 是比較世界上熱門的文…

AI網絡爬蟲:批量爬取電視貓上面的《慶余年》分集劇情

電視貓上面有《慶余年》分集劇情&#xff0c;如何批量爬取下來呢&#xff1f; 先找到每集的鏈接地址&#xff0c;都在這個class"epipage clear"的div標簽里面的li標簽下面的a標簽里面&#xff1a; <a href"/drama/Yy0wHDA/episode">1</a> 這個…

速盾:負載均衡能防ddos攻擊嗎?

負載均衡是一種分布式系統的設計思想&#xff0c;通過將流量分散到多個服務器上&#xff0c;以提高系統的穩定性和可擴展性。然而&#xff0c;負載均衡本身并不能完全防止DDoS攻擊&#xff0c;但可以在一定程度上減輕其影響。 DDoS&#xff08;分布式拒絕服務&#xff09;攻擊…