SpringBoot_websocket实战

SpringBoot_websocket实战

  • 前言
  • 1.websocket入门
    • 1.1 websocket最小化配置
      • 1.1.1 后端配置
      • 1.1.2 前端配置
    • 1.2 websocket使用sockjs
      • 1.2.1 后端配置
      • 1.2.2 前端配置
    • 1.3 websocket使用stomp协议
      • 1.3.1 后端配置
      • 1.3.2 前端配置
  • 2.websocket进阶
    • 2.1 websocket与stomp有什么区别
    • 2.2 websocket与stomp怎么选
  • 3.websocket实战
    • 3.1 案例1:websocket 实现web-ssh
    • 3.2 案例2:websocket 实现控制台日志在线展示

前言

本文记录说明springboot websocket示例及实战,你将学习到
三种websocket开发方式

  • /websocket 接口演示原生websocket前后端收发websocket消息
  • /websocket-sockjs 演示使用sockjs 前后端收发websocket消息
  • /weboscket-stomp 演示使用stomp协议使用websocket

以及通过实战演示在不同业务场景的技术选择

  • web-ssh 使用sockjs点对点数据传输
  • 日志项目 使用stomp广播数据

使用环境:

  • springboot: 2.3.2.RELEASE
  • jdk: java11

1.websocket入门

Spring Boot WebSocket是Spring框架的一部分,用于实现WebSocket通信协议的支持。WebSocket是一种双向通信协议,允许服务器与客户端之间进行实时、低延迟的数据交换,适用于实时聊天、实时通知、在线协作和实时数据展示等场景。Spring Boot WebSocket提供了使用WebSocket的简化和高效的方法,让开发者能够轻松地实现WebSocket通信。

以下是Spring Boot WebSocket的主要特点和概念:

  1. WebSocket协议支持: Spring Boot WebSocket支持WebSocket通信协议,允许双向的、实时的通信。WebSocket允许服务器主动向客户端推送数据,而不需要客户端发起请求。
  2. STOMP协议支持: 除了原始WebSocket,Spring Boot WebSocket还支持STOMP(Simple Text Oriented Messaging Protocol)协议。STOMP是一个基于文本的协议,它提供了更高级的消息传递功能,例如消息订阅、目标广播和认证等。
  3. 消息处理器: Spring Boot WebSocket允许你定义消息处理器,用于处理WebSocket消息。你可以编写处理器来处理接收到的消息,并决定如何响应。
  4. 消息代理: Spring Boot WebSocket支持消息代理,你可以配置一个消息代理服务器(如RabbitMQ或ActiveMQ),用于处理WebSocket消息的分发和广播。这使得构建分布式和扩展的WebSocket应用程序更容易。
  5. 消息广播: Spring Boot WebSocket允许你将消息广播到多个订阅者。这对于实现群聊、广播通知和实时数据展示等功能非常有用。
  6. 安全性: Spring Boot WebSocket提供了与Spring Security集成的方式,可以轻松实现WebSocket连接的安全性和认证。
  7. SockJS支持: Spring Boot WebSocket还支持SockJS,这是一个JavaScript库,用于处理浏览器不支持WebSocket的情况下的降级处理,使得WebSocket通信在各种浏览器上都能正常工作

1.1 websocket最小化配置

