(java)websocket服务的两种实现方式

1.基于java注解实现websocket服务器端

1.1需要的类

1.1.1服务终端类

用java注解来监听连接@ServerEndpoint、连接成功@OnOpen、连接失败@OnClose、收到消息等状态@OnMessage

1.1.2配置类

把spring中的ServerEndpointExporter对象注入进来

2.1代码示例

2.1.1 maven配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.heima</groupId><artifactId>ws-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.22</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.14</version></dependency></dependencies></project>

2.1.2 WsServerEndpoint类

package com.heima;import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/**** 监听websocket地址  /myWs*/
@ServerEndpoint("/myWs")
@Component
@Slf4j
@EnableScheduling
public class WsServerEndpoint {static Map<String,Session> map = new ConcurrentHashMap<String,Session>();/**** 连接建立时执行的操作* @param session*/@OnOpenpublic void onOpen(Session session){map.put(session.getId(),session);log.info("websocket is open");}/**** 收到客户端消息执行的操作* @param text*/@OnMessagepublic String OnMessage(String text){log.info("收到了一条信息"+text);return "已收到你的信息" ;}/**** 连接关闭时执行的操作* @param session*/@OnClosepublic void OnClose(Session session){map.remove(session.getId());log.info("连接关闭时执行的操作");}/**** 向客户端发送信息*/@Scheduled(fixedRate = 2000)public void sendMsg() throws IOException {for (String key : map.keySet()){map.get(key).getBasicRemote().sendText("你好,你好");}}
}

2.1.3 WebSocketConfig

package com.heima;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}}

2.1.3 前端测试代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>wsClient</title>
</head>
<body><script>// 创建websocketlet ws = new WebSocket("ws://localhost:8080/myWs")//向服务器发送hellows.onopen=function (){ws.send("hello")}//监听数据ws://localhost:8080/myWsws.onmessage=function (message){console.log(message.data)}
</script>
</body>
</html>

2.1.4测试结果

2.1.4.1 当打开浏览器时

2.1.4.2 当关闭浏览器时

2.1.4.3 当刷新浏览器的时候

2.基于spring提供的类和接口刷新websocket服务器端

2.1:HttpSessionHandShakeInter 握手拦截器

package com.spring;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
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;/**** 握手拦截器*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {log.info(request.getRemoteAddress().toString()+"开始握手");return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {log.info(request.getRemoteAddress().toString()+"完成握手");super.afterHandshake(request, response, wsHandler, ex);}
}

2.2  MyWsHandler 主处理程序

sessionbean封装类
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.socket.WebSocketSession;@Data
@AllArgsConstructor
public class SessionBean {private WebSocketSession webSocketSession;private Integer clientId;
}
 主处理程序
package com.spring;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.scheduling.annotation.EnableScheduling;
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;/**** webSocket 主处理程序*/
@Component
@Slf4j
@EnableScheduling
public class MyWsHandler extends AbstractWebSocketHandler {//map有并发线程问题  所以用ConcurrentHashMapprivate static Map<String, SessionBean> map ;//id有并发问题 所以用Integer的安全类型private static AtomicInteger clientIdMaker;static {map = new ConcurrentHashMap<>();clientIdMaker=new AtomicInteger(0);}//连接建立@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {super.afterConnectionEstablished(session);//将session 进一步封装  id采用的是自增SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());map.put(session.getId(),sessionBean);log.info(map.get(session.getId()).getClientId()+"建立了连接");}//收到消息@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {super.handleTextMessage(session, message);log.info(map.get(session.getId()).getClientId()+":"+message.getPayload());}//传输异常@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {super.handleTransportError(session, exception);if (session.isOpen()){session.close();}map.remove(session.getId());}//连接关闭@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {super.afterConnectionClosed(session, status);log.info(map.get(session.getId()).getClientId()+"关闭连接");}/**** 向客户端发送信息*/@Scheduled(fixedRate = 2000)public void sendMsg() throws IOException {for (String key : map.keySet()){map.get(key).getWebSocketSession().sendMessage(new TextMessage("hello," +"spring socket"));}}
}

2.3 WebSocketConfigurer 注册拦截器和主处理程序以及监听路径

