QT聊天项目DAY10

1.封装redis操作类

头文件

cpp 复制代码
#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);											// 连接redis
	bool Get(const string& key, string& value);											// 获取value
	bool Set(const string& key, const string& value);									// 设置value
	bool Auth(const string& password);													// 验证密码
	bool LPush(const string& key, const string& value);									// 左侧push
	bool LPop(const string& key, string& value);										// 左侧pop
	bool RPush(const string& key, const string& value);									// 右侧push
	bool RPop(const string& key, string& value);										// 右侧pop
	bool Del(const string& key);														// 删除key
	bool 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

实现文件

cpp 复制代码
#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 编译测试

测试一下代码

cpp 复制代码
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就是获取连接和还回连接

cpp 复制代码
/* 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连接类

头文件

cpp 复制代码
class RedisManage : public Singletion<RedisManage>
{
	friend class Singletion<RedisManage>;
public:
	~RedisManage();
	bool Get(const string& key, string& value);											// 获取value
	bool Set(const string& key, const string& value);									// 设置value
	bool Auth(const string& password);													// 验证密码
	bool LPush(const string& key, const string& value);									// 左侧push
	bool LPop(const string& key, string& value);										// 左侧pop
	bool RPush(const string& key, const string& value);									// 右侧push
	bool RPop(const string& key, string& value);										// 右侧pop
	bool Del(const string& key);														// 删除key
	bool 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

实现文件

cpp 复制代码
#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来返回

cpp 复制代码
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连接池编写成功

相关推荐
小杜-coding6 分钟前
黑马点评day04(分布式锁-setnx)
java·spring boot·redis·分布式·spring·java-ee·mybatis
tanxiaomi7 小时前
Java中对象集合转换的优雅实现【实体属性范围缩小为vo】:ListUtil.convert方法详解
java·spring boot·mybatis
cs8219848319 小时前
QT 解决msvc fatal error C1060: 编译器的堆空间不足
开发语言·qt
m0_5557629013 小时前
手势、鼠标滑动实现界面切换
c++·qt
bbqz00715 小时前
Qml Console
c++·qt·qml
小马爱打代码17 小时前
Spring Boot + MyBatis-Plus 高并发读写分离实战
spring boot·mybatis
小刘|1 天前
Redis 中简单动态字符串(SDS)的深入解析
数据库·redis·bootstrap
cykaw25901 天前
QT 文件选择对话框 QFileDialog
开发语言·qt
RunsenLIu1 天前
基于Django和Bootstrap开发的美食推荐系统
django·bootstrap·美食