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的主要特点和概念:
- WebSocket协议支持: Spring Boot WebSocket支持WebSocket通信协议,允许双向的、实时的通信。WebSocket允许服务器主动向客户端推送数据,而不需要客户端发起请求。
- STOMP协议支持: 除了原始WebSocket,Spring Boot WebSocket还支持STOMP(Simple Text Oriented Messaging Protocol)协议。STOMP是一个基于文本的协议,它提供了更高级的消息传递功能,例如消息订阅、目标广播和认证等。
- 消息处理器: Spring Boot WebSocket允许你定义消息处理器,用于处理WebSocket消息。你可以编写处理器来处理接收到的消息,并决定如何响应。
- 消息代理: Spring Boot WebSocket支持消息代理,你可以配置一个消息代理服务器(如RabbitMQ或ActiveMQ),用于处理WebSocket消息的分发和广播。这使得构建分布式和扩展的WebSocket应用程序更容易。
- 消息广播: Spring Boot WebSocket允许你将消息广播到多个订阅者。这对于实现群聊、广播通知和实时数据展示等功能非常有用。
- 安全性: Spring Boot WebSocket提供了与Spring Security集成的方式,可以轻松实现WebSocket连接的安全性和认证。
- SockJS支持: Spring Boot WebSocket还支持SockJS,这是一个JavaScript库,用于处理浏览器不支持WebSocket的情况下的降级处理,使得WebSocket通信在各种浏览器上都能正常工作
1.1 websocket最小化配置
步骤说明
- 后端通过@EnableWebSocket注解开启websocket功能
- 定义websocket的访问端点 (作用: 定义对外暴露websocket接口)
- 定义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的端点
- 定义stomp端点 WebSocketStompConfiguration
- 配置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
- WebSocket 是一种通信协议: WebSocket 是一种在Web浏览器和服务器之间提供双向通信的协议。它允许在客户端和服务器之间创建持久性的连接,以便在连接建立后实时地发送和接收消息。
- 原始的、低级的协议: WebSocket 是一种相对较低级的协议,它允许在两端之间直接发送原始的消息帧(frames)。这意味着你可以通过WebSocket发送任意的二进制或文本数据。
- 需要自行处理消息格式和路由逻辑: WebSocket 本身并没有规定消息的格式或路由逻辑。在WebSocket上发送的消息可以是任意格式的数据,你需要自行定义消息的结构和处理逻辑。
- STOMP
- STOMP 是一种消息协议: STOMP 是一种基于文本的简单消息协议,它定义了客户端和消息代理(broker)之间如何进行交互的规范。STOMP 通常运行在WebSocket之上,它提供了一种在客户端和服务器之间进行实时消息通信的方式。
- 面向文本的消息格式: STOMP 消息是文本格式的,它使用类似于HTTP报文的格式来定义消息的头部和体。这种面向文本的格式使得它易于阅读和调试。
- 定义了消息的结构和路由逻辑: 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模块, 代码量很少。

