背景:后台需要静默调用接口访问数据,不能影响UI线程操作,数据可能会有上万,一次不能全传过来,递归自己调用接口。服务器会在接口返回值中totaEelements返回当前筛选条件下的总条数,比如pageNumber为1,pageSize为100,意味着获取全部数据,如共329条,按照每页100分开,现在获取第1页。totaEelements为329。
struct NetworkReply
{
QNetworkReply::NetworkError error = QNetworkReply::NetworkError::NoError;
QByteArray content;
QString errorString = "";
};
class NetworkHelper :public QObject
{
Q_OBJECT
public:
static NetworkReply post(const QString url, const QByteArray content, int timeout = NetworkSet::getInstance()->getDelayTime());
/**
* \brief 同步post请求
* \param url 地址如"/api/pack/list"
* \param content json内容
* \param timeout 超时设置(毫秒)
* \return NetworkReply请求结果
*/
static NetworkReply postJson(const QString url, const QByteArray content, int timeout = NetworkSet::getInstance()->getDelayTime());
/**
* \brief 异步post请求
* \param manager 请求管理对象,在函数调用处绑定信号和自定义的槽connect(manager, &QNetworkAccessManager::finished,***,***);
* \param url 地址如"/api/pack/list"
* \param content json内容
*/
static void postJson(QNetworkAccessManager* manager, const QString url, const QByteArray content);
/**
* \brief 获取登记人员列表 [异步]
* \param pageNumber 页码
* \param pageSize 每页数量
* \param startTime 操作开始时间yyyy-MM-dd HH:mm:ss
* \param endTime 操作结束时间yyyy-MM-dd HH:mm:ss
*/
static void getUserListSync(int pageNumber, int pageSize, QString startTime = "", QString endTime = "");
};
```cpp
NetworkReply NetworkHelper::post(const QString url, const QByteArray content, int timeout)
{
QEventLoop eventloop;
QTimer timer;
timer.singleShot(timeout, &eventloop, &QEventLoop::quit);
QNetworkAccessManager manager;
manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
manager.setProxy(QNetworkProxy::NoProxy);
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");//二进制流类型
request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
timer.start(timeout);
QNetworkReply* reply = manager.post(request, content);
connect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
eventloop.exec(QEventLoop::ExcludeUserInputEvents); //开启事件循环
NetworkReply result;
if (!timer.isActive())
{
//超时,未知状态
disconnect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
reply->abort();
reply->deleteLater();
result.error = QNetworkReply::NetworkError::TimeoutError;
return result;
}
reply->abort();
reply->deleteLater();
result.error = reply->error();
result.errorString = reply->errorString();
result.content = reply->readAll();
return result;
}
NetworkReply NetworkHelper::postJson(const QString url, const QByteArray content, int timeout)
{
QEventLoop eventloop;
QTimer timer;
timer.singleShot(timeout, &eventloop, &QEventLoop::quit);
QNetworkAccessManager manager;
manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
manager.setProxy(QNetworkProxy::NoProxy);
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
timer.start(timeout);
QNetworkReply* reply = manager.post(request, content);
connect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
eventloop.exec(QEventLoop::ExcludeUserInputEvents); //开启事件循环
NetworkReply result;
if (!timer.isActive())
{
//超时,未知状态
disconnect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
reply->abort();
reply->deleteLater();
result.error = QNetworkReply::NetworkError::TimeoutError;
return result;
}
reply->abort();
reply->deleteLater();
result.error = reply->error();
result.errorString = reply->errorString();
result.content = reply->readAll();
return result;
}
void NetworkHelper::postJson(QNetworkAccessManager* manager, const QString url, const QByteArray content)
{
manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
manager->setProxy(QNetworkProxy::NoProxy);
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
request.setUrl(QUrl(NetworkSet::getInstance()->getUrl().toString() + url));
manager->post(request, content);
}
void NetworkHelper::getUserListSync(int pageNumber, int pageSize, QString startTime, QString endTime)
{
if (NetworkSet::getInstance()->getToken().isEmpty())
return;
LocalLog->info(QString(u8"准备获取用户列表第%1页%2个").arg(pageNumber).arg(pageSize));
//body 参数
QJsonObject json;
QJsonObject jsonData;
QJsonObject data;
data.insert("pageNumber", pageNumber);
data.insert("pageSize", pageSize);
jsonData.insert("tokenId", NetworkSet::getInstance()->getToken());
jsonData.insert("data", data);
json.insert("jsonData", jsonData);
QJsonDocument document;
document.setObject(json);
QByteArray dataArray = document.toJson(QJsonDocument::Compact);
QString apiPath = "/api/userlist";
NetworkReply replay = NetworkHelper::postJson(apiPath, dataArray);
if (replay.error == QNetworkReply::NetworkError::TimeoutError)
{
LocalLog->debug(apiPath + u8"请求超时");
}
else
{
if (replay.error != QNetworkReply::NetworkError::NoError)
{
LocalLog->debug(apiPath + u8"请求出错 : " + replay.errorString);
}
else
{
QJsonDocument document = QJsonDocument::fromJson(replay.content, new QJsonParseError);
QJsonObject rootObj = document.object();
QString code = rootObj["code"].toString(); //服务器返回的状态码
bool success = rootObj["success"].toBool(); //是否成功
QString message = rootObj["message"].toString();
if (code == "200" && success)
{
if (rootObj.contains("data"))
{
QJsonObject subObj = rootObj.value("data").toObject();
QString token = subObj["tokenId"].toString();
int totaEelements = subObj["totaEelements"].toString().toInt();
if (subObj.contains("items"))
{
QList<User>users;
QJsonArray itemsObj = subObj.value("items").toArray();
for (int i = 0; i < itemsObj.count(); ++i)
{
QJsonObject item = itemsObj.at(i).toObject();
User user;
user.userName = item["userName"].toString(); //用户名
user.emplName = item["emplName"].toString(); //姓名
users.push_back(user);
}
DataBaseOperation::addUsers(users);
}
if (pageNumber * pageSize < totaEelements)
{
LocalLog->info(u8"发现数据不足,自动调用");
getUserListSync(pageNumber + 1, pageSize, startTime, endTime);
}
}
}
else
LocalLog->error(apiPath + message);
}
}
}
调用的话只需要利用QtConcurrent::run临时开启一个子线程即可,从第一页开始获取,每次最多获取5000个,如果总数据太多,每次获取太多条等待时间太长,容易产生一些额外情况
QtConcurrent::run([=]
{
NetworkHelper::getUserListSync(1, 5000);
});