package com.spring;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;import javax.annotation.Resource;@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {@Resourceprivate MyWsHandler wsHandler;@Resourceprivate MyWsInterceptor wsInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(wsHandler,"/myWs1").addInterceptors(wsInterceptor).setAllowedOriginPatterns("*");}
}

2.4 前端测试

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>wsClient</title>
</head>
<body><script>// 创建websocketlet ws = new WebSocket("ws://localhost:8080/myWs1")//向服务器发送hellows.onopen=function (){ws.send("hello")}//监听数据ws://localhost:8080/myWsws.onmessage=function (message){console.log(message.data)}
</script>
</body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

易图讯科技三维电子沙盘系统

深圳易图讯科技有限公司&#xff08;www.3dgis.top&#xff09;创立于2013年&#xff0c;专注二三维地理信息、三维电子沙盘、电子地图、虚拟现实、大数据、物联网和人工智能技术研发&#xff0c;获得20多项软件著作权和软件检测报告&#xff0c;成功交付并实施了1000多个项目&…

【刷题篇】滑动窗口(二)

文章目录 1、水果成篮2、找到字符串中所有字母异位词3、串联所有单词的子串4、最小覆盖子串 1、水果成篮 你正在探访一家农场&#xff0c;农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示&#xff0c;其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多…

Copilot for Microsoft 365 扩充新增 16 种语言

最近&#xff0c;微软公司发布公告&#xff0c;进一步扩大 Copilot for Microsoft 365 语言支持&#xff0c;新增 16 种&#xff0c;支持的语言总数达到 25 种。 新支持的语言如下&#xff1a; 阿拉伯语 捷克语 丹麦语 荷兰语 芬兰语 希伯来语 匈牙利语 韩语 挪威语&am…

找不到d3dx9_42.dll无法继续执行代码的原因分析及解决方法

当您在使用电脑过程中遇到提示“缺少d3dx9_42.dll”时&#xff0c;这实际上是操作系统在运行某些应用程序或游戏时遇到的一个常见问题。D3DX9_42.dll是DirectX 9的一部分&#xff0c;DirectX是一组由微软开发的多媒体处理软件组件&#xff0c;广泛用于提升游戏与多媒体程序的性…

Qt之QMqtt 发送图片数据

简述 MQTT(消息队列遥测传输)是ISO标准下基于发布/订阅范式的消息协议;它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件; MQTT是一个基于客户端-服务器的消息发布/订阅传输协议;MQT…

【Qt-CMake】QT中cmak编译出现CMake Error: The source.. does not match the soused

QT中cmak编译出现CMake Error: The source… does not match the soused 分析 前提是该项目是从另一个路径的项目复制过来的&#xff0c;编写代码时发现无论怎样修改代码&#xff0c;运行后都没有任何变化&#xff0c;以为是qtbug&#xff0c;重构重启都没用&#xff0c;最后…

有了copilot,Word、Excel和PPT终于是成熟软件了

这几个表情想必大家都见过&#xff1a; 这表情包应该有几年了&#xff0c;当初看到只觉得想笑。 一来确实搞笑&#xff0c;二来包含了众多办公一族对这三件套深沉的爱与苦大仇深的怨念。 如今&#xff0c;有了 Copilot for Microsoft 365&#xff0c;这一切&#xff0c;便成了…

Cloudflare国内IP地址使用教程

Cloudflare国内IP地址使用教程 加速网站&#xff1a; 首先我们添加一个 A 记录解析&#xff0c;解析 IP 就是我们服务器真实 IP&#xff1a; 然后侧边栏 SSL/TLS - 自定义主机名&#xff1a; 回退源这里填写你刚刚解析的域名&#xff0c;保存后回退源状态为有效再来接下的操作…

虚拟机CentOS密码重置

1&#xff0c;reboot重启 在出现下面的界面1按e 如果有选项就选择“CentOS Linux &#xff08;3.10.0-327.e17.x86_64&#xff09;7 &#xff08;Core&#xff09;”【我的电脑没有直接显示界面2】 界面1 界面2 2&#xff0c;在上述界面2中继续按e进入编辑模式 找到“ro cr…

Ps各种修改文字超实用方法