相关文章:
SpringBoot_websocket实战
SpringBoot_websocket实战 前言1.websocket入门1.1 websocket最小化配置1.1.1 后端配置1.1.2 前端配置 1.2 websocket使用sockjs1.2.1 后端配置1.2.2 前端配置 1.3 websocket使用stomp协议1.3.1 后端配置1.3.2 前端配置 2.websocket进阶2.1 websocket与stomp有什么区别2.2 webs…...
香港科技大学广州|机器人与自主系统学域博士招生宣讲会—同济大学专场!!!(暨全额奖学金政策)
在机器人和自主系统领域实现全球卓越—机器人与自主系统学域 硬核科研实验室,浓厚创新产学研氛围! 教授亲临现场,面对面答疑解惑助攻申请! 一经录取,享全额奖学金1.5万/月! 🕙时间:…...
python基于GCN(图卷积神经网络模型)和LSTM(长短期记忆神经网络模型)开发构建污染物时间序列预测模型
在以往的时间序列预测建模中广泛使用的是回归类算法模型和RNN类的算法模型,相对来说技术栈会更稳定一些,最近有一个实际业务场景的需求,在建模的过程中要综合考虑其余点位的影响依赖,这时候我想到了之前做过的交通流量和速度预测相…...
SpringMVC问题
文章目录 SpringMVC运行流程MVC的概念与请求在MVC中的执行路径,ResponsBody注解的用途SpringMVC启动流程 SpringMVC运行流程 • 客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。 • DispatcherServlet 根据请求信息调用 …...
【Linux】Linux的常用基本指令
Linux常用基本指令 Linux指令的历史背景前言说明一、 ls 列出文件中的所有内容常用选项 二、pwd 显示当前所在目录进程三、cd 将当前工作目录改变到指定的目录下常用样例 四、touch 1. 更改文档或目录的日期时间 2. 新建一个不存在的文件常用选项 四、mkdir 1. 更改文档或目录的…...
气候变化和人类活动对中国植被固碳的贡献量化数据月度合成产品
简介: 气候变化和人类活动对中国植被固碳的贡献量化数据月度合成产品包括中国2001~2018年地表短波波段反照率、植被光合有效辐射吸收比、叶面积指数、森林覆盖度和非森林植被覆盖度、地表温度、地表净辐射、地表蒸散发、地上部分自养呼吸、地下部分自养呼吸、总初级…...
定位鼠标悬浮才出现的元素
第一步:按F12进入开发者模式 第二步:点击Sources. 第三步:鼠标进入,触发悬浮框弹出,然后鼠标停止不要移动。 第四步:按F8 或者(Ctrl\),正常情况下,此时页…...
【css/vue】使用css变量,在同一个页面根据不同情况改变字号等样式
解决方法是:将 css 的属性使用 v-bind 与 Vue 组件的属性绑定,当组件的属性变化时,css 对应的属性值也就会随之变化; 具体实现代码: <template><div><span class"navTitle">标题名</s…...
在springboot中实现WebSocket协议通信
前面介绍了使用netty实现websocket通信,有些时候,如果我们的服务并不复杂或者连接数并不高,单独搭建一个websocket服务端有些浪费资源,这时候我们就可以在web服务内提供简单的websocket连接支持。其实springboot已经支持了websock…...
云原生Docker系列 | Docker私有镜像仓库公有镜像仓库使用
云原生Docker系列 | Docker私有镜像仓库&公有镜像仓库使用 1. 使用公有云镜像仓库1.1. 阿里云镜像仓库1.2. 华为云镜像仓库1.3. 腾讯云镜像仓库2. 使用Docker Hub镜像仓库3. 使用Harbor构建私有镜像仓库4. 搭建本地Registry镜像仓库1. 使用公有云镜像仓库 1.1. 阿里云镜像…...
用于 syslog 收集的协议:TCP、UDP、RELP
系统日志是从 Linux/Unix 设备和其他网络设备(如交换机、路由器和防火墙)生成的日志 可以通过将 syslog 聚合到称为 syslog 服务器、syslog 守护程序或 syslogd 的服务器来集中 syslog。在TCP、UDP和RELP协议的帮助下,系统日志从设备传输到系…...
OpenAI创始人山姆·阿尔特曼重返公司;LLM持续学习
🦉 AI新闻 🚀 OpenAI创始人山姆阿尔特曼重返公司并与微软建立合作伙伴关系 摘要:OpenAI创始人山姆阿尔特曼回归OpenAI,担任首席执行官,并与微软建立牢固的合作伙伴关系。这解决了近期的争论,微软对OpenAI…...
Ant Design Pro生产环境部署
Ant Design Pro是通过URL路径前缀/api访问后端服务器,因此在nginx配置以下代理即可。 location / {index.html } location /api {proxy_pass: api.mydomain.com }...
Altium Designer学习笔记10
再次根据图纸进行布局走线: 这个MT2492 建议的布局走线。 那我这边应该是尽量按照该图进行布局: 其中我看到C1的电容的封装使用的是电感的封装,需要进行更换处理: 执行Validate Changes和Execute Changes操作,更新&a…...
ubuntu cutecom串口调试工具使用方法(图形界面)
文章目录 Ubuntu下使用CuteCom进行串口调试使用指南什么是CuteCom?主要特点 安装CuteCom使用APT包管理器从源码编译安装 配置串口CuteCom界面解析(启动cutecom)使用CuteCom进行数据发送和接收配置串口参数数据接收数据发送 高级功能和技巧流控…...
flink 1.17.1的pom.xml模板
flink 1.17.1的pom.xml模板 <?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.apa…...
MySql的数据类型和隐式转换
文章目录 一、数据类型1、数值类型1.1、整数类型1.2、浮点1.3、定点DECIMAL 2、时间类型2.1、日期和时间类型占用的存储空间2.2、日期和时间类型表示的范围2.3、日期和时间类型的零值表示 3、文本类型 二、隐式转换参考文章 一、数据类型 1、数值类型 1.1、整数类型 整数名称…...
【开源】基于JAVA的在线课程教学系统
项目编号: S 014 ,文末获取源码。 \color{red}{项目编号:S014,文末获取源码。} 项目编号:S014,文末获取源码。 目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2…...
【Linux】权限理解【文件权限以及目录权限详解、以及umsk程序掩码知识详解】
权限理解 一、Linux权限的概念二、su [用户名] : 切换用户三、Linux权限管理文件(一)文件访问者的分类(人)(二)文件类型和访问权限(事物属性)(1)第…...
Leetcode—1410.HTML实体解析器【中等】
2023每日刷题(三十八) Leetcode—1410.HTML实体解析器 算法思想 实现代码 typedef struct entityChar {char* entity;char rechar; }entity;entity matches[] {{""", "},{"'", \},{"&"…...
如何快速解密QQ音乐加密文件:qmcdump终极免费解决方案
如何快速解密QQ音乐加密文件:qmcdump终极免费解决方案 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 想要在…...
Real Anime Z多场景落地:游戏立绘、轻小说插画、虚拟UP主头像批量生成方案
Real Anime Z多场景落地:游戏立绘、轻小说插画、虚拟UP主头像批量生成方案 1. 工具介绍 Real Anime Z是一款基于阿里云通义Z-Image底座模型开发的高精度二次元图像生成工具。通过Real Anime Z专属微调权重,该工具专门针对真实系二次元风格进行了优化&a…...
DRIFT:基于用户不满信号的大语言模型优化方法
1. 项目背景与核心价值DRIFT项目提出了一种创新的大语言模型(LLM)偏好学习方法——通过主动捕捉用户交互中的不满信号(如负面反馈、修正指令、语气变化等)来优化模型表现。这种方法跳出了传统RLHF(基于人类反馈的强化学…...
中小企业ERP系统源代码开源扩展方案|模块化架构
温馨提示:文末有联系方式一、基础系统配置中心 统一管理企业数字化运营底层参数,保障权限、界面与操作行为的一致性与安全性。二、组织架构与权限体系 2.1 部门架构维护:支持多级部门树形结构创建、编辑与停用,适配集团化或扁平化…...
炉石传说macOS玩家的智能数据助手:HSTracker从入门到精通指南
炉石传说macOS玩家的智能数据助手:HSTracker从入门到精通指南 【免费下载链接】HSTracker A deck tracker and deck manager for Hearthstone on macOS 项目地址: https://gitcode.com/gh_mirrors/hs/HSTracker 想要在炉石传说对局中拥有透视对手牌库的能力吗…...
别再手动拼接数据了!用Kettle Spoon的JavaScript步骤5分钟搞定字段合并
5分钟掌握Kettle Spoon字段合并:JavaScript步骤实战指南 每天面对成百上千条需要拼接的字段数据,你是否还在用Excel公式或手写Python脚本?作为ETL工程师最基础却最高频的操作之一,字段合并的效率直接影响着数据预处理的速度。今天…...
MCP协议与mcp-use工具集:模块化配置管理的工程实践
1. 项目概述:一个“元”工具集的诞生在软件开发和系统运维的日常里,我们总会遇到一些“元”问题。比如,如何高效地管理不同项目、不同环境下的配置文件?如何让团队内部那些零散但极其有用的脚本、工具能被所有人方便地使用&#x…...
8大主流网盘直链解析工具:一键获取真实下载地址,告别限速烦恼
8大主流网盘直链解析工具:一键获取真实下载地址,告别限速烦恼 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中…...
合宙 LuatOS 开发避坑指南:智能售货机 APP 从调试到上架
本文将以智能售货机APP开发为例,详细拆解基于合宙Air8101引擎主机的完整开发流程,全程实操落地,帮助新手快速上手并实现专属嵌入式APP。 一、准备硬件环境 WIN10 以及 WIN10 以上的 Windows 操作系统电脑一台合宙引擎主机8101一块 type-c 接…...
告别会员!用Docker小雅+PotPlayer打造Windows本地4K影院(附Reex/VidHub多端配置)
打造Windows本地4K影院:Docker小雅与多端播放器配置指南 对于追求极致影音体验的用户来说,搭建一个私人影院系统早已不再是遥不可及的梦想。通过Docker小雅与精心挑选的播放器组合,你可以在家中任何角落享受4K甚至8K的高清内容,告…...
