正在做一个第三方微信企业要接口的项目,JAVA的实现方法比较简单,网上资料也很多。
但是我需要在C++下实现,微信企业号接口大多都是https的GET/POST方法实现的。
Qt提供了一个封装好的类QNetworkAccessManager,就不需要使用windows的套接字来编程了,也脱离的平台限制。
上图是我从http://blog.csdn.net/chenlong12580/article/details/7392766 当中借来得,这位兄弟也很好的演示了QNetworkAccessManager的基本调用方法。
但是QNetworkAccessManager是为图形界面而设计的,当Manager得到finished()信号时,使用一个SLOT函数去做读取数据的事,这对于显示在GUI的数据时,可以说不能再好用了。
但是微信企业号在调用任何的接口之前,都需要获得一个认证,就是access_token,需要使用GET方式来获得,这使得我需要将获得access_token的方法封装成一个函数,以便在每次具体的如发送微信之前,调用它。
贴上代码:
void MainWindow::getAccessToken()
{
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishedSlot(QNetworkReply*)),Qt::DirectConnection);
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(ACCESS_TOKEN_URL)));
}
void MainWindow::finishedSlot(QNetworkReply* reply)
{
qDebug()<<"start";
QVariant statusCodeV =
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl =
reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(reply->error()==QNetworkReply::NoError)
{
QByteArray bytes = reply->readAll();
QString rlt =QString::fromUtf8(bytes);
accessToken = rlt;
}
reply->deleteLater();
//ACCESS_FLAG = true;
qDebug()<<"finished";
}
如果我再main中直接调用
getAccessToken()
的话,程序会直接运行之后的代码片,而不会先运行SLOT,因为他们在同一线程。
而如果用C++11的 thread.h 用多线程调用,编译器也不认QNetworkReply为valid的type,并且多线程也不符合代码的逻辑,因为主线程要等待子线程,且只有一个子线程。
解决的办法就是使用QEventLoop:直接上代码:
void MainWindow::getAccessToken()
{
QEventLoop temp_loop;
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(ACCESS_TOKEN_URL)));
connect(reply, SIGNAL(finished()), &temp_loop, SLOT(quit()));
temp_loop.exec();
qDebug()<<"start";
QVariant statusCodeV =
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl =
reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(reply->error()==QNetworkReply::NoError)
{
QByteArray bytes = reply->readAll();
QString rlt =QString::fromUtf8(bytes);
accessToken = rlt;
qDebug()<deleteLater();
qDebug()<<"finished";
}
通过比较之前的代码片,我想应该很好看出不同,不仅within一个方法,而且代码也更好读更短,QNetworkAccessManager的操作封装在一个函数中了。
这里还要提一点,按照文档的资料,QNetworkReply的waitForReadyRead()函数,应该也可以完成上述操作,但是我发现不管设置几秒的等待,函数都无脑回false,看网上说Qt在某个版本后这个函数失效了,我用的是Qt5.4,可能4.x下可以用,应该也是可以实现的的。