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

QT聊天项目DAY10

1.封装redis操作类

头文件

#ifndef REDISMANAGE_H
#define REDISMANAGE_H#include "Singletion.h"
#include "GlobalHead.h"class RedisManage : public Singletion<RedisManage>
{friend class Singletion<RedisManage>;
public:~RedisManage();bool Connect(const string& host, int port);											// 连接redisbool Get(const string& key, string& value);											// 获取valuebool Set(const string& key, const string& value);									// 设置valuebool Auth(const string& password);													// 验证密码bool LPush(const string& key, const string& value);									// 左侧pushbool LPop(const string& key, string& value);										// 左侧popbool RPush(const string& key, const string& value);									// 右侧pushbool RPop(const string& key, string& value);										// 右侧popbool Del(const string& key);														// 删除keybool ExitsKey(const string& key);													// 判断key是否存在void Close();																		// 关闭连接/* 将名为key的hash表中的field设置为Value */bool HSet(const string& key, const string& field, const string& value);				bool HSet(const char* key, const char* field, const char* value, size_t valuelen);/* 获取名为key的hash表中field对应的value */string HGet(const string& key, const string& field);					private:RedisManage();private:redisContext* _connect;																// redis连接redisReply* _reply;																	// redis响应对象
};
#endif // REDISMANAGE_H

实现文件

