Springboot整合WebSocket实现浏览器和服务器交互

Websocket定义

代码实现

引入maven依赖

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

配置类

  import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类*/@Configurationpublic class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

WebSocketServer 服务端

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.hc.dialer_server.service.SendMessageService;
import com.hc.dialer_server.utils.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/*** WebSocket的操作类*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{number}")
@DependsOn("springContext")
public class WebSocketServer {SendMessageService sendMessageServiceImpl = SpringContextUtils.getBean("sendMessageServiceImpl");// 记录当前在线连接数private static AtomicInteger onlineSessionClientCount = new AtomicInteger(0);// 记录number和 session的对应关系public static Map<String, Session> connectionMap = new ConcurrentHashMap<>();private String number;@OnOpenpublic void onOpen(@PathParam("number") String number, Session session) throws IOException {log.info("连接建立中 ==> session_id = {}, number = {}", session.getId(), number);// 在线人数+1onlineSessionClientCount.incrementAndGet();this.number = number;connectionMap.put(number, session);session.getBasicRemote().sendText("连接建立成功");log.info("连接建立成功, 当前在线数为: {}, session_id = {}, number = {}", onlineSessionClientCount, session.getId(), number);}@OnClosepublic void onClose(@PathParam("number") String number, Session session) {connectionMap.remove(number);onlineSessionClientCount.decrementAndGet();log.info("连接关闭成功, 当前在线数为: {} ==> 关闭该连接信息: session_id = {}, number = {}", onlineSessionClientCount, session.getId(), number);}@OnMessagepublic void onMessage(String message, Session session) throws Exception {if (StringUtils.isBlank(message)) {return;}JSONObject jsonObject = JSON.parseObject(message);String eventType = jsonObject.getString("eventType");String msg = jsonObject.getString("message");log.info("服务端收到客户端消息 ==> number = {}, eventType = {}, message = {}", number, eventType, msg);session.getBasicRemote().sendText("服务端给客户端发送消息");}@OnDisconnectpublic void onDisconnect(Session session) {connectionMap.remove(number);onlineSessionClientCount.decrementAndGet();log.info("disconnect event ==> number: {}, session_id: {}, 当前在线数: {}", number, session.getId(), onlineSessionClientCount);}@OnErrorpublic void onError(Session session, Throwable error) {log.error("WebSocket发生错误, session id = {}, 错误信息为:{}", session.getId(), error.getMessage());}}

工具类


import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;@Component("springContext")
public class SpringContextUtils implements ApplicationContextAware {/*** Spring应用上下文环境*/private static ApplicationContext applicationContext;/*** 获取对象** @return Object 一个以所给名字注册的bean的实例*/@SuppressWarnings("unchecked")public static <T> T getBean(String name) {return (T) applicationContext.getBean(name);}/*** 获取类型为requiredType的对象*/public static <T> T getBean(Class<T> clz) {return applicationContext.getBean(clz);}/*** 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true** @return boolean*/public static boolean containsBean(String name) {return applicationContext.containsBean(name);}/*** 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)** @return boolean*/public static boolean isSingleton(String name) {return applicationContext.isSingleton(name);}/*** @return Class 注册对象的类型*/public static Class<?> getType(String name) {return applicationContext.getType(name);}@Overridepublic synchronized void setApplicationContext(ApplicationContext applicationContext) {if (SpringContextUtils.applicationContext == null) {SpringContextUtils.applicationContext = applicationContext;}}
}

