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.mzph.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;攻击…