上一篇介绍了Qt开源网络库,有兴趣的可以翻开往期推送.今篇主要介绍该开源网络库接口的用法.
1. 接口目录文件列表:
Network
├── HttpRequest.h
├── HttpResponse.h
└── HttpService.h
2. QtNetworkService网络库接口体现在这三个头文件:
(1)HttpRequest.h是处理网络请求功能,比如参数,body,json数据,表单数据;
(2)HttpResponse.h是处理网络响应功能,当请求数据返回时会经过它处理;
(3)HttpService.h是用户使用的接口层,提供get,post, put, send等http接口.
3. HttpService头文件源代码:
#ifndef HTTP_SERVICE_H
#define HTTP_SERVICE_H
#include "HttpRequest.h"
#include "HttpResponse.h"
#include <QNetworkRequest>
#include <QNetworkReply>
class HttpService : public QNetworkAccessManager
{
Q_OBJECT
public:
friend class HttpRequest;
HttpService();
~HttpService();
HttpRequest get(const QString &url);
HttpRequest post(const QString &url);
HttpRequest put(const QString &url);
HttpRequest send(const QString &url, Operation op = GetOperation);
};
#endif // HTTP_SERVICE_H
HttpService类提供的接口有get, post, put, send这几种方式,url为请求路径,如果使用send方式,则需要指定op的属性,默认为get方式.
4. HttpRequest类头文件源代码:
#ifndef HTTP_REQUEST_H
#define HTTP_REQUEST_H
#include "HttpResponse.h"
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QJsonObject>
#include <functional>
class HttpService;
class HttpRequest
{
public:
explicit HttpRequest(QNetworkAccessManager::Operation op, HttpService *jsonHttpClient);
virtual ~HttpRequest();
HttpRequest &url(const QString &url);
HttpRequest &header(const QString &key, const QVariant &value);
HttpRequest &headers(const QMap<QString, QVariant> &headers);
HttpRequest &queryParam(const QString &key, const QVariant &value);
HttpRequest &queryParams(const QMap<QString, QVariant> ¶ms);
/* Mainly used for identification */
HttpRequest &userAttribute(const QVariant &value);
HttpRequest &jsonBody(const QVariant &jsonBody);
/*
* @onRespone slot support type: void function(QVariantMap resultMap) OR
* void function(QByteArray resultData) OR
* void function(QNetworkReply* reply)
* note: The same type is only triggered once
*/
HttpRequest &onResponse(const QObject *receiver, const char *slot, HttpResponse::SupportMethod type = HttpResponse::AutoInfer);
/*
* @onError slot support type: void function(QNetworkReply::NetworkErro errorr)
* note: The same type is only triggered once
*/
HttpRequest &onError(const QObject *receiver, const char *slot);
HttpResponse *exec();
private:
HttpRequest();
private:
QNetworkRequest m_networkRequest;
QJsonObject m_jsonBody;
QNetworkAccessManager::Operation m_op;
HttpService *m_httpService;
QMultiMap<QString, QMap<QString, const QObject *>> m_slotsMap;
};
#endif // HTTP_REQUEST_H
HttpRequest类后台逻辑都是封装QNetworkRequest类,提供出来的接口主要有:
(1)url为调用请求路径;
(2)header相当于setRawHeader, 用于设置HTTP头信息;
request.header("Last-Modified", "1994-05-07 08:49:37");
(3)headers用于多个HTTP头信息参数同时写入;
(4)queryParam用于表单提交数据,这个是对于URL的数据拼接,比如:
原url:
http://www.qt.io
使用queryParam("param1", "test")添加表单数据;
则url变为:
http://www.qt.io?param1=test
(5)queryParams用于多个表单参数同时写入;
(6)userAttribute用于自定义数据,主要配合HttpResponse使用,用于区别请求是哪一个,用得相对较少;
(7)jsonBody用于post,put提交json数据,get无效;
(8)onResponse为设置异步槽函数,当请求回应时,系统自动调用对象接收者(第一个参数)的槽函数(第二个参数).这里底层自动帮你绑定了槽函数.该槽函数需要用户自定义.
<1>该槽函数的定义也是有限制的目前只支持这三种槽函数定义方式:
void function(QVariantMap resultMap) //function为用户定义函数的名字
void function(QByteArray resultData) //function为用户定义函数的名字
void function(QNetworkReply* reply) //function为用户定义函数的名字
<2>用法:
m_service.get("http:/www.baidu.com")
.onResponse(this, SLOT(finish(QVariantMap)))
.onError(this, SLOT(error(QNetworkReply::NetworkError, QNetworkReply*)))
.exec();
<3>onResponse里面的this为接收者对象,SLOT(finish(QVariantMap))则为该对象的finish槽函数,当请求正常返回时,系统将对自动调用finish槽函数,当然槽函数的QVariantMap则为结果(类型自动转换为QVariantMap),如果返回数据不是json格式,则finish获取到的结果为空.修改为finish(QByteArray)通用做法也可以.最终的处理结果由finish操作.
m_service.get("http:/www.baidu.com")
.onResponse(this, SLOT(finish(QByteArray)))
.onError(this, SLOT(error(QNetworkReply::NetworkError, QNetworkReply*)))
.exec();
<4>onResponse还支持以下类型槽函数
void function(qint64 bytesReceived, qint64 bytesTotal);
该槽函数用于数据接收的进度状态,bytesReceived变量为已经接收到的数据长度,bytesTotal为需要接收的总长度.
示例:
m_service.get("http:/www.baidu.com")
.onResponse(this, SLOT(downloadProgress(qint64, qint64)))
.onError(this, SLOT(error(QNetworkReply::NetworkError, QNetworkReply*)))
.exec();
(9)onError与onResponse用法,但要注意支持的类型不一样
void function(QNetworkReply::NetworkError error);
void function(QString errorString);
void function(QNetworkReply::NetworkError error, QNetworkReply* reply);
void function(QString errorString, QNetworkReply* reply);
(10)exec为执行操作请求,如果没有调用该函数,则请求不会发送.
5. HttpResponse类头文件源代码:
#ifndef HTTP_RESPONSE_H
#define HTTP_RESPONSE_H
#include <QNetworkReply>
#include <QMultiMap>
class HttpResponse : public QNetworkReply
{
Q_OBJECT
public:
/*
* Support Reflex Method
* default: AutoInfer
* AutoInfer: Automatic derivation based on type
*/
enum SupportMethod {
AutoInfer,
onResponse_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply* reply); Is_AutoInfer: true */
onResponse_QByteArray, /* method: void function(QByteArray data); Is_AutoInfer: true */
onResponse_QVariantMap, /* method: void function(QVariantMap map); Is_AutoInfer: true */
onDownloadProgress_qint64_qint64, /* method: void function(qint64 bytesReceived, qint64 bytesTotal); Is_AutoInfer: true */
onError_QNetworkReply_To_NetworkError, /* method: void function(QNetworkReply::NetworkError error); Is_AutoInfer: true */
onError_QString, /* method: void function(QString errorString); Is_AutoInfer: true */
onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply::NetworkError error, QNetworkReply* reply); Is_AutoInfer: true */
onError_QString_QNetworkReply_A_Poniter/* method: void function(QString errorString), QNetworkReply* reply); Is_AutoInfer: true */
};
explicit HttpResponse(QNetworkReply *parent, const QMultiMap<QString, QMap<QString, const QObject *> > &slotsMap);
virtual ~HttpResponse();
public slots:
void abort();
private slots:
void onFinished();
void onError(QNetworkReply::NetworkError error);
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
protected:
qint64 readData(char *data, qint64 maxlen);
void slotsMapOperation(QMultiMap<QString, QMap<QString, const QObject *> > &slotsMap);
signals:
void finished(QNetworkReply *reply);
void finished(QByteArray data);
void finished(QVariantMap map);
void error(QString errorString);
void error(QNetworkReply::NetworkError error);
void error(QString errorString, QNetworkReply *reply);
void error(QNetworkReply::NetworkError error, QNetworkReply *reply);
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private:
HttpResponse();
private:
QMultiMap<QString, QMap<QString, const QObject *> > m_slotsMap;
};
#endif // HTTP_RESPONSE_H
(1) HttpResponse看起来复杂,但实际用户用得不多,主要用于HttpRequest类的使用.用户使用需要关注这个SupportMethod枚举即可
enum SupportMethod {
AutoInfer,
onResponse_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply* reply); Is_AutoInfer: true */
onResponse_QByteArray, /* method: void function(QByteArray data); Is_AutoInfer: true */
onResponse_QVariantMap, /* method: void function(QVariantMap map); Is_AutoInfer: true */
onDownloadProgress_qint64_qint64, /* method: void function(qint64 bytesReceived, qint64 bytesTotal); Is_AutoInfer: true */
onError_QNetworkReply_To_NetworkError, /* method: void function(QNetworkReply::NetworkError error); Is_AutoInfer: true */
onError_QString, /* method: void function(QString errorString); Is_AutoInfer: true */
onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply::NetworkError error, QNetworkReply* reply); Is_AutoInfer: true */
onError_QString_QNetworkReply_A_Poniter/* method: void function(QString errorString, QNetworkReply* reply); Is_AutoInfer: true */
};
(2)SupportMethod枚举用于HttpRequest类的onResponse的槽函数的参数使用,这里值得注意的是onResponse的最后一个参数type,该作用用于标识槽函数参数的类型是什么,如果Is_AutoInfer: true为真,则第三个参数不需要填写即可自动推导.这里描述得有点抽象但后续文章会重点写到,有兴趣的可以关注一下.
HttpRequest &onResponse(const QObject *receiver, const char *slot, HttpResponse::SupportMethod type)