websocket 实现前后端通信

server/2025/2/6 14:35:34/

 1.spring boot 引入依赖

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

 2.添加配置类

java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @Description: 开启WebSocket支持*/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

3.构建websocketserver

java">import lombok.Getter;
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;/*** @version 1.0* @description 存放websocket连接的集合* @date 2025/1/20 10:46**/
@Slf4j
public class WebSockeServerLocalCache {@Getterprivate final static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();/*** 将指定的键添加到集合中。** @param webSocketServer 要添加到集合中的键* @return 添加成功,则返回 true;否则返回 false*/public static void save(WebSocketServer webSocketServer) {log.info("添加到缓存中:{}", webSocketServer);webSocketSet.add(webSocketServer);}/*** 判断集合中是否不包含指定的键。** @param webSocketServer 要删除的实例*/public static boolean remove(WebSocketServer webSocketServer) {return webSocketSet.remove(webSocketServer);}/**** 根据sid获取websocket连接* @param sid* @return*/public static CopyOnWriteArraySet<WebSocketServer> get(String sid) {return webSocketSet.stream().filter(webSocketServer -> webSocketServer.getSid().equals(sid)).collect(Collectors.toCollection(CopyOnWriteArraySet::new));}
}
java">
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;/*** @version 1.0* @description  WebSocketServer实例* @date 2025/1/20 10:46**/
@Getter
@Slf4j
@Service
@ServerEndpoint(value = "/sysoperation/alarmWebSocketData/{sid}", encoders = {CustomEncoder.class})
public class WebSocketServer {// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static int onlineCount = 0;//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;//接收sidprivate String sid = "";/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {this.session = session;this.sid = sid;//在线数加1addOnlineCount();//保存实例到set中WebSockeServerLocalCache.save(this);sendMessage("conn_success");log.info("有新窗口开始监听sid{},当前在线人数为:{}",sid, getOnlineCount());}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {//从set中删除
//        webSocketSet.remove(this);boolean remove = WebSockeServerLocalCache.remove(this);log.info("移除的sid为:{},结果为{}",sid,remove);//在线数减1subOnlineCount();//断开连接情况下,更新占用情况为释放log.info("释放的sid为:" + sid);//这里写你 释放的时候,要处理的业务  todolog.info("有一连接关闭!当前在线人数为" + getOnlineCount());// 连接关闭 停止任务}/*** 收到客户端消息后调用的方法** @Param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自窗口sid{},的信息:{}",sid, message);//群发消息WebSockeServerLocalCache.get(sid).forEach(webSocketServer -> {webSocketServer.sendMessage(message);});}/*** @Param session* @Param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发生错误");error.printStackTrace();}/*** 实现服务器主动推送*/public void sendMessage(Object message) {try {this.session.getBasicRemote().sendObject(message);} catch (IOException | EncodeException e) {log.error("推送消息发生异常:" + e.getMessage());}}/*** 群发自定义消息*/public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {log.info("推送消息到窗口" + sid + ",推送内容:" + message);CopyOnWriteArraySet<WebSocketServer> webSocketServers = WebSockeServerLocalCache.get(sid);for (WebSocketServer item : webSocketServers) {//这里可以设定只推送给这个sid的,为null则全部推送if (sid == null) {// item.sendMessage(message);} else if (item.sid.equals(sid)) {item.sendMessage(message);}}}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}public static synchronized void subOnlineCount() {WebSocketServer.onlineCount--;}}

其他公共类

java">@Data
public class AlarmInfoDTO implements Serializable {private String  alarmType;private String  time;private String  alarmContent;private String alarmTitle;private String  alarmReceivePerson;private String  realAlarm="Real";private AlarmInfoExtDataDTO  extData;
}@Data
public class AlarmInfoExtDataDTO implements Serializable {private Long taskId;private String deviceId;private String imagePath;private String storagePath;private String motorVehicleId;private String plateNo;private String plateColor;private String plateClass;private String vehicleClass;private String vehicleBrand;private String deviceName;private String latitude;private String longitude;private String areaName;}import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import com.fasterxml.jackson.databind.ObjectMapper;public class CustomEncoder implements Encoder.Text<Object> {private static final ObjectMapper objectMapper = new ObjectMapper();@Overridepublic String encode(Object object) throws EncodeException {try {return objectMapper.writeValueAsString(object);} catch (Exception e) {throw new EncodeException(object, "Error encoding object", e);}}@Overridepublic void init(EndpointConfig config) {// 初始化时的逻辑(可选)}@Overridepublic void destroy() {// 销毁时的逻辑(可选)}
}

前端html测试

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Java后端WebSocket的Tomcat实现</title>
</head><body>
<h1>Welcome</h1>
<br/><input id="text" type="text" />
<button onclick="send()">发送消息</button>
<hr/>
<button onclick="closeWebSocket()">关闭WebSocket连接</button>
<hr/>
<div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;//判断当前浏览器是否支持WebSocketif('WebSocket' in window) {//改成你的地址 ws://127.0.0.1:10242/sysoperation/alarmWebSocketData/{sid} 用taskid 当作sidwebsocket = new WebSocket("ws://127.0.0.1:10242/sysoperation/alarmWebSocketData/48");} else {alert('当前浏览器 Not support websocket')}//连接发生错误的回调方法websocket.onerror = function() {setMessageInnerHTML("WebSocket连接发生错误");};//连接成功建立的回调方法websocket.onopen = function() {setMessageInnerHTML("WebSocket连接成功");}var U01data, Uidata, Usdata//接收到消息的回调方法websocket.onmessage = function(event) {console.log(event);setMessageInnerHTML(event);//setechart()}//连接关闭的回调方法websocket.onclose = function() {setMessageInnerHTML("WebSocket连接关闭");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function() {closeWebSocket();}//将消息显示在网页上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//关闭WebSocket连接function closeWebSocket() {websocket.close();}//发送消息function send() {var message = document.getElementById('text').value;websocket.send('{"msg":"' + message + '"}');setMessageInnerHTML(message + "&#13;");}
</script></html>


http://www.ppmy.cn/server/165429.html

相关文章

线性数据结构:单向链表

放弃眼高手低&#xff0c;你真正投入学习&#xff0c;会因为找到一个新方法产生成就感&#xff0c;学习不仅是片面的记单词、学高数......只要是提升自己的过程&#xff0c;探索到了未知&#xff0c;就是学习。 目录 一.链表的理解 二.链表的分类&#xff08;重点理解&#xf…

css小知识

1、clip-path clip-path: <clip-source> | [ <basic-shape> || <geometry-box> ] | none; <clip-source>&#xff1a;可以是一个 URL&#xff0c;指向一个 SVG <clipPath> 元素。 <basic-shape>&#xff1a;基本形状函数&#xff0c;用于…

基于强化学习的机器人自主导航与避障

前言 自主导航与避障是机器人领域的核心研究方向之一&#xff0c;传统的避障算法多依赖于先验模型和规则设计。然而&#xff0c;面对复杂且动态的环境&#xff0c;这些算法常表现出一定的局限性。强化学习&#xff08;Reinforcement Learning, RL&#xff09;通过与环境交互&a…

Web安全|渗透测试|网络安全

基础入门(P1-P5) p1概念名词 1.1域名 什么是域名&#xff1f; 域名&#xff1a;是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称&#xff0c;用于在数据传输时对计算机的定位标识&#xff08;有时也指地理位置&#xff09;。 什么是二级域名多级域名…

物联网 STM32【源代码形式-使用以太网】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】

物联网&#xff08;IoT&#xff09;‌是指通过各种信息传感器、射频识别技术、全球定位系统、红外感应器等装置与技术&#xff0c;实时采集并连接任何需要监控、连接、互动的物体或过程&#xff0c;实现对物品和过程的智能化感知、识别和管理。物联网的核心功能包括数据采集与监…

AI生成产品原型与设计稿:我的工具使用心得与推荐

摘要 AI在设计领域的应用日益广泛&#xff0c;尤其在生成产品原型和UI设计稿方面表现突出。本文分享了我常用的AI设计工具及其使用体验&#xff0c;展示了AI生成的设计稿与实际开发页面的对比。此外&#xff0c;还推荐了其他同类工具&#xff0c;并附上官网链接。未来将继续尝试…

Linux 系统上安装 Docker 并进行配置

Docker 是一种开源的应用容器引擎&#xff0c;它允许开发者打包他们的应用以及应用的依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口&#xff08;类似 iPh…

openRv1126 AI算法部署实战之——Tensorflow模型部署实战

在RV1126开发板上部署Tensorflow算法&#xff0c;实时目标检测RTSP传输。视频演示地址 rv1126 yolov5 实时目标检测 rtsp传输_哔哩哔哩_bilibili ​ 一、准备工作 从官网下载tensorflow模型和数据集 手动在线下载&#xff1a; https://github.com/tensorflow/models/b…