前端

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>测试webSocket</title>
</head>
<body>
Client传来的number:
<!--<input type="text" th:value="${number}" id="number"/>-->
<p>【eventType】:
<div><input id="toUserId" name="toUserId" type="text" value="message"></div>
<p>【messageText】:
<div><input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【操作】:
<div><button type="button" onclick="sendMessage()">发送消息</button><button type="button" onclick="sendMessage1()">1626</button></div>
</body><script type="text/javascript">var socket;if (typeof (WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");} else {console.log("您的浏览器支持WebSocket");//实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接var number = '1626';console.log("number-->" + number);// socket服务器端的ip和端口var reqUrl = "http://localhost:8080/websocket/" + number;socket = new WebSocket(reqUrl.replace("http", "ws"));//打开事件socket.onopen = function () {console.log("Socket 已打开");//socket.send("这是来自客户端的消息" + location.href + new Date());};//获得消息事件socket.onmessage = function (msg) {console.log("onmessage--" + msg.data);//发现消息进入,开始处理前端触发逻辑};//关闭事件socket.onclose = function () {console.log("Socket已关闭");};//发生了错误事件socket.onerror = function () {alert("Socket发生了错误");//此时可以尝试刷新页面}}function sendMessage() {if (typeof (WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");} else {// console.log("您的浏览器支持WebSocket");var toUserId = document.getElementById('toUserId').value;var contentText = document.getElementById('contentText').value;var msg = '{"eventType":"' + toUserId + '","message":"' + contentText + '"}';console.log(msg);socket.send(msg);}}//发送json串function sendMessage1() {if (typeof (WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");} else {// console.log("您的浏览器支持WebSocket");var toUserId = document.getElementById('toUserId').value;var contentText = document.getElementById('contentText').value;// var msg = '{"eventType":"' + toUserId + '","message":"' + contentText + '"}';var msg = '{"eventType":"' + toUserId + '","message":{"number":"1626","serviceNumber":"60600","req":"event01"}}';console.log(msg);socket.send(msg);}}</script>
</html>

测试

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023 编程资料合集汇总

资源合集 名称链接Rabbitmq精讲&#xff0c;项目驱动落地&#xff0c;分布式事务拔高资料https://www.aliyundrive.com/s/5VwmhTCPBNa程序员书籍大全https://www.aliyundrive.com/s/Kz5UiijQB7i后端Java教程&#xff08;学完直接去BAT&#xff09;https://www.aliyundrive.com…

机器学习笔记 - 3D 对象跟踪极简概述

一、简述 大多数对象跟踪应用程序都是 2D 的。但现实世界是 3D 的,无论您是跟踪汽车、人、直升机、导弹,还是进行增强现实,您都需要使用 3D。在 CVPR 2022(计算机视觉和模式识别)会议上,已经出现了大量3D目标检测论文。 二、什么是 3D 对象跟踪? 对象跟踪是指随着时间的…

【环境搭建】linux docker-compose安装seata1.6.1,使用nacos注册、db模式

新建目录&#xff0c;挂载用 mkdir -p /data/docker/seata/resources mkdir -p /data/docker/seata/logs 给权限 chmod -R 777 /data/docker/seata 先在/data/docker/seata目录编写一个使用file启动的docker-compose.yml文件&#xff08;seata包目录的script文件夹有&#…

项目管理软件排行榜:点赞榜TOP5揭晓!

通过项目管理软件企业可以快速、高效地管理项目、整合团队成员以及资源。现如今市场上各类项目管理软件层出不穷&#xff0c;因此选择一款适合自身企业需求的软件显得尤为重要。本文将为大家介绍项目管理软件排行榜点赞榜&#xff0c;为大家选购提供一些参考。 1.Zoho Project…

【来点小剧场--项目测试报告】个人博客项目自动化测试

前述 针对个人博客项目进行测试&#xff0c;个人博客主要由七个页面构成&#xff1a;注册页、登录页、个人博客列表页、博客发布页、博客修改页、博客列表页、博客详情页&#xff0c;主要功能包括&#xff1a;注册、登录、编辑并发布博客、修改已发布的博客、查看详情、删除博…

解惑Android Scoped Storage

原文链接 Android Scoped Storage Puzzles 安卓对于文件存储这块&#xff0c;其实是相当混乱的&#xff0c;在早期的版本中对存储甚至是没有所谓的管理的&#xff0c;有多种方法可以操作文件存储&#xff0c;比如通过Java原生的方式(File/InputStream/OutputStream)&#xff0…

【微服务 SpringCloudAlibaba】实用篇 · Nacos注册中心

微服务&#xff08;5&#xff09; 文章目录 微服务&#xff08;5&#xff09;1. 认识和安装Nacos2. 服务注册到nacos和拉取服务1&#xff09;引入依赖2&#xff09;配置nacos地址3&#xff09;重启 3. 服务分级存储模型3.1 给user-service配置集群3.2 同集群优先的负载均衡 4. …

php74 安装sodium

下载编译安装libsodium wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz tar -zxf libsodium-1.0.18-stable.tar.gz cd libsodium-stable ./configure --without-libsodium make && make check sudo make install下载编译安装…

【Python搜索算法】广度优先搜索(BFS)算法原理详解与应用,示例+代码

目录 1 广度优先搜索 2 应用示例 2.1 迷宫路径搜索 2.2 社交网络中的关系度排序 2.3 查找连通区域 1 广度优先搜索 广度优先搜索&#xff08;Breadth-First Search&#xff0c;BFS&#xff09;是一种图遍历算法&#xff0c;用于系统地遍历或搜索图&#xff08;或树…

Linux Zabbix企业级监控平台+cpolar实现远程访问

文章目录 前言1. Linux 局域网访问Zabbix2. Linux 安装cpolar3. 配置Zabbix公网访问地址4. 公网远程访问Zabbix5. 固定Zabbix公网地址 前言 Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。能监视各种网络参数&#xff0c;保证服务器系…

HTML三叉戟,标签、元素、属性各个的意义是什么?

&#x1f31f;&#x1f31f;&#x1f31f; 专栏详解 &#x1f389; &#x1f389; &#x1f389; 欢迎来到前端开发之旅专栏&#xff01; 不管你是完全小白&#xff0c;还是有一点经验的开发者&#xff0c;在这里你会了解到最简单易懂的语言&#xff0c;与你分享有关前端技术和…

【Java基础面试十二】、说一说你对面向对象的理解

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 说一说你对面向对象的理…

thinkphp5.1 获取缓存cache(‘cache_name‘)特别慢,php 7.0 unserialize 特别慢

thinkphp5.1 获取缓存cache(‘cache_name’)特别慢&#xff0c;php 7.0 unserialize 特别慢 场景&#xff1a; 项目中大量使用了缓存&#xff0c;本地运行非常快&#xff0c;二三百毫秒&#xff0c;部署到服务器后 一个表格请求就七八秒&#xff0c;最初猜想是数据库查询慢&am…

消息队列学习分享

消息队列学习 消息队列来解决问题 &#xff08;1&#xff09;异步处理 消息通知、日志管理、更新统计数据等步骤 &#xff08;2&#xff09;流量控制 如何避免过多的请求压垮我们的系统&#xff1f; 比如一个秒杀系统&#xff0c;网关在收到请求后&#xff0c;将请求放入…

Kotlin中的数值类型

在Kotlin中&#xff0c;Byte、Short、Int、Long、Float和Double是基本数据类型&#xff0c;用于表示不同范围和精度的数值。 Byte&#xff08;字节&#xff09;&#xff1a;Byte类型是8位有符号整数类型&#xff0c;取值范围为-128到127。在Kotlin中&#xff0c;可以使用字面值…

vscode工程屏蔽不使用的文件夹或文件的方法

一. 简介 vscode是一款 微软提供的免费的代码编辑软件。 对于 IMX6ULL-ALPHA开发板而言&#xff0c;NXP官方uboot一定会支持不止 IMX6ULL芯片的代码&#xff0c;也不止支持 一种架构&#xff0c;还支持其他芯片或架构的源码文件。 为了方便阅读代码&#xff0c;vscode软件可…

腾讯云我的世界mc服务器多少钱一年?

腾讯云我的世界mc服务器多少钱&#xff1f;95元一年2核2G3M轻量应用服务器、2核4G5M带宽优惠价218元一年、4核8G12M带宽轻量服务器446元一年&#xff0c;云服务器CVM标准型S5实例2核2G优惠价280元一年、2核4G配置服务器748元一年&#xff0c;腾讯云百科txybk.com分享腾讯云我的…

[LeetCode周赛复盘] 第 115 场双周赛20231014

[LeetCode周赛复盘] 第 115 场双周赛20231014 一、本周周赛总结100095. 上一个遍历的整数1. 题目描述2. 思路分析3. 代码实现 100078. 最长相邻不相等子序列 I1. 题目描述2. 思路分析3. 代码实现 100077. 最长相邻不相等子序列 II1. 题目描述2. 思路分析3. 代码实现 100029. 和…

【数据结构】排序--选择排序(堆排序)

目录 一 堆排序 二 直接选择排序 一 堆排序 堆排序(Heapsort)是指利用堆积树&#xff08;堆&#xff09;这种数据结构所设计的一种排序算法&#xff0c;它是选择排序的一种。它是 通过堆来进行选择数据。 需要注意的是排升序要建大堆&#xff0c;排降序建小堆。 直接选择排…

HEIC转jpg

下载imagemagick,安装 https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-20-Q16-HDRI-x64-dll.exe cmd D:\soft\ImageMagick-7.1.1-Q16-HDRI\magick.exe "C:\Users\Gamer\Downloads\iCloud 照片1\iCloud 照片\IMG_3889.HEIC" IMG_3889.jpg