介绍 在日常生活中,难免会遇到进行文字修改的ps场景,此时就需要用到比较专业的ps进行文字修改,博主特意整合了多种情况下的文字p图方法进行记录,但是不包含全部情况,只记录日常中常见的情况,也可以解决大部分场景了 原图有可用文字素材 在p图时,我们可以先观察我们要p的图中…

Java面试之分布式篇

分布式锁的实现方案 &#xff08;1&#xff09;用数据库实现分布式锁比较简单&#xff0c;就是创建一张锁表&#xff0c;数据库对字段作唯一性约束。加锁的时候&#xff0c;在锁表中增加一条记录即可&#xff1b;释放锁的时候删除锁记录就行。如果有并发请求同时提交到数据库&…

【Linux-IMX6ULL-DDR3简介测试-RGBLCD控制原理】

目录 1. DDR3 简介1.1 前要基本概念RAM & ROM 2. DDR3测试及初始化3. RGBLCD简介及控制原理3.1 RGBLCD简介3.2.1 RGB LCD时序3.2.2 像素时钟&#xff08;800*400分辨率&#xff09;3.2.2 显存&#xff08;800*400分辨率&#xff09; 3.3 RGBLCD的控制3.3.1 DOTCLK 硬件接口…

Lab4: traps

RISC-V assembly Which registers contain arguments to functions? For example, which register holds 13 in mains call to printf? 根据RISC-V函数调用规范&#xff0c;函数的前8个参数使用a0-a7寄存器传递。 当main函数调用printf函数时&#xff0c;a2寄存器保存13 …

SQL-递归查询

运行环境&#xff1a; Mysql8以上&#xff0c;递归查询功能在8以上版本被正式引入 一、SQL递归查询的概念 递归指的是通过调用函数或过程或自身来解决问题的方法&#xff0c;常用于一些具有规律性循环的操作。SQL递归查询是基于一组初始数据&#xff0c;通过递归查询&#xf…

C++学习笔记3

A. 求出那个数 题目描述 喵喵是一个爱睡懒觉的姑娘&#xff0c;所以每天早上喵喵的妈妈都花费很大的力气才能把喵喵叫起来去上学。 在放学的路上&#xff0c;喵喵看到有一家店在打折卖闹钟&#xff0c;她就准备买个闹钟回家叫自己早晨起床&#xff0c;以便不让妈妈这么的辛苦…

【博士生必看】论文润色大揭秘!

&#x1f4dd; 投稿拒稿&#xff1f;语言不过关&#xff1f;别怕&#xff0c;我来支招&#xff01;&#x1f469;‍&#x1f393; &#x1f31f; 我的论文润色经历&#xff0c;从拒稿到接收的逆袭之路&#xff01;✨ &#x1f449; 【论文润色&#xff0c;我选了它】 我选择了…

嵌入式C语言高级教程:实现基于STM32的环境监测系统

⬇帮大家整理了单片机的资料 包括stm32的项目合集【源码开发文档】 点击下方蓝字即可领取&#xff0c;感谢支持&#xff01;⬇ 点击领取更多嵌入式详细资料 问题讨论&#xff0c;stm32的资料领取可以私信&#xff01; 环境监测系统通过实时收集和分析环境数据&#xff0c;如温度…

水面垃圾监测识别摄像机

随着城市化进程的加快和旅游业的兴起&#xff0c;水域环境污染问题日益突出&#xff0c;水面垃圾成为环境保护的重要问题。为有效监测和清理水面垃圾&#xff0c;水面垃圾监测识别摄像机应运而生。水面垃圾监测识别摄像机利用高清晰度摄像头和智能识别算法&#xff0c;能够实时…

【LeetCode:2391. 收集垃圾的最少总时间 + 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

如何远程操作服务器中的Python编译器并将运行结果返回到Pycharm

文章目录 一、前期准备1. 检查IDE版本是否支持2. 服务器需要开通SSH服务 二、Pycharm本地链接服务器测试1. 配置服务器python解释器 三、使用内网穿透实现异地链接服务器开发1. 服务器安装Cpolar2. 创建远程连接公网地址 四、使用固定TCP地址远程开发 本文主要介绍如何使用Pych…