步骤说明

  • 后端通过@EnableWebSocket注解开启websocket功能
    1. 定义websocket的访问端点 (作用: 定义对外暴露websocket接口)
    2. 定义websocket的处理器 (作用: 解决websocket建立后消息怎么处理)
  • 前端通过new WebSocket(“ws://localhost:9090/websocket”); 打开websocket连接并监听消息

1.1.1 后端配置

  • maven 依赖
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--websocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
  • WebSocketConfiguration 实现WebSocketConfigurer注册websocket接口及处理器
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {@Autowiredprivate EchoWebSocketHandler echoWebSocketHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 配置原生WebSocket处理器registry.addHandler(echoWebSocketHandler, "/websocket").setAllowedOrigins("*"); //允许跨域}@Beanpublic EchoWebSocketHandler echoWebSocketHandler() {return new EchoWebSocketHandler();}
}
  • EchoWebSocketHandler 实现WebSocketHandler接口, 接受消息后简单打印转发消息
public class EchoWebSocketHandler implements WebSocketHandler {private static final Logger LOGGER = LoggerFactory.getLogger(EchoWebSocketHandler.class);@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {// 连接建立时的处理逻辑LOGGER.info("[websocket-echo] session:{} ConnectionEstablished", session.getId());}@Overridepublic void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws IOException {String payload = (String) message.getPayload();LOGGER.info("[websocket-echo] session:{} receive:{}", session.getId(), payload);session.sendMessage(new TextMessage(payload));}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {// 处理传输错误}// 连接关闭时的处理逻辑@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {LOGGER.info("[websocket-echo] WebSocketSession[{}] close all ssh connection", session.getId());}@Overridepublic boolean supportsPartialMessages() {return false;}
}

1.1.2 前端配置

TODO 说明下WebSocket 对象作用

<!DOCTYPE html>
<html>
<head><title>原始WebSocket示例</title>
</head>
<body>
<h1>测试默认websocket 接发消息</h1>
<div id="messages"></div>
<input type="text" id="message" placeholder="输入消息">
<button onclick="sendMessage()">发送</button><script>var socket = new WebSocket("ws://localhost:9090/websocket");socket.onopen = function(event) {console.log("WebSocket连接已打开");};socket.onmessage = function(event) {var messages = document.getElementById("messages");messages.innerHTML += "<p>" + event.data + "</p>";};function sendMessage() {var messageInput = document.getElementById("message");var message = messageInput.value;socket.send(message);messageInput.value = "";}
</script>
</body>
</html>

1.2 websocket使用sockjs

为了区别原生WebSocket处理器,以示区别,再注册一个接口/websocket-sockjs. 并且开启.withSockJS()

1.2.1 后端配置

@Configuration
@EnableWebSocket
@Import({WebSocketStompConfiguration.class})
public class WebSocketConfiguration implements WebSocketConfigurer {@Autowiredprivate EchoWebSocketHandler echoWebSocketHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 配置原生WebSocket处理器器registry.addHandler(echoWebSocketHandler, "/websocket").setAllowedOrigins("*");//WebSocket connection to 'ws://localhost:9090/websocket' failed: Error during WebSocket handshake: Unexpected response code: 200//.withSockJS();//.withSockJS()的作用是声明我们想要使用 SockJS 功能,如果WebSocket不可用的话,会使用 SockJS。(前端需要使用sockjs库)registry.addHandler(echoWebSocketHandler, "/websocket-sockjs").setAllowedOrigins("*").withSockJS();}@Beanpublic EchoWebSocketHandler echoWebSocketHandler() {return new EchoWebSocketHandler();}
}

1.2.2 前端配置

使用sockjs需要引入前端sockjs的库: https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js

<!DOCTYPE html>
<html>
<head><title>原始WebSocket示例</title><script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
</head>
<body>
<h1>测试websocket sockjs接发消息</h1>
<div id="messages"></div>
<input type="text" id="message" placeholder="输入消息">
<button onclick="sendMessage()">发送</button><script>// var socket = new WebSocket("ws://localhost:9090/websocket");//原始写法var socket = new SockJS('http://localhost:9090/websocket-sockjs');// 依赖sockjs库socket.onopen = function(event) {console.log("WebSocket连接已打开");};// 监听websockt消息回调socket.onmessage = function(event) {var messages = document.getElementById("messages");messages.innerHTML += "<p>" + event.data + "</p>";};// 定义连接关闭时的回调函数socket.onclose = function () {console.log('WebSocket 连接已关闭');};// 定义连接错误时的回调函数socket.onerror = function (e) {console.error('WebSocket 连接出错:', e);};function sendMessage() {var messageInput = document.getElementById("message");var message = messageInput.value;socket.send(message);messageInput.value = "";}
</script>
</body>
</html>

1.3 websocket使用stomp协议

步骤说明

  • 启用stomp协议, 通过@EnableWebSocketMessageBroker 并注册stomp的端点
    1. 定义stomp端点 WebSocketStompConfiguration
    2. 配置stomp消息路由 TestWebSocketStompController

1.3.1 后端配置

@EnableWebSocketMessageBroker //在 WebSocket 上启用 STOMP
public class WebSocketStompConfiguration {@Bean@ConditionalOnMissingBeanpublic WebSocketMessageBrokerConfigurer brokerConfigurer() {return new WebSocketMessageBrokerConfigurer() {/*** stomp 协议,一种格式比较简单且被广泛支持的通信协议,spring4提供了以stomp协议为基础的websocket通信实现。* spring 的websocket实现,实际上是一个简易版的消息队列(而且是主题-订阅模式的)* @param registry*/@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {// "/stomp-websocket",客户端需要注册这个端点进行链接,// .withSockJS()的作用是声明我们想要使用 SockJS 功能,如果WebSocket不可用的话,会使用 SockJS。registry.addEndpoint("/websocket-stomp").setAllowedOrigins("*").withSockJS();}};}}
  • 配置消息转发路由
@Controller
public class TestWebSocketStompController {private static final Logger LOGGER = LoggerFactory.getLogger(TestWebSocketStompController.class);@AutowiredSimpMessagingTemplate messagingTemplate;@GetMapping("/websocket/print/{msg}")@ResponseBodypublic String print(@PathVariable String msg) {messagingTemplate.convertAndSend("/topic/print", msg);return msg;}@MessageMapping("/app/{destination}") // 使用 {destination} 占位符来捕获动态的目的地@SendTo("/topic/print") // 服务器广播消息的目的地public String handleMessage(@DestinationVariable String destination, String message) {// 处理接收到的消息LOGGER.info("Dynamic destination:[{}] Received message:{}", destination, message);// 根据动态目的地执行不同的操作if ("destination1".equals(destination)) {// 处理目的地1的操作} else if ("destination2".equals(destination)) {// 处理目的地2的操作} else {// 直接转发到对应订阅地址messagingTemplate.convertAndSend("/topic/" + destination, "copy:" + message);}// 可以根据需要添加更多的条件// 返回响应消息return message;}
}
  • 最后通过@Import导入WebSocketStompConfiguration配置
@Configuration
@EnableWebSocket
@Import({WebSocketStompConfiguration.class})
public class WebSocketConfiguration implements WebSocketConfigurer {@Autowiredprivate EchoWebSocketHandler echoWebSocketHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 配置原生WebSocket处理器registry.addHandler(echoWebSocketHandler, "/websocket").setAllowedOrigins("*");//WebSocket connection to 'ws://localhost:9090/websocket' failed: Error during WebSocket handshake: Unexpected response code: 200//.withSockJS();//.withSockJS()的作用是声明我们想要使用 SockJS 功能,如果WebSocket不可用的话,会使用 SockJS。(前端需要使用sockjs库)registry.addHandler(echoWebSocketHandler, "/websocket-sockjs").setAllowedOrigins("*").withSockJS();}@Beanpublic EchoWebSocketHandler echoWebSocketHandler() {return new EchoWebSocketHandler();}
}

1.3.2 前端配置

前端依赖sockjs及stomp.min.js的库

<!DOCTYPE html>
<html>
<head><title>WebSocket Example</title><script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.2/sockjs.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script></head>
<body>
<h1>测试websocket stomp协议接发消息</h1>
<h2>发送示例</h2>
<input type="text" id="sendDestination" placeholder="Enter send destination"><input type="text" id="message" placeholder="Enter your message">
<button onclick="sendMessage()">Send Message</button><hr>
<h2>订阅示例</h2>
<input type="text" id="listenDestination" placeholder="Enter listen destination">
<button onclick="subscribeToDestination()">Subscribe</button>
<div id="messages"></div><script>var stompClient = null;var listenDestination = null;function connect() {var socket = new SockJS('/websocket-stomp'); // WebSocket端点stompClient = Stomp.over(socket);stompClient.connect({}, function (frame) {console.log('stomp Connected: ' + frame);});}function sendMessage() {var sendDestination = document.getElementById('sendDestination').value; // 获取发送目的地var message = document.getElementById('message').value;stompClient.send('/app/' + sendDestination, {}, message); // 发送消息到指定的目的地}function subscribeToDestination() {listenDestination = document.getElementById('listenDestination').value; // 获取监听目的地stompClient.subscribe('/topic/' + listenDestination, function (message) {displayMessage(message.body);});}function displayMessage(message) {var messagesDiv = document.getElementById('messages');var p = document.createElement('p');p.appendChild(document.createTextNode(message));messagesDiv.appendChild(p);}connect();
</script>
</body>
</html>

2.websocket进阶

2.1 websocket与stomp有什么区别

  • WebSocket
    1. WebSocket 是一种通信协议: WebSocket 是一种在Web浏览器和服务器之间提供双向通信的协议。它允许在客户端和服务器之间创建持久性的连接,以便在连接建立后实时地发送和接收消息。
    2. 原始的、低级的协议: WebSocket 是一种相对较低级的协议,它允许在两端之间直接发送原始的消息帧(frames)。这意味着你可以通过WebSocket发送任意的二进制或文本数据。
    3. 需要自行处理消息格式和路由逻辑: WebSocket 本身并没有规定消息的格式或路由逻辑。在WebSocket上发送的消息可以是任意格式的数据,你需要自行定义消息的结构和处理逻辑。
  • STOMP
    1. STOMP 是一种消息协议: STOMP 是一种基于文本的简单消息协议,它定义了客户端和消息代理(broker)之间如何进行交互的规范。STOMP 通常运行在WebSocket之上,它提供了一种在客户端和服务器之间进行实时消息通信的方式。
    2. 面向文本的消息格式: STOMP 消息是文本格式的,它使用类似于HTTP报文的格式来定义消息的头部和体。这种面向文本的格式使得它易于阅读和调试。
    3. 定义了消息的结构和路由逻辑: STOMP 规定了消息的格式和消息目的地的语义。它定义了消息头部的各种属性(例如,目的地、消息类型等),并提供了一种简单的消息路由机制,使得消息能够被发送到特定的目的地。

2.2 websocket与stomp怎么选

如果你期望WebSocket连接之间是隔离的,不需要共享数据,那么使用原始的WebSocket通信是一个合适的选择。原始WebSocket通信提供了一种简单而轻量级的方式,每个连接都是独立的,不会共享会话数据。

STOMP协议通常用于需要高级消息传递功能和消息广播的场景,其中不同连接之间需要共享数据。如果你不需要这种复杂性,原始WebSocket通信足以满足需求,而且更容易理解和维护。

因此,你可以根据你的应用程序需求选择使用原始WebSocket通信或STOMP协议。如果只需要简单的双向通信并希望保持连接之间的隔离,原始WebSocket通信通常是一个更直接的选择

3.websocket实战

3.1 案例1:websocket 实现web-ssh

springboot实现webssh功能, 使用xterm(前端) + websocket + jsch技术实现。后端主要实现websocket消息与jsch命令收发即可。还在开发中, 篇幅关系,实现过程就不写了。有需要点赞或留言,开源后再通知。

在这里插入图片描述

3.2 案例2:websocket 实现控制台日志在线展示

web在线查看springboot后台日志,源码参考:https://github.com/easycode8/easy-log 的easy-log-web模块, 代码量很少。

在这里插入图片描述

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

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

相关文章

思维模型 重叠效应

本系列文章 主要是 分享 思维模型 &#xff0c;涉及各个领域&#xff0c;重在提升认知。相似内容易被混淆或遗忘。 1 重叠效应的应用 1.1 重叠效应在教育中的应用 1 通过避免重叠效应提升学习效率 为了避免重叠效应&#xff0c;通过对比、归纳等方法来帮助学生更好地理解和掌…

黑马React18: Redux

黑马React: Redux Date: November 19, 2023 Sum: Redux基础、Redux工具、调试、美团案例 Redux介绍 Redux 是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia&#xff08;Vuex&#xff09;&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管…

VPS配置了swap没发挥作用怎么办

1 swap配置了但没用上 我的服务器内存是2G&#xff0c;装多一点东西就不够用&#xff0c;于是我给他分配了2G的swap&#xff0c;等了几小时&#xff0c;swap还是一点都没有使用 Linux中Swap&#xff08;即&#xff1a;交换分区&#xff09;&#xff0c;类似于Windows的虚拟内存…

MongoDB的常用操作以及python连接MongoDB

一,MongoDB的启动 mongod --dbpath..\data\db mongodb注意同时开两个窗口&#xff0c;不要关&#xff01; 二, MongoDB的简单使用 简单介绍一下mongoDB中一些操作 show dbs: 显示所有数据库 show databases: 显示所有数据库 use xxxx: 使用指定数据库/创建数据库&#xff08…

时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现BiLSTM-Adaboost…

【精选】Ajax技术知识点合集

Ajax技术详解 Ajax简介 Ajax 即“Asynchronous Javascript And XML”&#xff08;异步 JavaScript 和 XML&#xff09;&#xff0c;是指一种创建 交互式、快速动态应用的网页开发技术&#xff0c;无需重新加载整个网页的情况下&#xff0c;能够更新页面局 部数据的技术。通过在…

Scala如何写一个通用的游戏数据爬虫程序

以前想要获取一些网站数据的时候&#xff0c;都是通过人工手动复制粘贴&#xff0c;这样的效率及其低下。数据少无所谓&#xff0c;如果需要采集大量数据&#xff0c;手动就显得乏力了。半夜睡不着&#xff0c;爬起来写一段有关游戏商品数据的爬虫通用模板&#xff0c;希望能帮…

专业pdf编辑工具PDF Expert mac中文版特点介绍

PDF Expert mac是一款专业的PDF编辑和阅读工具。它可以帮助用户在Mac、iPad和iPhone等设备上查看、注释、编辑、填写和签署PDF文档。 PDF Expert mac软件特点 PDF编辑&#xff1a;PDF Expert提供了丰富的PDF编辑功能&#xff0c;包括添加、删除、移动、旋转、缩放、裁剪等操作…

基于顺序表实现通讯录

1.功能实现 功能要求 1&#xff09;至少能够存储100个人的通讯信息 2&#xff09;能够保存用户信息&#xff1a;名字、性别、年龄、电话、地址等 3&#xff09;增加联系人信息 4&#xff09;删除指定联系人 5&#xff09;查找制定联系人 6&#xff09;修改指定联系人 7&#xf…

网络运维与网络安全 学习笔记2023.11.22

网络运维与网络安全 学习笔记 第二十三天 今日目标 VLAN间通信之交换机、VLAN间通信综合案例、浮动路由 VRRP原理与配置、VRRP链路跟踪、VRRP安全认证 VLAN间通信之交换机 单臂路由的缺陷 在内网的VLAN数量增多时&#xff0c;单臂链路容易成为网络瓶颈 三层交换机 具备…

react中模块化样式中:global的作用

在react中如果是通过import styles from ./index.less这种方式模块化引入样式的话&#xff0c;那么编译后的less文件里的样式名都会自动添加后缀。而:global的作用就是不让类名添加后缀

利用 Apache Ranger 管理 Amazon EMR 中的数据权限

需求背景简介 系统安全通常包括两个核心主题&#xff1a;身份验证和授权。一个解决“用户是谁”的问题&#xff0c;另一个解决“用户允许执行什么操作”的问题。在大数据领域&#xff0c;Apache Ranger 是最受欢迎的授权选择之一&#xff0c;它支持所有主流大数据组件&#xff…

微机原理_1

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 1,下列8086CPU标志寄存器的标志位中,不属于状态标志位的是(&#xff09; A. OF B. IF C. AF D. PF 8086微处理器可寻址访问的最大…

万界星空科技SMT行业生产管理MES系统解决方案

一、SMT行业特点&#xff1a; SMT&#xff08;Surface Mounted Technology&#xff09;作为电子组装行业里首先的技术和工艺&#xff0c;选择合适的MES解决方案来保障SMT生产的成功至关重要。 电子行业涉及的范围非常广&#xff0c;包含了汽车、电脑、电视、手机等产品上&…

HCIA-Datacom跟官方路线学习

通过两次更换策略。最后找到最终的学习方案&#xff0c;华为ICT官网有对这个路线的学习&#xff0c;hcia基础有这个学习路线&#xff0c;hcip也有目录路线。所以&#xff0c;最后制定学习路线&#xff0c;是根据这个认证的路线进行学习了&#xff1a; 官网课程&#xff1a;课程…

everything的高效使用方法

目录 前言1 everything的简单介绍2 常用搜索3 语法搜索4 正则表达式搜索5 服务器功能 前言 本文介绍everything软件的高效使用方法&#xff0c;everything是一款在系统中快速搜索文件的软件&#xff0c;能够帮助人们快速定位需要查找的文件。首先介绍everything软件的作用和使…

掌握 AI 和 NLP:深入研究 Python — 情感分析、NER 等

一、说明 我们见证了 BERT 等预训练模型在情感分析方面的强大功能,使我们能够破译隐藏在文本数据中的情感。通过 SpaCy,我们探索了命名实体识别的迷人世界,揭开了隐藏在非结构化文本中的秘密。 二、问题陈述 命名实体识别(NER)是自然语言处理中的一项关键…

数字化时代的政务服务:构建便捷高效的线上政务大厅

引言&#xff1a; 随着数字化时代的来临&#xff0c;如何通过线上政务大厅搭建一个便捷高效的服务平台&#xff0c;以更好地满足公众需求值得探究。线上政务大厅是政务服务的新方式&#xff0c;但搭建线上政务大厅并不是一件容易的事情&#xff0c;需要精心的规划和设计。 一…

【蓝桥杯选拔赛真题25】C++两个数比大小 第十三届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析

目录 C/C++两个数比大小 一、题目要求 1、编程实现 2、输入输出 二、算法分析

centos无法进入系统之原因解决办法集合

前言 可爱的小伙伴们&#xff0c;由于精力有限&#xff0c;暂时整理了两类。如果没有你遇到的问题也没有关系&#xff0c;欢迎底下留言评论或私信&#xff0c;小编看到后第一时间帮助解决 一. Centos 7 LVM xfs文件系统修复 情况1&#xff1a; [sda] Assuming drive cache:…