用Qt实现基于网络请求的用户登录(二)

来源:互联网 发布:数据脱敏的主要方法 编辑:程序博客网 时间:2024/05/24 03:43

上一篇文章介绍了在Qt中与网络请求相关的类,以及在Qt中生成和解析Json。这一篇文章,将基于实例展示如何应用这些类实现网络请求,以及Json的生成和解析体现在哪里。
先回顾一下需要解决的问题:

  • 问题:用户联网登录

    1.提供登录界面(客户端),输入用户名和密码;
    2.将用户名和密码发送给服务器端,并进行相关查询,如果用户合法,返回用户信息;
    3.对返回的用户信息进行解析。

  • 假设:
    已经有了服务器和存储着用户名和密码数据库。服务器当接收到客服端的请求的时候,先在数据库中进行查询操作,然后返回用户信息。
    其中,客户端与服务器进行通信用到的接口信息如下所示:

【url】 /xxx1/xxx2/
【请求方式】 post
【请求参数说明】
{“username”:6到15个字符, 数字和字母的组合,非空,唯一
“passwd”:6到20个字符,非空}
【样例说明】
{“passwd”:”123456”,”username”:”haha”}
【返回信息】
{“code”:84,”message”:”登陆失败,验证码输入错误”}
{“code”:4,”message”:”账号异常”}
{“code”:5,”message”:”密码错误”}
{“code”:6,”message”:”用户名不存在”}

一、客户端界面
这里写图片描述

二、实现步骤
1.生成QNetworkRequest对象,设置请求头、请求所用API所需实参、url等信息;
在这里根据请求方式是post还是get,请求所用API所需实参的设置分两种情况:
①manager.post(request,data)
其中data为形如

"data={"username": "haha","passwd": 123456}"

这样的QByteArray。
②manager.get(request)
参数直接在设置request的URL的时候设置(post要另设置URL):

request.setUrl(QUrl("http://xxx1/xxx2?username="+username+"&passwd="+passwd));

2.准备解析处理QNetworkReply的slot;
3.生成QNetworkAccessManager,发送request,并将返回来的reply委托给该slot处理(实现上就是一条connect语句)

三、代码实现
1.在.pro中添加netwotk模块
因为与网络请求相关的那些类在这个模块里面

QT       += core gui   //原来存在的QT       += network    //添加的

2.login.h文件

#ifndef LOGIN_H#define LOGIN_H#include <QMainWindow>#include <QtNetwork/QNetworkAccessManager>#include <QtNetwork/QNetworkRequest>#include <QtNetwork/QNetworkReply>namespace Ui {class Login;}class Login : public QMainWindow{    Q_OBJECTpublic:    explicit Login(QWidget *parent = 0);    ~Login();private slots:    void finishRequest(QNetworkReply*);  //处理reply的slot    void on_OKButton_clicked();private:    Ui::Login *ui;    QNetworkAccessManager manager;   //manager  相关注意点见后文    QNetworkRequest request;    //request };#endif // LOGIN_H

3.login.cpp

