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连接池编写成功

相关推荐
考虑考虑3 天前
Mybatis实现批量插入
java·后端·mybatis
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt