Qt封装Http请求工具类

发布时间 2024-01-03 15:58:30作者: 飘杨......

一、概述

  封装一个HttpUtils工具类,此列封装了Qt的Http请求。总共封装了两个方法Get和Post方法。

二、代码示例

  1.工具类:HttpUtils.h/HttpUtils.cpp

#pragma once

#include <QObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QString>
#include <QMap>
#include <functional>
#include "CacheUtils.h"


//Qt的Http请求的工具类
class HttpUtils : public QObject
{
    Q_OBJECT

public:
    HttpUtils(QObject *parent);
    ~HttpUtils();
public:
    void post(QString url,QMap<QString,QString> param, QMap<QString, QString> headers, std::function<void(int, int, QString, QJsonObject)> onResponseResult);
    void get(QString url,  QMap<QString, QString> headers, std::function<void(int, int, QString, QJsonObject)> onResponseResult);
};

  HttpUtils.cpp

#include "HttpUtils.h"

HttpUtils::HttpUtils(QObject* parent)
    : QObject(parent)
{

}


void HttpUtils::get(QString url, QMap<QString, QString> headers, std::function<void(int, int, QString, QJsonObject)> onResponseResult) {
    //http请求
    QNetworkRequest request;//用于设置请求参数,如:请求头、请求URL等
    QNetworkAccessManager nam;//用于发起网络请求,如POST、GET
    //由于请求发生重定向,所以要加上这行代码,设置自动跳转,否则会返回 302
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    request.setUrl(url);
    connect(&nam, &QNetworkAccessManager::finished, this, [=](QNetworkReply* reply) {//自定义槽函数用于接收网络请求完成后的数据
        //获取Http请求响应状态码
        QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        if (statusCode.isValid()) {
            qDebug() << "Http请求状态码 = " << statusCode.toInt();
        }
        //获取响应源语
        QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
        if (reason.isValid()) {
            qDebug() << "Http请求响应源语=" << reason.toString();
        }

        //网络请求错误
        QNetworkReply::NetworkError err = reply->error();
        QByteArray res = reply->readAll();
        QJsonObject doc = QJsonDocument::fromJson(res).object();
        if (err == QNetworkReply::NoError) {//表示网络请求没有错误
            QString ip = doc.value("ip").toString();
            int code = doc.value("code").toInt();
            QString message = doc.value("message").toString();
            qDebug() << "IP地址:" << ip;
            qDebug() << "code:" << code;
            qDebug() << "message:" << message;
            if (code == 200) {//请求正常输出token的值,存储本地,然后表示登录成功
                QJsonObject mData = doc.value("data").toObject();
                QString token = mData.value("key").toString();
                CacheUtils::getInstance().setToken(token);
                qDebug() << "token:" << token;
                //QMessageBox::information(this, "信息", "token的值为" + token);
            }
            else {
                //QMessageBox::critical(this, "错误", message);
            }
            onResponseResult(statusCode.toInt(), code, message, doc);
            //QString 
            qDebug() << "输出网络请求的整体响应结果:" << res << endl;
        }
        else {
            qDebug() << "网络请求发生异常";
            onResponseResult(statusCode.toInt(), -1, reason.toString(), doc);
        }

        //请求完成后释放reply对象
        reply->deleteLater();
        });
    //设置网络请求的URL
    request.setUrl(QUrl(url));

    //请求头token设置
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json; charset=UTF-8"));
    for (auto& pair : headers.toStdMap()) {
        request.setRawHeader(pair.first.toStdString().c_str(), pair.second.toStdString().c_str());
    }
    qDebug() << "请求方式:Get";
    QNetworkReply* reply = nam.get(request); //post请求头+传输的数据

    //开启事件循环,直到请求完成
    QEventLoop loop;
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();
}

//http://192.168.100.12:8384/aic-user/sso/login
void HttpUtils::post(QString url, QMap<QString, QString> param, QMap<QString, QString> headers,
    std::function<void(int, int, QString, QJsonObject)> onResponseResult) {
    //http请求
    QNetworkRequest request;//用于设置请求参数,如:请求头、请求URL等
    QNetworkAccessManager nam;//用于发起网络请求,如POST、GET
    //准备登录数据:用户名和密码,并存入JSONObject中
    QJsonObject dataObj;
    for (auto& pair : param.toStdMap()) {
        dataObj.insert(pair.first, pair.second);
    }

    //将数据存入json文档
    QJsonDocument document;
    document.setObject(dataObj);
    //转换成QByteArray方便下面使用
    QByteArray byteArray = document.toJson(QJsonDocument::Compact);//类型转换

    connect(&nam, &QNetworkAccessManager::finished, this, [=](QNetworkReply* reply) {//自定义槽函数用于接收网络请求完成后的数据
        //获取Http请求响应状态码
        QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        if (statusCode.isValid()) {
            qDebug() << "Http请求状态码 = " << statusCode.toInt();
        }
        //获取响应源语
        QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
        if (reason.isValid()) {
            qDebug() << "Http请求响应源语=" << reason.toString();
        }

        //网络请求错误
        QNetworkReply::NetworkError err = reply->error();
        QByteArray res = reply->readAll();
        QJsonObject doc = QJsonDocument::fromJson(res).object();
        if (err == QNetworkReply::NoError) {//表示网络请求没有错误
            QString ip = doc.value("ip").toString();
            int code = doc.value("code").toInt();
            QString message = doc.value("message").toString();
            qDebug() << "IP地址:" << ip;
            qDebug() << "code:" << code;
            qDebug() << "message:" << message;
            if (code == 200) {//请求正常输出token的值,存储本地,然后表示登录成功
                QJsonObject mData = doc.value("data").toObject();
                QString token = mData.value("key").toString();
                CacheUtils::getInstance().setToken(token);
                qDebug() << "token:" << token;
                //QMessageBox::information(this, "信息", "token的值为" + token);
            }
            else {
                //QMessageBox::critical(this, "错误", message);
            }
            onResponseResult(statusCode.toInt(), code, message, doc);
            //QString 
            qDebug() << "输出网络请求的整体响应结果:" << res << endl;
        }
        else {
            qDebug() << "网络请求发生异常";
            onResponseResult(statusCode.toInt(), -1, reason.toString(), doc);
        }

        //请求完成后释放reply对象
        reply->deleteLater();
        });
    //设置网络请求的URL
    request.setUrl(QUrl(url));

    //请求头token设置
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json; charset=UTF-8"));
    for (auto& pair : headers.toStdMap()) {
        request.setRawHeader(pair.first.toStdString().c_str(), pair.second.toStdString().c_str());
    }
    qDebug() << "请求头:";
    qDebug() << "请求内容:" << byteArray.toStdString().c_str();
    qDebug() << "请求方式:Post";
    QNetworkReply* reply = nam.post(request, byteArray); //post请求头+传输的数据

    //开启事件循环,直到请求完成
    QEventLoop loop;
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();
}

HttpUtils::~HttpUtils()
{
}

  2.使用上述工具类做一个登录和获取用户信息的功能

  LoginWindow.h

#pragma once

#include <QWidget>
#include "../../common/edittext/EditText.h"
#include "../../common/button/Button.h"
#include <QMessageBox>
#include "utils/HttpUtils.h"
#include <QFormLayout>

class LoginWindow : public QWidget
{
    Q_OBJECT

public:
    LoginWindow(QWidget *parent = nullptr);
    ~LoginWindow();
    void login(QString username, QString password);
    void getUserInfo();

private:
    EditText* etUserName;
    EditText* etPassword;
    Button* btnLogin;
    HttpUtils *httpUtils;
};

  LoginWindow.cpp

#include "LoginWindow.h"

LoginWindow::LoginWindow(QWidget* parent)
    : QWidget(parent)
{
    httpUtils = new HttpUtils(this);
    this->setWindowTitle("登录");
    etUserName = new EditText(this);
    etUserName->setPlaceholderText("请输入用户名");
    etPassword = new EditText(this);
    etPassword->setPlaceholderText("请输入密码");
    btnLogin = new Button(this);
    btnLogin->setText("登录");

    QFormLayout* formLayout = new QFormLayout(this);
    formLayout->addRow(tr("用户名:"), etUserName);
    formLayout->addRow(tr("密   码:"), etPassword);
    formLayout->addRow(btnLogin);
    //formLayout->setMargin(50);
    formLayout->setVerticalSpacing(20);
    formLayout->setContentsMargins(50, 50, 50, 200);
    this->setLayout(formLayout);
    connect(btnLogin, &Button::clicked, [=]() {
        const QString username = etUserName->text();
        const QString password = etPassword->text();
        if (username.isEmpty()) {
            QMessageBox::warning(this, "温馨提示", "用户名不能为空");
        }
        else if (password.isEmpty()) {
            QMessageBox::warning(this, "温馨提示", "用户密码不能为空");
        }
        else {
            login(QString(username), QString(password));
        }


        });
}

void LoginWindow::login(QString username, QString password) {
    QMap<QString, QString> param;
    param.insert("username", username);
    param.insert("password", password);
    QMap<QString, QString> headers;
    headers.insert("Authorization", "");
    headers.insert("appVersion", "1.0.0");
    headers.insert("apiVersion", "1.0");
    headers.insert("channel", "android");
    headers.insert("deviceType", "2");
    headers.insert("deviceCode", "8f6f465f-e91d-4a97-8f4e-e6a410e4f0e7_android_1702617469162");
    headers.insert("deviceName", "LNA-AL00");
    httpUtils->post("http://192.168.10.12:8080/xxxxx/xxx/login", param, headers, 
        [=](int statusCode, int code, QString msg, QJsonObject result) {
        if (code == 200) {
            QMessageBox::critical(this, "提示", "登录成功");
            getUserInfo();
        }
        else {
            QMessageBox::critical(this, "提示", "登录失败");
        }
        });
}

//根据token获取用户信息
void LoginWindow::getUserInfo() {
    QMap<QString, QString> headers;
    headers.insert("Authorization", "Bearer " + CacheUtils::getInstance().getToken());
    headers.insert("appVersion", "1.0.0");
    headers.insert("apiVersion", "1.0");
    headers.insert("channel", "android");
    headers.insert("deviceType", "2");
    headers.insert("deviceCode", "8f6f465f-e91d-4a97-8f4e-e6a410e4f0e7_android_1702617469162");
    headers.insert("deviceName", "LNA-AL00");
    httpUtils->get("http://192.168.10.12:8080/xxxx/xxxx/detail", headers,
        [=](int statusCode, int code, QString msg, QJsonObject result) {
        if (code == 200) {
            QMessageBox::critical(this, "提示", "获取用户信息成功");
        }
        else {
            QMessageBox::critical(this, "提示", "获取用户信息失败");
        }
        });
}

LoginWindow::~LoginWindow()
{

}