#include "RedisManage.h"RedisManage::~RedisManage()
{}RedisManage::RedisManage()
{}/* 连接redis */
bool RedisManage::Connect(const string& host, int port)
{_connect = redisConnect(host.c_str(), port);if (_connect == NULL || _connect->err){cout << "connect error " << _connect->errstr << endl;return false;}return true;
}/* 获取value */
bool RedisManage::Get(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_connect, "GET %s", key.c_str());if (_reply == NULL){cout << "[ GET " << key << " ] error" << endl;freeReplyObject(_reply);return false;}/* 不是字符串 */if (_reply->type != REDIS_REPLY_STRING){cout << "[ GET " << key << " ] not string" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "[ GET " << key << " ] success" << endl;return true;
}/* 设置value */
bool RedisManage::Set(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_connect, "SET %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ SET " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}// 执行失败则释放连接if ((_reply->type != REDIS_REPLY_STATUS && _reply->str != "ok") || _reply->str != "ok"){cout << "Execute command [ SET " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ SET " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 验证密码 */
bool RedisManage::Auth(const string& password)
{_reply = (redisReply*)redisCommand(_connect, "AUTH %s", password.c_str());if (_reply->type == REDIS_REPLY_ERROR){cout << "Auth failed" << endl;freeReplyObject(_reply);return false;}else{cout << "Auth success" << endl;freeReplyObject(_reply);return true;}
}/* 左侧插入 */
bool RedisManage::LPush(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_connect, "LPUSH %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ LPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}if (_reply->type != REDIS_REPLY_INTEGER || _reply->integer <= 0){cout << "Execute command [ LPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ LPush " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 左侧弹出 */
bool RedisManage::LPop(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_connect, "LPOP %s", key.c_str());if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ LPop " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ LPop " << key << " ] success" << endl;return true;
}/* 右侧插入 */
bool RedisManage::RPush(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_connect, "RPUSH %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ RPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}if (_reply->type != REDIS_REPLY_INTEGER || _reply->integer <= 0){cout << "Execute command [ RPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ RPush " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 右侧弹出 */
bool RedisManage::RPop(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_connect, "RPOP %s", key.c_str());if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ RPop " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ RPop " << key << " ] success" << endl;return true;
}/* 将名为key的hash表中的field设置为Value */
bool RedisManage::HSet(const string& key, const string& field, const string& value)
{/* 负责传输命令 */_reply = (redisReply*)redisCommand(_connect, "HSET %s %s %s", key.c_str(), field.c_str(), value.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}bool RedisManage::HSet(const char* key, const char* field, const char* value, size_t valuelen)
{const char* argv[4];size_t argvlen[4];argv[0] = "HSET";argvlen[0] = 4;argv[1] = key;argvlen[1] = strlen(key);argv[2] = field;argvlen[2] = strlen(field);argv[3] = value;argvlen[3] = valuelen;/* 负责传输二进制,比如图片之类的*/_reply = (redisReply*)redisCommandArgv(_connect, 4, argv, argvlen);if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 获取名为key的hash表中field对应的value */
string RedisManage::HGet(const string& key, const string& field)
{const char* argv[3];size_t argvlen[3];argv[0] = "HGET";argvlen[0] = 4;argv[1] = key.c_str();argvlen[1] = key.length();argv[2] = field.c_str();argvlen[2] = field.length();_reply = (redisReply*)redisCommandArgv(_connect, 3, argv, argvlen);if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ HGet " << key << " " << field << " ] failed" << endl;freeReplyObject(_reply);return "";}string value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ HGet " << key << " " << field << " ] success" << endl;return value;
}/* 删除key */
bool RedisManage::Del(const string& key)
{_reply = (redisReply*)redisCommand(_connect, "DEL %s", key.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ DEL " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ DEL " << key << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 判断key是否存在 */
bool RedisManage::ExitsKey(const string& key)
{_reply = (redisReply*)redisCommand(_connect, "EXISTS %s", key.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER || _reply->integer == 0){cout << "Execute command [ ExitsKey " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ ExitsKey " << key << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 关闭连接 */
void RedisManage::Close()
{redisFree(_connect);
}

1.2 编译测试

测试一下代码

void TestRedisManage() {assert(RedisManage::GetInstance()->Connect("127.0.0.1", 6380));assert(RedisManage::GetInstance()->Auth("123456"));assert(RedisManage::GetInstance()->Set("blogwebsite", "llfc.club"));std::string value = "";assert(RedisManage::GetInstance()->Get("blogwebsite", value));assert(RedisManage::GetInstance()->Get("nonekey", value) == false);assert(RedisManage::GetInstance()->HSet("bloginfo", "blogwebsite", "llfc.club"));assert(RedisManage::GetInstance()->HGet("bloginfo", "blogwebsite") != "");assert(RedisManage::GetInstance()->ExitsKey("bloginfo"));assert(RedisManage::GetInstance()->Del("bloginfo"));assert(RedisManage::GetInstance()->Del("bloginfo"));assert(RedisManage::GetInstance()->ExitsKey("bloginfo") == false);assert(RedisManage::GetInstance()->LPush("lpushkey1", "lpushvalue1"));assert(RedisManage::GetInstance()->LPush("lpushkey1", "lpushvalue2"));assert(RedisManage::GetInstance()->LPush("lpushkey1", "lpushvalue3"));assert(RedisManage::GetInstance()->RPop("lpushkey1", value));assert(RedisManage::GetInstance()->RPop("lpushkey1", value));assert(RedisManage::GetInstance()->LPop("lpushkey1", value));assert(RedisManage::GetInstance()->LPop("lpushkey2", value) == false);RedisManage::GetInstance()->Close();
}

执行失败

set指令出问题了

指令是执行成功了的

对于char只能使用strcmp的方式去比较

2. Redis连接池

之前写了事件循环池和GRPC连接池,事件循环池中是专门处理客户端和服务器之间的通讯的,如果客户端发来数据需要存储起来的话,服务器就需要调用我们刚刚封装的RedisManage获取它的单例然后去向redis数据库中写东西,这时候就带来一个问题,如果两个线程同时写,就会产生资源竞争而如果使用互斥锁,多线程的优势又没有完全展现出来,所用封装多个redis连接的池性组件,这样就能够充分发挥多线程的优势了

从原本的一个连接,变成多个连接

池性组件中的核心function就是获取连接和还回连接

/* Redis 连接池 */
class RedisPool
{
public:RedisPool(size_t PoolSize, const char* host, int port, const char* password = "123456"): _PoolSize(PoolSize), _host(host), _port(port), bIsStop(false){for (size_t i = 0; i < PoolSize; i++){redisContext* redis = redisConnect(_host, _port);if (redis == NULL || redis->err != 0){if (redis){redisFree(redis);}continue;}redisReply* ret = (redisReply*)redisCommand(redis, "AUTH %s", password);if (ret->type == REDIS_REPLY_ERROR){cout << "Redis Auth Error: " << ret->str << endl;freeReplyObject(ret);redisFree(redis);continue;}freeReplyObject(ret);cout << "Redis Connect Success!" << endl;_pool.push(redis);}}~RedisPool(){lock_guard<mutex> lock(_mutex);bIsStop = true;_cond.notify_all();															// 唤醒所有线程while (!_pool.empty()){redisContext* redis = _pool.front();_pool.pop();redisFree(redis);}}/* 获取一个redis 连接 */redisContext* GetConnect(){unique_lock<mutex> lock(_mutex);_cond.wait(lock, [this]() {return!_pool.empty() || !bIsStop; });redisContext* redisConnection = _pool.front();_pool.pop();return redisConnection;}/* 归还一个redis 连接 */void ReturnConnect(redisContext* redis){lock_guard<mutex> lock(_mutex);if(bIsStop)return;_pool.push(redis);_cond.notify_one();																// 唤醒沉睡的线程}private:atomic<bool> bIsStop;																// 停止标志size_t _PoolSize;																	// 连接池大小const char* _host;																	// redis主机地址int _port;																			// redis端口/* 队列, 锁, 条件变量 */queue<redisContext*> _pool;															// 连接池mutex _mutex;																		// 互斥锁condition_variable _cond;															// 条件变量
};

重新修改的redis连接类

头文件

class RedisManage : public Singletion<RedisManage>
{friend class Singletion<RedisManage>;
public:~RedisManage();bool Get(const string& key, string& value);											// 获取valuebool Set(const string& key, const string& value);									// 设置valuebool Auth(const string& password);													// 验证密码bool LPush(const string& key, const string& value);									// 左侧pushbool LPop(const string& key, string& value);										// 左侧popbool RPush(const string& key, const string& value);									// 右侧pushbool RPop(const string& key, string& value);										// 右侧popbool Del(const string& key);														// 删除keybool ExitsKey(const string& key);													// 判断key是否存在void Close();																		// 关闭连接/* 将名为key的hash表中的field设置为Value */bool HSet(const string& key, const string& field, const string& value);				bool HSet(const char* key, const char* field, const char* value, size_t valuelen);/* 获取名为key的hash表中field对应的value */string HGet(const string& key, const string& field);					private:RedisManage();private:RedisPool* _redisPool;																// redis连接池redisReply* _reply;																	// redis响应对象
};
#endif // REDISMANAGE_H

实现文件

#include "RedisManage.h"
#include "ServerStatic.h"RedisManage::~RedisManage()
{}RedisManage::RedisManage()
{const char* ip = get<string>(ServerStatic::ParseConfig("Redis", "Host")).c_str();int Port = get<int>(ServerStatic::ParseConfig("Redis", "Port"));_redisPool = new RedisPool(5,ip, Port);
}/* 获取value */
bool RedisManage::Get(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "GET %s", key.c_str());if (_reply == NULL){cout << "[ GET " << key << " ] error" << endl;freeReplyObject(_reply);return false;}/* 不是字符串 */if (_reply->type != REDIS_REPLY_STRING){cout << "[ GET " << key << " ] not string" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "[ GET " << key << " ] success" << endl;return true;
}/* 设置value */
bool RedisManage::Set(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "SET %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ SET " << key << " " << value << " ] failed   _reply == NULL" << endl;freeReplyObject(_reply);return false;}// 执行失败则释放连接if ((_reply->type != REDIS_REPLY_STATUS && strcmp(_reply->str, "OK") != 0) || strcmp(_reply->str, "OK") != 0){cout << "Execute command [ SET " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ SET " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 验证密码 */
bool RedisManage::Auth(const string& password)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "AUTH %s", password.c_str());if (_reply->type == REDIS_REPLY_ERROR){cout << "Auth failed" << endl;freeReplyObject(_reply);return false;}else{cout << "Auth success" << endl;freeReplyObject(_reply);return true;}
}/* 左侧插入 */
bool RedisManage::LPush(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "LPUSH %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ LPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}if (_reply->type != REDIS_REPLY_INTEGER || _reply->integer <= 0){cout << "Execute command [ LPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ LPush " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 左侧弹出 */
bool RedisManage::LPop(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "LPOP %s", key.c_str());if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ LPop " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ LPop " << key << " ] success" << endl;return true;
}/* 右侧插入 */
bool RedisManage::RPush(const string& key, const string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "RPUSH %s %s", key.c_str(), value.c_str());if (_reply == NULL){cout << "Execute command [ RPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}if (_reply->type != REDIS_REPLY_INTEGER || _reply->integer <= 0){cout << "Execute command [ RPush " << key << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ RPush " << key << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 右侧弹出 */
bool RedisManage::RPop(const string& key, string& value)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "RPOP %s", key.c_str());if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ RPop " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ RPop " << key << " ] success" << endl;return true;
}/* 将名为key的hash表中的field设置为Value */
bool RedisManage::HSet(const string& key, const string& field, const string& value)
{/* 负责传输命令 */_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "HSET %s %s %s", key.c_str(), field.c_str(), value.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}bool RedisManage::HSet(const char* key, const char* field, const char* value, size_t valuelen)
{const char* argv[4];size_t argvlen[4];argv[0] = "HSET";argvlen[0] = 4;argv[1] = key;argvlen[1] = strlen(key);argv[2] = field;argvlen[2] = strlen(field);argv[3] = value;argvlen[3] = valuelen;/* 负责传输二进制,比如图片之类的*/_reply = (redisReply*)redisCommandArgv(_redisPool->GetConnect(), 4, argv, argvlen);if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ HSet " << key << " " << field << " " << value << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 获取名为key的hash表中field对应的value */
string RedisManage::HGet(const string& key, const string& field)
{const char* argv[3];size_t argvlen[3];argv[0] = "HGET";argvlen[0] = 4;argv[1] = key.c_str();argvlen[1] = key.length();argv[2] = field.c_str();argvlen[2] = field.length();_reply = (redisReply*)redisCommandArgv(_redisPool->GetConnect(), 3, argv, argvlen);if (_reply == NULL || _reply->type == REDIS_REPLY_NIL){cout << "Execute command [ HGet " << key << " " << field << " ] failed" << endl;freeReplyObject(_reply);return "";}string value = _reply->str;freeReplyObject(_reply);cout << "Execute command [ HGet " << key << " " << field << " ] success" << endl;return value;
}/* 删除key */
bool RedisManage::Del(const string& key)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "DEL %s", key.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER){cout << "Execute command [ DEL " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ DEL " << key << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 判断key是否存在 */
bool RedisManage::ExitsKey(const string& key)
{_reply = (redisReply*)redisCommand(_redisPool->GetConnect(), "EXISTS %s", key.c_str());if (_reply == NULL || _reply->type != REDIS_REPLY_INTEGER || _reply->integer == 0){cout << "Execute command [ ExitsKey " << key << " ] failed" << endl;freeReplyObject(_reply);return false;}cout << "Execute command [ ExitsKey " << key << " ] success" << endl;freeReplyObject(_reply);return true;
}/* 关闭连接 */
void RedisManage::Close()
{redisFree(_redisPool->GetConnect());
}

重新修改读取配置文件类,采用c++17的variant来返回

static variant<int, string> ParseConfig(string blockName, string key, string configPath = "./Config/config.json");/* 解析配置文件 */
variant<int, string>ServerStatic::ParseConfig(string blockName, string key, string configPath)
{ifstream file(configPath, ifstream::binary);if (!file.is_open()){cerr << "Failed to open config file: " << configPath << endl;return {};}Json::Value jsonResult;Json::Reader reader;if (!reader.parse(file, jsonResult)){cout << "Failed to parse config file: " << configPath << endl;return {};}if (!jsonResult.isMember(blockName)){cout << "Failed to find block: " << blockName << endl;return {};}const Json::Value& value = jsonResult[blockName][key];if (value.isInt()){return value.asInt();}else if (value.isString()){return value.asString();}return {};
}

2.2 编译测试

报错,说std::iterator什么什么的

C++17 中,标准库弃用了std::iterator,可以定义_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING来屏蔽这个错误

编译成功

redis连接池编写成功

相关文章:

QT聊天项目DAY10

1.封装redis操作类 头文件 #ifndef REDISMANAGE_H #define REDISMANAGE_H#include "Singletion.h" #include "GlobalHead.h"class RedisManage : public Singletion<RedisManage> {friend class Singletion<RedisManage>; public:~RedisMana…...

养生:开启健康生活的钥匙

养生&#xff0c;是对生活的精心呵护&#xff0c;是通往健康之路的秘诀。以下从饮食、运动、睡眠和心态四个方面&#xff0c;为你呈现科学养生之道。 饮食养生&#xff1a;营养均衡的智慧 合理的饮食是养生的基础。遵循 “食物多样&#xff0c;谷类为主” 的原则&#xff0c;…...

基于springboot的海洋环保知识分享系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…...

操作系统 第2章节 进程,线程和作业

一:多道程序设计 1-多道程设计的目的 for:提高吞吐量(作业道数/处理时间),我们可以从提高资源的利用率出发 2-单道程序设计缺点: 设备的利用率低,内存的利用率低,处理机的利用率低 比如CPU去访问内存,CPU空转.内存等待CPU访问也是没有任何操作的.要是有多个东西要去访问不冲…...

住宅IP的深度解析与合理运用

海外住宅代理IP作为全球化数字业务的核心工具&#xff0c;其配置与运用需兼顾技术适配性、业务需求与合规性。以下从类型选择、配置方法、应用场景、优化策略及风险控制五个维度进行解析&#xff1a; 一、类型选择&#xff1a;静态与动态住宅IP的核心差异 静态住宅IP 特性&…...

RT-Thread 深入系列 Part 2:RT-Thread 内核核心机制深度剖析

摘要&#xff1a; 本文从线程管理、调度器原理、中断处理与上下文切换、IPC 同步机制、内存管理五大核心模块出发&#xff0c;深入剖析 RT-Thread 内核实现细节&#xff0c;并辅以源码解读、流程图、时序图与性能数据。 目录 线程管理与调度器原理 1.1 线程控制块&#xff08;T…...

在线caj转换word

CAJ格式是中国知网特有的一种文献格式&#xff0c;在学术研究等领域广泛使用&#xff0c;但有时我们需要将其转换为Word格式&#xff0c;方便编辑、引用文献。本文分享如何轻松将CAJ转换为word的转换工具&#xff0c;提高阅读和办公效率。 如何将CAJ转换WORD? 1、使用CAJ转换…...

25:三大分类器原理

1.分类的逻辑&#xff1b; 2.统计学与数据分析。 ************************ Mlp 多层感知系统 GMM 高斯混合模型-极大似然估计法 SVM 支持向量机建立一个超平面作为决策曲面&#xff0c;使得正例和反例的隔离边界最大化 Knn 1.MLP整个模型就是这样子的&#xff0c;上面…...

数据库插入数据时自动生成创建时间和修改时间

工具 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component;import java.time.LocalDateTime; Component public class MetaObjectHandlerConfig implements…...

Go语言中 源文件开头的 // +build 注释的用法

// build注释主要用于实现条件编译。借助设置不同的构建标签&#xff08;build tags&#xff09;&#xff0c;我们能够指定在特定的操作系统、架构或者其他自定义条件下才编译某个文件 1、基本规则 格式要求&#xff1a; 这种注释必须出现在文件的开头部分。注释与包声明之间至…...

【从零开始学习微服务 | 第一篇】单体项目到微服务拆分实践

目录 引言 一、选择聚合结构进行拆分的优势 二、微服务模块创建步骤 &#xff08;一&#xff09;引入 pom 文件与修改 &#xff08;二&#xff09;创建 Spring Boot 启动类 &#xff08;三&#xff09;搭建基本包结构 三、配置文件的引入与调整 四、业务代码的引入与注意…...

【高并发】Celery + Redis异步任务队列方案提高OCR任务时的并发

线程池处理OCR仍然会阻塞请求的原因主要有以下几点&#xff0c;以及为什么CeleryRedis是更好的解决方案&#xff1a; 1. 线程池的阻塞本质 请求-响应周期未分离&#xff1a;即使使用线程池&#xff0c;HTTP请求仍需要等待线程池任务完成才能返回响应。当所有线程都繁忙时&#…...

2025数维杯数学建模竞赛B题完整参考论文(共38页)(含模型、代码、数据)

2025数维杯数学建模竞赛B题完整参考论文 目录 摘要 一、问题重述 二、问题分析 三、模型假设 四、定义与符号说明 五、 模型建立与求解 5.1问题1 5.1.1问题1思路分析 5.1.2问题1模型建立 5.1.3问题1求解结果 5.2问题2 5.2.1问题2思路分析 5.2.2问题2…...

C#黑魔法:鸭子类型(Duck Typing)

C#黑魔法&#xff1a;鸭子类型(Duck Typing) 如果它走起路来像鸭子&#xff0c;叫起来像鸭子&#xff0c;那么它就是鸭子。 鸭子类型&#xff0c;主要应用于动态语言类型&#xff0c;比如JS、Python等&#xff0c;核心理念为&#xff1a;关注对象的行为&#xff08;方法或属性…...

AI数据分析中的伪需求场景:现状、挑战与突破路径

在当今企业数字化转型浪潮中&#xff0c;AI数据分析产品如雨后春笋般涌现&#xff0c;但其中存在大量"伪需求场景"——看似创新实则难以落地的功能设计。本文将从技术限制、用户体验和商业价值三个维度&#xff0c;系统分析AI数据分析产品中常见的伪场景现象&#xf…...

大尺寸PCB如何重塑通信与新能源产业格局

在5G通信基站与新能源电站的机房内&#xff0c;一块块面积超过600mm600mm的PCB板正悄然推动着技术革命。作为电子设备的核心载体&#xff0c;大尺寸PCB凭借其高密度集成与复杂工艺&#xff0c;成为通信、能源等领域的“隐形功臣”。以猎板PCB为代表的厂商&#xff0c;凭借宽幅曝…...

base64与图片的转换和预览(高阶玩法)

1.完整的功能描述 功能概述 这是一个网页工具&#xff0c;支持用户输入不同格式的图片数据或上传本地图片文件&#xff0c;对图片进行预览、转换为多种格式&#xff0c;并支持导出不同格式的图片数据。 输入方式 1. 文本输入 &#xff1a;用户可以输入 Data URL、公网图片 UR…...

AI客服问答自动生成文章(基于deepseek实现)

小编一直在用AI做网站平台文章的润色或者二创。一直有一个想法&#xff0c;在自己网站加一个AI智能客服&#xff0c;通过文心或者deepseek来智能回答网友提出的问题&#xff0c;这样就能减少很多人工回复的麻烦&#xff0c;提高互动效率。 开发背景 其实很多网友提出的问题非…...

Langchain、RAG、Agent相关

ChatBot-销售型机器人 优化点&#xff1a;把相似度低于10条的请求Query打印出来。 RAG 类型&#xff1a;RAG、Latent RAG&#xff08;产生一个回答&#xff0c;再用回答进行召回&#xff09;、Logit RAG、Speculative RAG 个人感觉RAG召回可以分成3种&#xff1a;一种是que…...

Spring Web MVC基础理论和使用

目录 什么是MVC 什么是SpringMVC SpringMVC基础使用 建立连接 RequestMapping介绍 请求 传递参数 传递对象 参数重命名 传递数组 传递JSON数据 获取URL中参数 上传文件 获取Cookie/Session 获取Header 响应 返回静态页面 RestController和Controller的区别 返…...

课程审核流程揭秘:确保内容合规与用户体验

业务流程 为什么课程审核通过才可以发布呢&#xff1f; 这样做为了防止课程信息有违规情况&#xff0c;课程信息不完善对网站用户体验也不好&#xff0c;课程审核不仅起到监督作用&#xff0c;也是 帮助教学机构规范使用平台的手段。 如果流程复杂用工作流 说明如下&#xff…...

Mac电脑,idea突然文件都展示成了文本格式,导致ts,tsx文件都不能正常加载或提示异常,解决方案详细说明如下

有一天使用clean my mac软件清理电脑 突然发现idea出现了文件都以文本格式展示&#xff0c;如图所示 然后就卸载&#xff0c;计划重新安装&#xff0c;安装了好几个版本&#xff0c;并且setting->file types怎么设置都展示不对&#xff0c;考虑是否idea没卸载干净&#xff…...

HarmonyOS开发-组件市场

1. HarmonyOS开发-组件市场 HarmonyOS NEXT开源组件市场是一个独立的插件&#xff0c;需通过DevEco Studio进行安装&#xff0c;可以点击下载&#xff0c;无需解压&#xff0c;直接通过zip进行安装&#xff0c;具体安装和使用方法可参考HarmonyOsNEXT组件市场使用说明。Harmony…...

【Python 列表(List)】

Python 中的列表&#xff08;List&#xff09;是最常用、最灵活的有序数据集合&#xff0c;支持动态增删改查操作。以下是列表的核心知识点&#xff1a; 一、基础特性 有序性&#xff1a;元素按插入顺序存储可变性&#xff1a;支持增删改操作允许重复&#xff1a;可存储重复元…...

vison transformer vit 论文阅读

An Image is Worth 16x16 Words 20年的论文看成10年的哈斯我了 [2010.11929] 一张图像胜过 16x16 个单词&#xff1a;用于大规模图像识别的转换器 --- [2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 为什么transformer好训练&am…...

图像移动图像归类代码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 图像移动图像归类代码 import os import shutilvalue_dir rJ:\IDM_data\cls_chinese_medicine\cls_chinese_medicine\traintrain_dir rJ:\IDM_data\cls_chinese_medicine\c…...

Day 15 训练

Day 15 对鸢尾花数据集进行处理&#xff0c;特征可视化&#xff0c;贝叶斯优化随机森林&#xff0c;Shap解释1. 导入必要的库2. 设置中文字体3. 加载数据集4. 查看数据5. 数据准备6. 贝叶斯优化随机森林7. 评估结果8. 绘制箱形图9. 绘制特征相关性热力图10. SHAP模型解释总结 对…...

Vue Router 3 使用详解:从零构建嵌套路由页面

Vue Router 是 Vue.js 官方的路由管理器&#xff0c;常用于构建单页面应用&#xff08;SPA&#xff09;。本文将手把手带你完成 vue-router3.6.5 的基本配置&#xff0c;并实现一个带有嵌套路由的页面结构。本文适用于 Vue 2.x 项目 一、安装 vue-router3.6.5 npm install vue…...

物理服务器紧急救援:CentOS系统密码重置全流程实战指南

前言 在企业IT运维实践中&#xff0c;物理服务器密码丢失是典型的"低概率高风险"事件。某金融科技公司曾因核心服务器密码遗失导致业务中断36小时&#xff0c;直接损失超过800万元。这起真实案例揭示了系统密码管理的关键性——当承载重要业务的物理服务器遭遇密码丢…...

第J7周:对于ResNeXt-50算法的思考

目录 思考 一、代码功能分析 1. 构建 shortcut 分支&#xff08;残差连接的旁路&#xff09; 2. 主路径的第一层卷积&#xff08;11&#xff09; 4. 主路径的第三层卷积&#xff08;11&#xff09; 5. 残差连接 激活函数 二、问题分析总结&#xff1a;残差结构中通道数不一致的…...