QT聊天项目DAY14
1. 客户端登录
1.1 初始化玩家头像
将头像的大小固定在250 * 250
void InitHeadImage(); // 初始化头像/* 初始化头像 */
void LoginWidget::InitHeadImage()
{// 加载头像QPixmap OriginalPixmap(":/Chat/Images/head_5.jpg");OriginalPixmap = OriginalPixmap.scaled(ui.Head_Label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);// 绘制圆形头像QPixmap RoundPixmap(ui.Head_Label->size());RoundPixmap.fill(Qt::transparent); // 用透明色填充QPainter painter(&RoundPixmap);painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿painter.setRenderHint(QPainter::SmoothPixmapTransform); // 平滑缩放// 使用QPainterPath设置圆角QPainterPath path;path.addRoundedRect(0, 0, ui.Head_Label->width(), ui.Head_Label->height(), 10, 10);painter.setClipPath(path);// 将原始图片绘制到圆形头像上painter.drawPixmap(0, 0, OriginalPixmap);// 设置头像ui.Head_Label->setPixmap(RoundPixmap);
}
1.2 登录界面新增err_Tip
设置成水平居中,并且最大最小高度为25
添加文本刷新Function
void ShowTipLabel(const QString& tip, const QString& State); // 显示提示信息
void AddTipErr(TipErr err, const QString& tips); // 添加错误提示
void DelTipErr(TipErr err); // 清除错误提示QMap<TipErr, QString> _TipErrs; // 错误提示记录
#include "Global.h"
ui.Tip_Label->clear();/* 刷新文本提示标签的样式 */
void LoginWidget::ShowTipLabel(const QString& tip, const QString& State)
{ui.Tip_Label->setText(tip);ui.Tip_Label->setProperty("state", State);repolish(ui.Tip_Label);
}/* 添加错误提示 */
void LoginWidget::AddTipErr(TipErr err, const QString& tips)
{_TipErrs[err] = tips;ShowTipLabel(tips, "error");
}/* 删除错误提示 */
void LoginWidget::DelTipErr(TipErr err)
{_TipErrs.remove(err);if (_TipErrs.isEmpty()){ui.Tip_Label->clear();return;}ShowTipLabel(_TipErrs.first(), "error");
}
1.3 添加控制密码是否可见的标签
添加标签控件,将该标签提升为clickedLabel,重定义名称为PassWord_Visible并设置固定大小为20 * 20;
为标签设置样式
/* 初始化可视化控件 */
ui.PassWord_Visible->SetState("unvisible", "unvisible_hover", "", "visible","visible_hover", "");/* 密码可见性 */
connect(ui.PassWord_Visible, &ClickedLabel::clicked, this, [this](){auto state = ui.PassWord_Visible->GetState();if (state == ClickLabelState::Normal){ui.PassWord_Edit->setEchoMode(QLineEdit::Password);}else if (state == ClickLabelState::Selected){ui.PassWord_Edit->setEchoMode(QLineEdit::Normal);}});
1.4 登陆验证
点击登录需要发送http请求到GateServer,GateServer先验证登录密码,在调用grpc请求StatusServer,获取聊天服务器ip信息和token信息反馈给客户端
1.4.1 添加登录按钮的槽函数
1. 检查用户名输入以及密码输入是否有问题
bool CheckUserValid(); // 检查用户名是否合法
bool CheckPasswordValid(); // 检查密码是否合法
/* 检查用户名是否合法 */
bool LoginWidget::CheckUserValid()
{if (ui.User_Edit->text().isEmpty()){AddTipErr(TipErr::TIP_USER_ERR, QString::fromLocal8Bit("用户名不能为空"));return false;}/* 一切正常则删除错误提示 */DelTipErr(TipErr::TIP_USER_ERR);return true;
}/* 检验密码是否合法 */
bool LoginWidget::CheckPasswordValid()
{QString passText = ui.PassWord_Edit->text();if (passText.length() < 6 || passText.length() > 15){AddTipErr(TipErr::TIP_PWD_ERR, QString::fromLocal8Bit("密码长度必须在6-15位之间"));return false;}/* 密码长度至少6位 可以是字母、数字、特定的特殊字符 */QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*]{6,15}$");bool match = regExp.match(passText).hasMatch();if (!match){AddTipErr(TipErr::TIP_PWD_ERR, QString::fromLocal8Bit("不能包含非法字符"));return false;}/* 一切正常则删除错误提示 */DelTipErr(TipErr::TIP_PWD_ERR);return true;
}
2. 实现槽函数逻辑
enum ReqID
{ID_GET_VARIFY_CODE = 1001, // 获取验证码ID_REG_USER = 1002, // 注册用户ID_RESET_PWD = 1003, // 重置密码ID_LOGIN_USER = 1004, // 登录用户
};enum Modules
{REGISTERMOD = 0, // 注册模块LOGINMOD = 1, // 登录模块
};[GateServer]
host=localhost
port=8080
getVerifycode=getVarifycode
RegisterUser=RegisterUser
ResetUserPassword=ResetUserPassword
LoginUser=LoginUser/* 登录按钮点击时 */
void LoginWidget::OnLoginButtonClicked()
{if (!CheckUserValid())return;if (!CheckPasswordValid())return;QString user = ui.User_Edit->text();QString pass = ui.PassWord_Edit->text();// 发送http请求QJsonObject json;json["user"] = user;json["password"] = xorString(pass);// 创建URLQString urlStr = "http://" +ConfigSettings->value("GateServer/host").toString() + ":"+ ConfigSettings->value("GateServer/port").toString() + "//"+ ConfigSettings->value("GateServer/LoginUser").toString();QUrl url(urlStr);HttpManager::Instance()->PostHttpReq(url, json, ReqID::ID_LOGIN_USER, Modules::LOGINMOD);
}
1.4.2 处理客户端发来的响应
1. 添加对应ReqId的回调
Struct.h
#ifndef STRUCT_H
#define STRUCT_H#include <QString>/* 服务器信息 */
struct ServerInfo {QString Host;QString Port;QString Token;int Uid;
};#endif // STRUCT_H
void sig_connect_tcp(ServerInfo serverInfo); // 连接聊天服务器void InitHttpHandlers(); // 设置网络回包的回调函数QMap<ReqID, std::function<void(const QJsonObject&)>> _handlers; // 不同类型的回调函数/* 网络回包的处理函数 */
void LoginWidget::InitHttpHandlers()
{// 注册获取验证码回包的逻辑_handlers.insert(ReqID::ID_LOGIN_USER, [this](const QJsonObject& jsonObj){int error = jsonObj["error"].toInt();if (error != ErrorCodes::SUCCESS){ShowTipLabel(QString::fromLocal8Bit("参数错误"), "error");return;}auto email = jsonObj["email"].toString();// 发送信号通知TcpMgr发送长链接ServerInfo serverInfo;serverInfo.Uid = jsonObj["uid"].toInt();serverInfo.Host = jsonObj["host"].toString();serverInfo.Port = jsonObj["port"].toInt();serverInfo.Token = jsonObj["token"].toString();_Uid = serverInfo.Uid;_Token = serverInfo.Token;emit sig_connect_tcp(serverInfo);ShowTipLabel(QString::fromLocal8Bit("登陆成功"), "normal");qDebug() << QString::fromLocal8Bit("登陆成功 user: ") << email;});
}
2. 实现处理服务器响应的槽函数
/* 服务器处理完登录请求回复的响应 */
void LoginWidget::slot_login_mod_finished(ReqID reqId, QString res, ErrorCodes errCode)
{if (errCode != ErrorCodes::SUCCESS) {ShowTipLabel(QString::fromLocal8Bit("网络请求错误"), "error");return;}QJsonDocument jsonDoc = QJsonDocument::fromJson(res.toUtf8()); // .json文件if (jsonDoc.isNull()){ShowTipLabel(QString::fromLocal8Bit("json 是空的"), "error");return;}// 解析json数据if (!jsonDoc.isObject()){ShowTipLabel(QString::fromLocal8Bit("json 格式不正确"), "error");return;}// 回调函数_handlers[reqId](jsonDoc.object());
}
客户端登录请求发送的模块封装完毕
2. 服务器处理登录请求
2.1 使用RAII思想来归还池式组件的连接
// RAII 归还连接
class ConnectionRAII
{
public:ConnectionRAII(function<void()> RetunConnection): m_RetunConnection(RetunConnection){}~ConnectionRAII(){m_RetunConnection();}private:function<void()> m_RetunConnection;
};
2.2 重新定义GRPC服务并编译
message.proto
syntax = "proto3";package message;service VerifyService {rpc GetVerifyCode (GetVerifyRequest) returns (GetVerifyRsponse) {}
}message GetVerifyRequest {string email = 1;
}message GetVerifyRsponse {int32 error = 1;string email = 2;string code = 3;
}message GetChatServerRequest {int32 uid = 1;
}message GetChatServerResponse {int32 error = 1;string host = 2;string port = 3;string token = 4;
}message LoginRequest {int32 uid = 1;string token = 2;
}message LoginResponse {int32 error = 1;int32 uid = 2;string token = 3;
}service StatusService {rpc GetChatServer (GetChatServerRequest) returns (GetChatServerResponse) {}rpc Login (LoginRequest) returns (LoginResponse) {}
}
编译生成新的通信文件
H:\BoostNetLib\grpc\visualpro\third_party\protobuf\Debug\protoc.exe -I="." --grpc_out="." --plugin=protoc-gen-grpc="H:\BoostNetLib\grpc\visualpro\Debug\grpc_cpp_plugin.exe" "message.proto"
编译生成新的序列化和反序列化文件
H:\BoostNetLib\grpc\visualpro\third_party\protobuf\Debug\protoc.exe --cpp_out=. "message.proto"
2.3 创建StatusGrpcClient
#ifndef STATUSGRPCCLIENT_H
#define STATUSGRPCCLIENT_H
#include "Singletion.h"
#include "GlobalHead.h"
#include <grpcpp/grpcpp.h>
#include "message.grpc.pb.h"using grpc::Channel;
using grpc::Status;
using grpc::ClientContext;using message::GetChatServerRequest;
using message::GetChatServerResponse;
using message::StatusService;class StatusConPool
{
public:StatusConPool(int _PoolSize, string IP):PoolSize(_PoolSize), bStop(false){for (int i = 0; i < PoolSize; i++){StatusService::Stub* stub = new StatusService::Stub(grpc::CreateChannel(IP, grpc::InsecureChannelCredentials()));conPool.push(stub);}}~StatusConPool() {lock_guard<mutex> lock(mtx);bStop = true;cv.notify_all();for (int i = 0; i < PoolSize; i++){delete conPool.front();conPool.pop();}}StatusService::Stub* GetCon(){unique_lock<mutex> lock(mtx);cv.wait(lock, [this]() {return !conPool.empty() || bStop; });if(bStop)return nullptr;StatusService::Stub* stub = conPool.front();conPool.pop();return stub;}void ReturnCon(StatusService::Stub* _con){lock_guard<mutex> lock(mtx);if(bStop)return;conPool.push(_con);cv.notify_one();}private:int PoolSize;/* 锁相关 */atomic<bool> bStop;mutex mtx;condition_variable cv;/* 连接池 */queue<StatusService::Stub*> conPool;
};class StatusGrpcClient : public Singletion<StatusGrpcClient>
{friend class Singletion<StatusGrpcClient>;
public:~StatusGrpcClient() {}GetChatServerResponse GetChatServer(int uid);private:StatusGrpcClient();private:StatusConPool* conPool = nullptr;
};#endif // STATUSGRPCCLIENT_H
#include "StatusGrpcClient.h"
#include "ServerStatic.h"StatusGrpcClient::StatusGrpcClient()
{int Port = get<int>(ServerStatic::ParseConfig("StatusServer", "Port"));string Ip = "localhost:" + to_string(Port);conPool = new StatusConPool(5, Ip);
}GetChatServerResponse StatusGrpcClient::GetChatServer(int uid)
{/* 向GRPC服务端发送请求,获取聊天服务器信息 */ClientContext context;GetChatServerResponse response;GetChatServerRequest request;request.set_uid(uid);auto stub = conPool->GetCon();Status status = stub->GetChatServer(&context, request, &response);ConnectionRAII ConRAII([this,&stub](){conPool->ReturnCon(stub);});if (!status.ok())response.set_error(ErrorCodes::RPC_FAILED);return response;
}
修改Config.json
{"GateServer": {"Port": 8080},"VerifyServer": {"Port": 50051},"StatusServer": {"Port" : 50052},"Redis": {"Host": "127.0.0.1","Port": 6380,"Password": "123456"},"Mysql": {"Host": "127.0.0.1","Port": 3306,"Username": "root","Password": "123456","Database": "YjjChat"}
}
2.4 处理登陆请求
/* 用户登录 */
RegisterPost("/LoginUser", [](HttpConnection* connection){if (connection){auto bodyStr = boost::beast::buffers_to_string(connection->_request.body().data()); // 获取 Http请求体中的内容cout << "receive body is \n" << bodyStr << endl;connection->_response.set(http::field::content_type, "text/json"); // 设置 Http响应头中的 content-typeJson::Value jsonResonse; // 响应用的JsonJson::Value jsonResult; // 请求体解析出来的JsonJson::Reader reader; // Json解析器bool parseSuccess = reader.parse(bodyStr, jsonResult); // 将请求体解析为Jsonif (!parseSuccess){cout << "parse json failed" << endl;jsonResonse["error"] = ErrorCodes::ERROR_JSON; // 设置响应的错误码string jsonStr = jsonResonse.toStyledString();beast::ostream(connection->_response.body()) << jsonStr; // 向 Http响应体中写入错误码内容return;}UserInfo userInfo;/* 访问Mysql检查密码是否匹配 */bool bUpdatePassword = MySqlManage::GetInstance()->CheckPassword(jsonResult["user"].asString(), jsonResult["password"].asString(), userInfo);if (!bUpdatePassword){cout << "update password failed\n";jsonResonse["error"] = ErrorCodes::Update_Password_Failed;string jsonStr = jsonResonse.toStyledString();beast::ostream(connection->_response.body()) << jsonStr;return;}/* 查询StatusServer匹配对应的服务器 */GetChatServerResponse response = StatusGrpcClient::GetInstance()->GetChatServer(userInfo.uid);if (response.error()){cout << "grpc get chat server failed: error is " << response.error() << endl;jsonResonse["error"] = response.error();string jsonStr = jsonResonse.toStyledString();beast::ostream(connection->_response.body()) << jsonStr;return;}/* 返回响应报文给客户端 */cout << "succeed to load userinfo uid is " << userInfo.uid << endl;jsonResonse["error"] = 0;jsonResonse["user"] = jsonResult["user"];jsonResonse["password"] = jsonResult["password"];string jsonStr = jsonResonse.toStyledString();beast::ostream(connection->_response.body()) << jsonStr; // 向 Http响应体中写入Json内容return;}else{std::cout << "connection is null" << std::endl;}});
3. 创建状态服务器
3.1 创建属性页
视图->其他窗口->属性管理器 之前的项目怎么配置的现在怎么配置就行了
将pdb文件添加到静态库文件夹下
此时还是有,这是因为原本的redis库中Win32库与别的库冲突,重新修改了一份redis
3.2 填充服务器
3.2.1. 将这些文件全都添加到项目中
3.2.2. 创建新的StatusServiceImpl类
#ifndef STATUS_SERVICE_IMPL_H
#define STATUS_SERVICE_IMPL_H
#include <string>
#include <grpcpp/grpcpp.h>
#include "message.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using message::GetChatServerRequest;
using message::GetChatServerResponse;
using message::StatusService;
using namespace std;struct ChatServer
{string Host;int Port;
};class StatusServiceImpl final : public StatusService::Service
{
public:StatusServiceImpl();Status GetChatServer(ServerContext* context, const GetChatServerRequest* request,GetChatServerResponse* response) override;private:string generate_unique_string();public:std::vector<ChatServer> _servers;int ServerIndex = 0;
};
#endif // STATUS_SERVICE_IMPL_H
#include "StatusServiceImpl.h"#include "ServerStatic.h"
#include <boost/beast/http.hpp>
#include <boost/beast.hpp>
#include <boost/asio.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>StatusServiceImpl::StatusServiceImpl():ServerIndex(0)
{ChatServer server1;string Host1 = get<string>(ServerStatic::ParseConfig("ChatServer1", "Host"));int Port1 = get<int>(ServerStatic::ParseConfig("ChatServer1", "Port"));server1.Host = Host1;server1.Port = Port1;ChatServer server2;string Host2 = get<string>(ServerStatic::ParseConfig("ChatServer2", "Host"));int Port2 = get<int>(ServerStatic::ParseConfig("ChatServer2", "Port"));server2.Host = Host2;server2.Port = Port2;_servers.push_back(server1);_servers.push_back(server2);
}Status StatusServiceImpl::GetChatServer(ServerContext* context, const GetChatServerRequest* request, GetChatServerResponse* response)
{ServerIndex = (ServerIndex + 1) % _servers.size();ChatServer server = _servers[ServerIndex];response->set_host(server.Host);response->set_port(to_string(server.Port));response->set_error(ErrorCodes::SUCCESS);string token = generate_unique_string();response->set_token(token);return Status::OK;
}string StatusServiceImpl::generate_unique_string()
{// 创建UUID对象boost::uuids::uuid uuid = boost::uuids::random_generator()();// 将UUID转换为字符串std::string unique_string = to_string(uuid);return unique_string;
}
4. C++中线程的使用方法
4.1 线程创建
#include <iostream>
#include <thread>
using namespace std;void Function()
{std::cout << "This is a thread function.\n";
}class HelloFunction
{
public:void operator()(){std::cout << "Hello, world!\n";}
};int main()
{//1. 普通函数thread t1(Function);t1.join();// 2.函数对象HelloFunction hello;thread t2(hello);t2.join();// 3.lambda表达式thread t3([]() {std::cout << "Hello, lambda!\n";});t3.join();return 0;
}
4.2 等待线程完成
使用join()成员函数来等待线程完成。如果不等待,则线程可能在主线程结束后仍然运行,导致未定义行为(除非将线程分离)
4.3 分离线程
使用detach()成员函数将线程与thread对象分离,这样线程将在后台独立运行,不再收到thread对象的控制;
4.4 传递参数
线程函数可以接受参数。参数默认以值传递方式传递,如果需要传递引用必须使用ref进行包装
#include <iostream>
#include <thread>
using namespace std;void Function(int a)
{a++;std::cout << "a = " << a << "\n";
}void RefFunction(int& a, int b)
{a += b;std::cout << "a = " << a << "\n";
}int main()
{// 1.值传递int a = 10;thread t1(Function, 10);t1.join();cout << "a = " << a << "\n";// 2.引用传递thread t2(RefFunction, std::ref(a), 5);t2.join();cout << "a = " << a << "\n";return 0;
}
5. 测试
5.1 逻辑梳理
1. 客户端登录
登录按钮点击时,发送Post请求,等待服务器的响应报文
2. 服务器监听客户端发来的Http
只关注Post请求,
处理登录请求时,先拆解出用户发来的用户名和密码,将用户信息(用户名,邮件,密码,uid)读取出来,利用用户的uid向StatusServer发送请求
3. StatusServer处理请求
监听端口号并添加服务(客户端发来对应请求的回调函数)
再创建一个事件循环对象来监听Crtl + C用来优雅退出,再后台线程中进行监听
服务(返回聊天服务器的IP地址和端口号)
登陆成功
添加打印日志查看StatusServer是否监听到发来的请求
测试成功!!!
6. Git管理
在项目中建立分支将所有的项目通过分支的形式去提交,不提交Master
拉取分支,创建空项目,复制URL,按照下面操作就能得到想要的分支的项目了
相关文章:

QT聊天项目DAY14
1. 客户端登录 1.1 初始化玩家头像 将头像的大小固定在250 * 250 void InitHeadImage(); // 初始化头像/* 初始化头像 */ void LoginWidget::InitHeadImage() {// 加载头像QPixmap OriginalPixmap(":/Chat/Images/head_5.jpg");OriginalPixmap …...

架构设计技巧——架构设计模板
一份实用、高效、覆盖核心要素的架构设计模板是确保设计质量、促进团队沟通和指导实施的关键。以下是一个经过提炼的架构设计文档核心模板框架,结合了业界最佳实践,并强调灵活裁剪: 架构设计文档模板 (核心框架) 文档标识 项目/系统名称&a…...
交易系统开发:跨境资本的高速通道架构解密
连接纽约、香港与内陆的金融管道工程 总收益互换(TRS)在港美股投资中扮演着跨境资本流动的“隐形桥梁”。本文基于真实跨境券商系统开发实践,深入解析支持多市场、多币种、多通道的TRS平台架构设计与业务解决方案。 一、港美股TRS的核心价值&…...

【Ragflow】27.RagflowPlus(v0.4.1):小版本迭代,问题修复与功能优化
概述 RagflowPlus v0.4.0 在发布后,收到了积极的反馈,同时也包含一些问题。 本次进行一轮小版本更新,发布 v0.4.1 版本,对已知问题进行修复,并对部分功能进行进一步优化。 开源地址:https://github.com/…...
易语言是什么?易语言能做什么?
易语言(EPL)是什么? 易语言(Easy Programming Language,简称EPL)是一款面向中文用户的编程语言,由中国人吴涛于2000年开发,专为降低编程门槛设计。其核心特点是…...

【Oracle】数据仓库
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 数据仓库概述1.1 为什么需要数据仓库1.2 Oracle数据仓库架构1.3 Oracle数据仓库关键技术 2. 数据仓库建模2.1 维度建模基础2.2 星形模式设计2.3 雪花模式设计2.4 缓慢变化维度(SCD)处…...

基于开源AI大模型AI智能名片S2B2C商城小程序源码的中等平台型社交电商运营模式研究
摘要:本文聚焦中等平台型社交电商,探讨其与传统微商及大型社交电商平台的差异,尤其关注产品品类管理对代理运营的影响。通过引入开源AI大模型、AI智能名片与S2B2C商城小程序源码技术,构建智能化运营体系。研究结果表明,…...
typeof运算符 +unll和undefined的区别
typeof运算符 JavaScript 有三种方法,可以确定一个值到底是什么类型。而我们 现在需要接触到的就是typeof 数值返回number 1 typeof 123 // "number" 字符串返回string 1 typeof 123 // "string" 布尔值返回boolean 1 typeof fal…...

Vite 双引擎架构 —— Esbuild 概念篇
Vite 底层采用 双引擎架构,核心构建引擎是 Esbuild 和 Rollup,二者在开发和生产环境中分工协作,共同实现高性能构建。不可否认,作为 Vite 的双引擎之一,Esbuild 在很多关键的构建阶段(如依赖预编译、TS 语法转译、代码…...
Life:Internship finding
1. 前言 fishwheel writes this Blog to 记录自分自身在研二下找实习的经历。When 写这篇 Blog 的时候我的最后一搏也挂掉了,只能启用保底方案了。When I 打开我的邮箱时,发现里面有 nearly 100 多封与之相关的邮件,顿时感到有些心凉&#x…...

阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】
个人记录 进入控制台,找到定时与自动化任务 进入‘安装/卸载扩展程序’ 点击‘安装扩展程序’ 选择docker社区版,点击下一步与确定,等待一会 安装成功 查询版本 查询docker sudo docker version查询docker compose sudo docker compo…...
GitHub 趋势日报 (2025年06月07日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 603 netbird 459 dify 440 cognee 352 omni-tools 337 note-gen 239 ragbits 237 …...
Java编程之组合模式
引言 在软件开发的世界里,我们经常会遇到需要表示"部分-整体"层次结构的场景。比如文件系统中的文件和文件夹、图形界面中的各种组件、企业组织架构中的部门和员工等。这些场景都有一个共同的特点:我们需要以一种统一的方式来处理单个对象和由…...
Oracle 19c RAC集群ADG搭建
1、将主库的pfile和passwdfile发送到备库 #主库一节点操作 scp -P1234 /tmp/pfile2025.ora bak_ip:/home/oracle sco -P1234 /oracle/app/oracle/product/19.0.0/db/dbs/orapw$ORACLE_SID bak_ip:/oracle/app/oracle/product/19.0.0/db/dbs 2、备库修改参数文件成standby相关…...

ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题
ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题 --蓝牙电话SDK自动部署 上一篇:手机App-插入USB时自动授权点击确定按钮-使系统弹出框自动消失 下一篇:编写中。 一、前言 我们在上一篇《手机App-插入USB时自动授权点击确定按钮-使系统弹出框…...
Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost+同一特征值多样性)
Predicting Optimal Fertilizers 题意: 给出土壤的特性,预测出3种最佳的肥料 数据处理: 1.有数字型和类别型,类别不能随意换成数字,独热编码。cat可以直接处理category类型。 2.构造一些相关土壤特性特征 3.由于la…...

uniapp+<script setup lang=“ts“>解决有数据与暂无数据切换显示,有数据加载时暂无数据闪现(先加载空数据)问题
声明showEmpty 为false,在接口返回处判断有数据时设置showEmpty 为false,接口返回数据为空则判断showEmpty 为true (这样就解决有数据的时候会闪现暂无数据的问题啦) <!--* Date: 2024-02-26 03:38:52* LastEditTime: 2025-06…...

详解鸿蒙Next仓颉开发语言中的动画
大家上午好,今天来聊一聊仓颉开发语言中的动画开发。 仓颉中的动画通常有两种方式,分别是属性动画和显示动画,我们今天以下面的加载动画为例,使用显示动画和属性动画分别实现一下,看看他们有什么区别。 显示动画 显示…...

Redis常见使用场景解析
1. 数据库缓存 Redis 作为典型的 Key-Value 型内存数据库,数据缓存是其最广为人知的应用场景。使用 Redis 缓存数据操作简便,通常将序列化后的对象以 string 类型存储。但在实际应用中,需注意以下关键要点: Key 设计:必须确保不同对象的 Key 具有唯一性,且尽量缩短长度,…...
C语言指针与数组sizeof运算深度解析:从笔试题到内存原理
前两天跟着数组指针的教程: // #self 视频里的笔试题 !!!vipint b12[3][4] {0};printf("%ld \n", sizeof(b12[0]));printf("%ld \n", sizeof(*b12));printf("%ld \n", sizeof(*(b12 1)));printf("%ld \n", sizeof(*(&am…...

起重机指挥人员在工作中需要注意哪些安全事项?
起重机指挥人员在作业中承担着协调设备运行、保障作业安全的关键职责,其安全操作直接关系到整个起重作业的安全性。以下从作业前、作业中、作业后的全流程,详细说明指挥人员需注意的安全事项: 一、作业前的安全准备 资质与状态检查ÿ…...
JVM内存区域与溢出异常详解
当然可以。以下是结合了程序计数器和Java内存区域以及内存溢出异常的详细解释: JVM内存区域与内存溢出异常 Java虚拟机(JVM)管理着不同类型的内存区域,每个区域都有其特定的功能和可能导致的内存溢出异常。 程序计数器ÿ…...
ES海量数据更新及导入导出备份
一、根据查询条件更新字段 from elasticsearch import Elasticsearch import redis import json# 替换下面的用户名、密码和Elasticsearch服务器地址 username elastic password password es_host https://127.0.0.2:30674# 使用Elasticsearch实例化时传递用户名和密码 es…...
Java线程池核心原理与最佳实践
Java 线程池详解 线程池是Java并发编程的核心组件,它能高效管理线程生命周期,避免频繁创建销毁线程的开销,提升系统性能和资源利用率。 一、线程池核心优势 降低资源消耗:复用已创建的线程,减少线程创建销毁开销提高…...

JAVA-springboot log日志
SpringBoot从入门到精通-第8章 日志的操作 一、Spring Boot默认的日志框架 SpringBoot支持很多种日志框架,通常情况下,这些日志框架都是由一个日志抽象层和一个日志实现层搭建而成的,日志抽象层是为记录日志提供的一套标准且规范的框架&…...

1.springmvc基础入门(一)
1.Spring MVC概念 Spring MVC 是 Spring Framework 提供的 Web 组件,全称是 Spring Web MVC,是⽬前主流的实现 MVC 设计模式的框架,提供前端路由映射、视图解析等功能。 Java Web 开发者必须要掌握的技术框架。 2.Spring MVC 功能 MVC&am…...
AI 时代下语音与视频伪造的网络安全危机
引言 在人工智能技术的推动下,语音合成、视频生成等技术取得了突破性进展,Deepfake、AI 语音克隆等工具让语音和视频伪造变得愈发简单且逼真。这些技术在娱乐、影视等领域带来便利的同时,也被不法分子利用,引发了一系列网络安全问…...

模块缝合-把A模块换成B模块(没写完)
把MLP Head替换为KAN 1.在model文件下新建一个python文件 2.把 模块文件里的整个KAN代码复制到新的python文件中 3.在开头导入 from model.KAN(新建文件名) import KAN(新建文件中的类名) 4.sys.path.append(r"D: Icode(Kansformer"…...

从零开始学Flink:揭开实时计算的神秘面纱
一、为什么需要Flink? 当你在电商平台秒杀商品时,1毫秒的延迟可能导致交易失败;当自动驾驶汽车遇到障碍物时,10毫秒的计算延迟可能酿成事故。这些场景揭示了一个残酷事实:数据的价值随时间呈指数级衰减。 传统批处理…...
一、ES6-let声明变量【解刨分析最详细】
一、块级作用域 { let Tim"Tim是靓仔!" } console.log("Tim:",Tim) 打印结果:Tim未进行任何定义! 原因:因为Tim定义再块级{}里面,它的声音Tim只服务于该块级里面。而打印结果是再块级外面&#…...