#include "login.h"#include "ui_login.h"#include <QMessageBox>#include <QByteArray>#include <QString>#include <QJsonDocument>#include <QJsonArray>#include <QJsonParseError>#include <QJsonValue>#include <QJsonObject>#include <QDebug>#include <iostream>Login::Login(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::Login){    ui->setupUi(this);}Login::~Login(){    delete ui;}void Login::on_OKButton_clicked(){    //获取用户名、密码    QString username = ui->usrLineEdit->text();    QString password = ui->pwdLineEdit->text();    if(username.isEmpty() || password.isEmpty())    {        QMessageBox::warning(this,"Warning","Username or password is empty!",QMessageBox::Yes);        ui->usrLineEdit->clear();        ui->pwdLineEdit->clear();    }    else{    //通过QJsonObject得到post需要的参数data, data形式为: "data={"username": "haha","passwd": 123456}"    QJsonObject json;    json.insert("username",username);    json.insert("passwd",password);    QJsonDocument document;    document.setObject(json);    QByteArray byte_array = document.toJson(QJsonDocument::Compact);    QByteArray data;    data.append("data="+byte_array);    //设置request    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");  //上面语句固定这么写,要不然会报错“contest—type is missing”    request.setRawHeader("XXX3", "XXX4");    request.setUrl(QUrl("http://xxx1/xxx2/"));  //"http:"不要少    //manager发送请求,并接收reply,委托给slot处理    manager.post(request,data);    connect(&manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishRequest(QNetworkReply*)));  }}void Login::finishRequest(QNetworkReply *reply){    if (reply->error()){            qDebug()<<"Error!"<<endl;    }else{            //解析reply中携带的Json            QByteArray byte_array = reply->readAll();  //Json ducument            QJsonParseError json_error;            QJsonDocument parse_document = QJsonDocument::fromJson(byte_array, &json_error);            if(json_error.error == QJsonParseError::NoError)            {                  if(parse_document.isObject())                  {                      QJsonObject obj = parse_document.object();                      if(obj.contains("code"))                      {                          QJsonValue code_value = obj.take("code");                          int code_value_int = code_value.toInt();                          if(code_value_int == 3)                          {                              QJsonValue message_value = obj.take("message");                              qDebug()<<message_value<<endl;  //输出:QJsonValue(string, "登录成功")                          }                          else                          {                              QJsonValue message_value = obj.take("message");                              qDebug()<< message_value<<endl;                              QString error_message = message_value.toString();                              QMessageBox::warning(this,"Error",error_message,QMessageBox::Yes);                              ui->usrLineEdit->clear();                              ui->pwdLineEdit->clear();                          }                    }               }           }    }     reply->deleteLater();}

四、实现时遇到的问题

1.试图直接生成Json document
post(request,data)请求中所用到的data为形如

"data={"username": "haha","passwd": 123456}"

的Json document,由于是一QByteArray的形式保存的,所以就想着能不能直接生成这样的QByteArray,从而绕过QJsonObject、 QJsonDocument, 实验结果是不可以。

 //想通过QByteArray直接生成Json document,结果是不可以    QByteArray data;    data.append("username="+username);    data.append("passwd="+password);

2.将manager 和 request设为了全局变量
在这个例子中,只有一次网络请求,因此看不出这样做有什么问题。但是,当程序中有好几个网络请求的时候,这些网络请求共用一套manager和request,就会出现问题了。因为connect语句,只要manager接收到reply,就会触发所有connect语句,所有的解析Json的slot都有可能被委托到。这样就会出现,为什么我发出网络请求的是第二部分,却会是第一部分的slot有所反应= =
如果一开始使用的是全局变量,简单地将用到全局变量manager 和 request的地方改为局部变量

    QNetworkAccessManager manager1;    QNetworkRequest request1;

出现的结果是,根本就没有网络请求成功的迹象。应该使用指针:

    QNetworkAccessManager *manager1 = new QNetworkAccessManager();    QNetworkRequest *request1= new QNetworkRequest();

原因参看:http://bbs.csdn.net/topics/391077810
但如果并不是由全局变量改为局部变量,采用第一种方式好像不会有什么问题。


参考资料:

网络请求基础相关:
Qt中网络请求相关类相关:
Qt实现网络数据传输: http://blog.sina.com.cn/s/blog_a6fb6cc90101fg0i.html
Post与get的区别: http://www.cnblogs.com/findumars/p/5574299.html
Qt网络编程之实例一GET方式: http://blog.csdn.net/chenlong12580/article/details/7392766
解决finished信号无法触发槽函数是看到的:
QNetworkAccessManager的finished信号无法触发槽函数: http://bbs.csdn.net/topics/391077810
QNetworkAccessManager : https://tieba.baidu.com/p/4089426961

Json相关:
Qt之JSON生成与解析: http://blog.sina.com.cn/s/blog_a6fb6cc90101gnxm.html
Json教程:http://www.w3school.com.cn/json/index.asp
http://www.w3school.com.cn/json/json_syntax.asp

阅读全文
0 0
原创粉丝点击