当前位置: 首页 > article >正文

SpringBoot+Vue 中 WebSocket 的使用

        WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它使得客户端和服务器之间可以进行实时数据传输,打破了传统 HTTP 协议请求 - 响应模式的限制。

        下面我会展示在 SpringBoot + Vue 中,使用WebSocket进行前后端通信。

后端

1、引入 jar 包

<dependency><!-- 引入 websocket 库,该库提供了对 WebSocket 协议的支持--><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.14</version>
</dependency>
<dependency><!-- 引入 org.json 库,该库为 Java 提供了处理 JSON 数据的功能--><groupId>org.json</groupId><artifactId>json</artifactId><version>20090211</version>
</dependency>

2、WebSocket 配置类

package com.zecApi.config;import com.zecApi.config.zecInstantMessaging.ZecInstantMessagingWebSocketHandler;
import org.springframework.context.annotation.Bean;
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 org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;/*** WebSocketConfig 类是一个配置类,用于配置 Spring 框架的 WebSocket 功能。* 该类实现了 WebSocketConfigurer 接口,并重写了 registerWebSocketHandlers 方法,* 用于注册 WebSocket 处理器和配置相关的连接信息。*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {static {System.out.println("----------------------------------");System.out.println("------   WebSocket服务启动   -------");System.out.println("----------------------------------");}/*** 配置 WebSocket 容器的参数* @return ServletServerContainerFactoryBean 实例*/@Beanpublic ServletServerContainerFactoryBean createWebSocketContainer() {ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();// 设置最大文本消息缓冲区大小为 8192 字节container.setMaxTextMessageBufferSize(8192);// 设置最大二进制消息缓冲区大小为 8192 字节container.setMaxBinaryMessageBufferSize(8192);return container;}/*** 重写 WebSocketConfigurer 接口的 registerWebSocketHandlers 方法,* 该方法用于注册 WebSocket 处理器并配置连接的相关信息。** @param registry 用于注册 WebSocket 处理器的注册表对象*/@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 注册WebSocket处理器,并设置允许的来源registry.addHandler(zecInstantMessagingWebSocketHandler(), "/ZecInstantMessaging/ZecInstantMessagingWebSocketHandler/{account}").setAllowedOrigins("*"); // 允许所有来源,生产环境建议指定具体的域}/*** 定义一个名为 ZecInstantMessagingWebSocketHandler 的 Bean,该 Bean 是一个自定义的 WebSocket 处理器。* Spring 会将该 Bean 注入到应用程序中,以便在 WebSocket 连接时使用。** @return 返回一个 ZecInstantMessagingWebSocketHandler 实例*/@Beanpublic ZecInstantMessagingWebSocketHandler zecInstantMessagingWebSocketHandler() {return new ZecInstantMessagingWebSocketHandler();}}

3、WebSocket 处理器类 

package com.zecApi.config.zecInstantMessaging;import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;/*** 自定义的 WebSocket 处理器类,继承自 TextWebSocketHandler,用于处理 WebSocket 连接、消息收发和连接关闭等操作。*/
//@Component
@ServerEndpoint("/ZecInstantMessaging/ZecInstantMessagingWebSocketHandler/{account}")
public class ZecInstantMessagingWebSocketHandler extends TextWebSocketHandler {/*** 用于存储账号和 WebSocketSession 映射关系的并发哈希表。* 键为账号,值为对应的 WebSocketSession 对象,方便根据账号查找对应的会话。* 采用 ConcurrentHashMap 保证在多线程环境下的线程安全。*/private static final ConcurrentHashMap<String, WebSocketSession> sessionPool = new ConcurrentHashMap<>();/*** 用于存储所有 WebSocketSession 的并发列表。* 该列表用于存储所有当前活跃的 WebSocket 会话,方便进行广播等操作。* 采用 CopyOnWriteArrayList 保证在多线程环境下的线程安全。*/private static final CopyOnWriteArrayList<WebSocketSession> sessions = new CopyOnWriteArrayList<>();/*** 当与客户端的 WebSocket 连接建立成功后,此方法会被调用。** @param session 代表与客户端建立的 WebSocket 会话对象。*/@Overridepublic void afterConnectionEstablished(WebSocketSession session) {try {// 从 URI 中获取 account 参数String account = extractAccountFromSession(session);// 检查是否成功获取到账号信息if (account == null) {// 若未获取到账号信息,打印错误信息并关闭连接System.out.println("客户端连接失败,未获取到账号信息");session.close();return;}// 打印客户端连接成功信息,包含账号信息System.out.println("账号 " + account + " 已上线");// 将账号和对应的 WebSocketSession 存入 sessionPool 中sessionPool.put(account, session);// 将该 WebSocketSession 存入 sessions 列表中sessions.add(session);// 遍历 sessionPool 中的所有账号,打印在线账号信息for (String key : sessionPool.keySet()) {System.out.println("在线账号: " + key);}// 打印当前在线人数System.out.println("在线人数:" + sessionPool.size());} catch (IOException e) {// 处理关闭连接时可能出现的异常System.out.println("处理连接建立时出现 I/O 异常: " + e.getMessage());}}/*** 当接收到客户端发送的文本消息时,此方法会被调用。** @param session 代表与客户端建立的 WebSocket 会话对象。* @param message 客户端发送的文本消息对象。*/@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) {try {// 从接收到的 TextMessage 对象中提取消息的具体内容String payload = message.getPayload();// 打印接收到的消息内容,方便调试和监控System.out.println("收到客户端发来的消息: " + payload);// 解析 JSON 数据JSONObject jsonObject = new JSONObject(payload);// 提取消息 IDlong messageId = jsonObject.optLong("id", -1);if (messageId == -1) {System.out.println("未找到有效的消息 ID");}// 提取真正的消息内容StringBuilder content = new StringBuilder();for (int i = 0; ; i++) {String charStr = jsonObject.optString(String.valueOf(i));if (charStr.isEmpty()) {break;}content.append(charStr);}// 真正的信息String msg = content.toString();//把发来的信息按照 / 分成数组String[] splitMsg = msg.split("/");switch (splitMsg[0]){case  "chat":System.out.println("聊天来了");break;default:System.out.println("默认");}// 打印提取的消息内容System.out.println("提取的消息内容: " + msg);// 向发送消息的客户端回送一条确认消息,告知服务器已成功收到消息// 创建一个 JSONObject 对象JSONObject response = new JSONObject();// 向 JSONObject 中添加键值对,键为 "friendAccount",值为 "friendAccount"(这里的值用的是前端传回来的)response.put("friendAccount", splitMsg[2]);// 将 messageId 添加到响应中(因为前端在发送信息后会校验返回数据的id,从而结束监听计时器,如果没有 id,连接计时器不会停止,导致超时报错)response.put("id", messageId);// 将 JSONObject 转换为 JSON 格式的字符串String jsonString = response.toString();// 把信息发送给前端session.sendMessage(new TextMessage(jsonString));} catch (IOException e) {// 若在处理消息或发送确认消息过程中出现 I/O 异常,捕获该异常// 并打印错误信息,包含异常的具体描述,便于后续排查问题System.out.println("处理消息时出现异常: " + e.getMessage());} catch (JSONException e) {throw new RuntimeException(e);}}/*** 当与客户端的 WebSocket 连接关闭时,此方法会被调用。** @param session 代表与客户端建立的 WebSocket 会话对象。* @param status 表示连接关闭的状态信息。*/@Overridepublic void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) {// 从 WebSocketSession 的 URI 中提取账号信息String account = extractAccountFromSession(session);// 检查是否成功获取到账号信息if (account != null) {// 从 sessionPool 中移除该账号对应的 WebSocketSessionsessionPool.remove(account);// 从 sessions 列表中移除该 WebSocketSessionsessions.remove(session);// 打印客户端断开连接信息,包含账号信息和当前在线人数System.out.println("账号 " + account + " 已下线" );// 打印当前在线人数System.out.println("在线人数:" + sessionPool.size());}}/*** 从 WebSocketSession 的 URI 中提取账号信息。** @param session 代表与客户端建立的 WebSocket 会话对象。* @return 提取到的账号信息,如果未找到则返回 null。*/private String extractAccountFromSession(WebSocketSession session) {if (session.getUri() == null) {return null;}// 获取 WebSocketSession 的 URI 并转换为字符串String uri = session.getUri().toString();// 查找 URI 中最后一个斜杠的位置int index = uri.lastIndexOf("/");// 检查是否找到斜杠且斜杠后面还有字符if (index != -1 && index < uri.length() - 1) {// 提取斜杠后面的部分作为账号信息return uri.substring(index + 1);}// 若未找到合适的账号信息,返回 nullreturn null;}
}

前端

1、WebSocket 工具JS

        这个是用来连接 webSocket 的。

// 定义 WebSocket 实例变量,用于存储当前的 WebSocket 连接
let webSocket;
// 我这里本来是用 sessionStorage 来获取登录账号的,这边演示的话我就直接写死了。
// const account = getAccountBySessionStorage();
const account = "987654321";/*** WebSocket还有一个readyState属性,可以用来获取当前连接的状态。* readyState有四个可能的值:0(连接尚未建立)、1(连接已建立,可以通信)、2(连接正在关闭)、3(连接已关闭)*//*** 登录时连接webSocket* @param account* 这个是我这边登录后进行 websocket 连接,这里演示没用到,下面刷新也可以进行连接*/
// export function loginConnectWebSocket(account) {
//     if (account === null){
//         return;
//     }else {
//         if (!webSocket || webSocket.readyState === WebSocket.CLOSED){
//             return connectWebSocket(account);
//         }
//     }
// }/*** 监听页面刷新,重新进行 WebSocket 连接*/
window.onload = function() {console.log("刷新了");if (account === null){return;}else {if (!webSocket || webSocket.readyState === WebSocket.CLOSED){connectWebSocket(account);}}
};/*** 监听页面关闭事件,页面刷新前也会触发(页面刷新会自动断开websocket连接,这个暂时不需要)*/
// window.onbeforeunload = function (){
//     disconnectWebSocket();
// };/*** 获取当前的 WebSocket 实例* @returns {WebSocket|null} 当前的 WebSocket 实例或 null*/
export function getWebSocket() {return webSocket;
}/*** 主动断开 WebSocket 连接*/
export function disconnectWebSocket() {if (webSocket && webSocket.readyState !== WebSocket.CLOSED) {webSocket.close();webSocket = null;}
}/*** 封装一个连接 webSocket 的操作*/
export function connectWebSocket(account){return new Promise((resolve, reject) => {// 检查是否已经存在有效的 WebSocket 连接if (webSocket && webSocket.readyState === WebSocket.OPEN) {return resolve(webSocket);}// 如果存在连接但已经关闭,先断开if (webSocket && webSocket.readyState !== WebSocket.CLOSED) {// console.log("断开了");webSocket.close();}webSocket = new WebSocket(`ws://localhost:8088/ZecInstantMessaging/ZecInstantMessagingWebSocketHandler/${account}`);// 连接成功时的处理webSocket.onopen = function () {// console.log('WebSocket 连接已建立');resolve(webSocket);};// 连接错误时的处理webSocket.onerror = function (error) {// console.error('WebSocket 连接错误:', error);reject(error);};// 连接关闭时的处理webSocket.onclose = function () {// console.log('WebSocket 连接已关闭');};});
}

2、VUE 页面

<template><div style="width: 100%;height: 120px;"><div><textarea v-model="message" style="height: 50px;resize: none; width: 97%;font-family: 'Arial'; font-size: 14px;padding: 5px"></textarea></div><div><el-button style="margin-top: 5px;position: fixed; right: 12px;" @click="sendMessage">发送</el-button></div></div>
</template><script>
import {ref} from "vue";
import {sendMessageJS} from "@/module/zec-instant-messaging/api/MessagePage";export default {name: "DataScreen",setup(){let message = ref("");// 聊天页面记录的好友的账号(我这里单独写一个页面就直接写死账号了,主要用来演示 websocket,你们用的话可以替换成自己的)let friendAccount = ref("123456789");// 我的账号let myAccount = ref("987654321");// 发送消息const sendMessage = async () => {const msg = "chat" + "/" + myAccount.value + "/" + friendAccount.value + "/" + message.value + "/注释:标识、我的账号、好友的账号、信息";// 开始发送try {// 这里进行发送const response = await sendMessageJS(msg);// 如果发送成功,才会执行下面的语句console.log('信息发送成功,并接收到后端返回的信息:', response);console.log("id:"+response.id);console.log("friendAccount::"+response.friendAccount);// 执行后续代码} catch (error) {// 如果信息发送失败,就执行下面的语句console.error('信息发送失败:', error);}};return{sendMessage,message}}
}
</script><style scoped></style>

3、页面 JS

import {getWebSocket} from "@/common/webSocketUtil";// 发送信息的函数
export async function sendMessageJS(msg) {const webSocket = getWebSocket();return new Promise((resolve, reject) => {// 检查WebSocket连接状态if (webSocket.readyState !== WebSocket.OPEN) {reject(new Error('WebSocket 连接未打开!'));return;}// 生成唯一的消息IDconst messageId = Date.now();const message = { ...msg, id: messageId };// 设置超时时间const timeoutId = setTimeout(() => {reject(new Error('信息发送超时'));webSocket.removeEventListener('message', handleMessage);webSocket.removeEventListener('error', handleError);}, 5000); // 5秒超时// 定义处理消息响应的函数const handleMessage = (event) => {const response = JSON.parse(event.data);if (response.id === messageId) {clearTimeout(timeoutId);resolve(response);// 移除事件监听器webSocket.removeEventListener('message', handleMessage);webSocket.removeEventListener('error', handleError);}};// 定义处理错误的函数const handleError = (error) => {clearTimeout(timeoutId);reject(error);// 移除事件监听器webSocket.removeEventListener('message', handleMessage);webSocket.removeEventListener('error', handleError);};// 添加事件监听器webSocket.addEventListener('message', handleMessage);webSocket.addEventListener('error', handleError);// 发送消息webSocket.send(JSON.stringify(message));});
}

测试

后端打印

         这是后端接收到前端的信息。

 前端打印

        这是发送信息到后端,并接收后端返回来的数据。

代码具体功能我都写有注释,如果有问题可以联系我进行调整。

这是我单独拎出来写的,如果有问题可以联系我进行调整。

相关文章:

SpringBoot+Vue 中 WebSocket 的使用

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议&#xff0c;它使得客户端和服务器之间可以进行实时数据传输&#xff0c;打破了传统 HTTP 协议请求 - 响应模式的限制。 下面我会展示在 SpringBoot Vue 中&#xff0c;使用WebSocket进行前后端通信。 后端 1、引入 j…...

关于依赖注入框架VContainer DIIOC 的学习记录

文章目录 前言一、VContainer核心概念1.DI(Dependency Injection&#xff08;依赖注入&#xff09;)2.scope(域&#xff0c;作用域) 二、练习例子1.Hello,World!步骤一&#xff0c;编写一个底类。HelloWorldService步骤二&#xff0c;编写使用低类的类。GamePresenter步骤三&am…...

LRU缓存是什么

LRU缓存是什么 LRU(Least Recently Used)即最近最少使用,是一种缓存淘汰策略。在缓存空间有限的情况下,当新的数据需要存入缓存,而缓存已满时,LRU 策略会优先淘汰最近最少使用的数据,以此保证缓存中存储的是最近最常使用的数据。 LRU缓存的工作原理 LRU 缓存的核心思…...

Qt常用控件第一部分

1.控件概述 Widget 是 Qt 中的核⼼概念. 英⽂原义是 "⼩部件", 我们此处也把它翻译为 "控件" . 控件是构成⼀个图形化界⾯的基本要素. 像上述⽰例中的, 按钮, 列表视图, 树形视图, 单⾏输⼊框, 多⾏输⼊框, 滚动条, 下拉框等, 都可以称为 "控件"…...

docker存储卷及dockers容器源码部署httpd

1. COW机制 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。 如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件…...

JMeter接口自动化发包与示例

前言 JMeter接口自动化发包与示例 近期需要完成对于接口的测试,于是了解并简单做了个测试示例&#xff0c;看了看这款江湖上声名远播的强大的软件-Jmeter靠不靠谱。 官网&#xff1a;Apache JMeter - Apache JMeter™ 1简介 Apache-Jmeter是一个使用java语言编写且开源&…...

INFINI Console 极限控制台密码忘记了,如何重置?

在使用 INFINI Console&#xff08;极限控制台&#xff09;时&#xff0c;可能会遇到忘记密码的情况&#xff0c;这对于管理员来说是一个常见但棘手的问题。 本文将详细介绍如何处理 INFINI Console 密码忘记的情况&#xff0c;并提供两种可能的解决方案&#xff0c;帮助您快速…...

Python运算符的理解及简单运用

免责声明 如有异议请在评论区友好交流&#xff0c;或者私信 内容纯属个人见解&#xff0c;仅供学习参考 如若从事非法行业请勿食用 如有雷同纯属巧合 版权问题请直接联系本人进行删改 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 提示&#xff1a;以…...

汇编学习之《jcc指令》

JCC&#xff08;Jump on Condition Code&#xff09;指的是条件跳转指令&#xff0c;c中的就是if-else, while, for 等分支循环条件判断的逻辑。它包括很多指令集&#xff0c;各自都不太一样&#xff0c;接下来我尽量将每一个指令的c 源码和汇编代码结合起来看&#xff0c;加深…...

k8s的容器操作指令

几个命令目录 1、kubectl exec -n ithmp-prod -it <pod-name> /bin/bash命令组成部分使用场景注意事项 2、docker ps基本用法输出格式常用选项1. 列出所有容器&#xff08;包括已停止的&#xff09;2. 显示最近创建的容器3. 显示最近创建的几个容器4. 显示容器的详细信息…...

从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.3.3低代码开发:快速构建行业应用(电商推荐与金融风控案例)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 从零构建大语言模型全栈开发指南-第四部分:工程实践与部署4.3.3 低代码开发:快速构建行业应用(电商推荐与金融风控案例)1. 低代码与AI结合的核心价值2. 电商推荐系统案例2.1 技术架构与实现2.2 性能…...

基于vue框架的智能服务旅游管理系统54kd3(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,景点信息,门票预订,酒店客房,客房预订,旅游意向,推荐景点,景点分类 开题报告内容 基于Vue框架的智能服务旅游管理系统开题报告 一、研究背景与意义 1.1 行业现状与挑战 传统系统局限性&#xff1a;当前旅游管理系统普遍存在信息…...

用Python实现TCP代理

依旧是Python黑帽子这本书 先附上代码&#xff0c;我在原书代码上加了注释&#xff0c;更好理解 import sys import socket import threading#生成可打印字符映射 HEX_FILTER.join([(len(repr(chr(i)))3) and chr(i) or . for i in range(256)])#接收bytes或string类型的输入…...

MySQL的进阶语法7(索引-B+Tree 、Hash、聚集索引 、二级索引(回表查询)、索引的使用及设计原则

目录 一、索引概述 1.1 基本介绍 1.2 基本演示 1.3 特点及优势 二、索引结构 2.1 概述 2.2 二叉树 2.3 B-Tree 2.4 BTree 2.5 Hash 2.5.1 结构 2.5.2 特点 2.5.3 存储引擎支持 三、索引的分类 3.1 索引分类 3.2 聚集索引和二级索引 3.2.1 聚集索引和二级…...

【CSS3】04-标准流 + 浮动 + flex布局

本文介绍浮动与flex布局。 目录 1. 标准流 2. 浮动 2.1 基本使用 特点 脱标 2.2 清除浮动 2.2.1 额外标签法 2.2.2 单伪元素法 2.2.3 双伪元素法(推荐) 2.2.4 overflow(最简单) 3. flex布局 3.1 组成 3.2 主轴与侧轴对齐方式 3.2.1 主轴 3.2.2 侧轴 3.3 修改主…...

内网环境将nginx的http改完https访问

原文参考链接&#xff1a;https://www.cnblogs.com/leilcoding/p/16138778.html 编写生成证书的脚本 vim gen-ssl.sh #!/bin/sh # create self-signed server certificate: read -p "Enter your domain [www.example.com]: " DOMAIN echo "Create server key…...

使用 libevent 处理 TCP 粘包问题(基于 Content-Length 或双 \r\n)

在基于 libevent 的 TCP 服务器开发中,处理消息边界是常见需求。以下是两种主流分包方案的完整实现: 一、基于 Content-Length 的分包方案 1.1 数据结构设计 typedef struct {struct bufferevent *bev;int content_length; // 当前消息的预期长度int received_bytes; //…...

论坛系统的测试

项目背景 论坛系统采用前后端分离的方式来实现&#xff0c;同时使用数据库 来处理相关的数据&#xff0c;同时将其部署到服务器上。前端主要有7个页面组成&#xff1a;登录页&#xff0c;列表页&#xff0c;论坛详情页&#xff0c;编辑页&#xff0c;个人信息页&#xff0c;我…...

宠物店小程序怎么做?助力实体店实现营销突破

宠物店小程序怎么做&#xff1f;助力实体店实现营销突破 ——一个宠物店老板的“真香”实战分享 ​一、行业现状&#xff1a;线下宠物店的“流量焦虑”​ 作为开了3年宠物店的“铲屎官供应商”&#xff0c;这两年明显感觉生意难做了&#xff1a;某宝9.9包邮的狗粮、某团“满…...

《Mycat核心技术》第21章:高可用负载均衡集群的实现(HAProxy + Keepalived + Mycat)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…...

obsidian ios git同步

首先感谢几位博主的文章&#xff0c;我现在时间久了&#xff0c;未保存原文地址。以下是我自己的执行步骤总结。 应用商店安装 iSH 打开iSH&#xff0c;执行 apk update 安装下面软件&#xff0c;&#xff08;我觉得只安装第一个应该就行&#xff0c;下次测试&#xff09;。 …...

当 “原子” 遇上 “光腔”:量子计算的新舞台

在微观世界里&#xff0c;原子就像一个个会 “跳舞” 的小精灵&#xff0c;而科学家正试图用 “光的牢笼” 困住它们&#xff0c;让这些小精灵为量子计算 “打工”。最近&#xff0c;哈佛大学和 MIT 的研究团队在《科学》杂志上发表了一项突破性研究&#xff0c;他们让单个原子…...

移动端六大语言速记:第1部分 - 基础语法与控制结构

移动端六大语言速记&#xff1a;第1部分 - 基础语法与控制结构 本文将对比Java、Kotlin、Flutter(Dart)、Python、ArkTS和Swift这六种移动端开发语言的基础语法与控制结构&#xff0c;帮助开发者快速理解各语言间的差异与共性。 1. 基础语法 1.1 数据类型 各语言的基本数据…...

针对 SQL 查询中 IN 子句性能优化 以及 等值 JOIN 和不等值 JOIN 对比 的详细解决方案、代码示例及表格总结

以下是针对 SQL 查询中 IN 子句性能优化 以及 等值 JOIN 和不等值 JOIN 对比 的详细解决方案、代码示例及表格总结&#xff1a; 问题 1&#xff1a;IN 的候选值过多&#xff08;如超过 1000 个&#xff09; 问题描述 当 IN 列表中的值过多时&#xff0c;SQL 会逐个比较每个值…...

微信小程序唤起app

1、前提 1、app与小程序主体需一致&#xff0c;可以前往微信公众平台关联。 2、小程序的场景值为1069&#xff0c;也就是得从app打开小程序&#xff0c;小程序才能唤起app。 2、vue3代码示例 <template><view class"maxBox bgc"><button open-typ…...

深度学习Note.5(机器学习.6)

1.Runner类 一个任务应用机器学习方法流程&#xff1a; 数据集构建 模型构建 损失函数定义 优化器 模型训练 模型评价 模型预测 所以根据以上&#xff0c;我们把机器学习模型基本要素封装成一个Runner类&#xff08;加上模型保存、模型加载等功能。&#xff09; Runne…...

从零开始设计Transformer模型(1/2)——剥离RNN,保留Attention

声明&#xff1a; 本文基于哔站博主【Shusenwang】的视频课程【RNN模型及NLP应用】&#xff0c;结合自身的理解所作&#xff0c;旨在帮助大家了解学习NLP自然语言处理基础知识。配合着视频课程学习效果更佳。 材料来源&#xff1a;【Shusenwang】的视频课程【RNN模型及NLP应用…...

Uniapp 持续出现 Invalid Host/Origin header 解决方法

目录 前言1. 问题所示2. 原理分析前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 1. 问题所示 执行代码的时候,源源不断,一直持续出现这个 Invalid Host/Origin header [WDS]...

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的缓存技术:使用 Redis 提升性能

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…...

音视频 YUV格式详解

前言 本文介绍YUV色彩模型,YUV的分类和常见格式。 RGB色彩模型 在RGB颜色空间中,任意色光F都可以使用R、G、B三色不同的分量混合相加而成即: F = R + G + B.。即我们熟悉的三原色模型。 RGB色彩空间根据每个分量在计算机中占用的存储字节数可以分为以下几种类型,字节数…...