文章目录
写在前面
关于服务器
本项目使用的是一个仿mudou库one-thread-one-loop式并发服务器的组件,关于该组件的细节内容在下面的链接中:
仿mudou库one-thread-one-loop式并发服务器
开源仓库和项目上线
本项目已开源到下面链接下的仓库当中
并且项目已经部署在了Linux服务器上,具体访问方式可以点击下面链接进行访问:
其他文档说明
针对于日志的信息,我采用了之前写的一份利用可变参数实现日志的代码,具体链接如下
这是一篇使用QT框架来实现一个配套与Boost搜索引擎的客户端的制作文档
登录界面
主体设计思路
首先设计一个简单的登陆界面
并且给对应的按钮提供对应的槽函数,如果验证成功了,就直接跳转到一个主页面
验证登录
下面是对于验证登录的逻辑,由于是连接到数据库的,所以这里需要用到网络通信,一个大体的思路就是把账号和密码提取出来,然后通过网络传输过去,在后端进行分析,再返回来,这里直接使用QT框架现成的Http部分
cpp
void Login::on_pushButton_login_clicked()
{
// 点击登录后先验证账号和密码
// 把账号和密码提取出来
const QString& username = ui->lineEdit_account->text();
const QString& password = ui->lineEdit_passwd->text();
sender(username, password);
}
void Login::sender(const QString &username, const QString &password)
{
// 1. 获取到输入框中的 URL, 构造 QUrl 对象
QUrl url(serverurl);
// 2. 构造 HTTP 请求对象,并设置请求头
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// 创建 JSON 文档并填充数据
QJsonObject jsonObject;
jsonObject["username"] = username;
jsonObject["password"] = password;
// 将 JSON 文档转换为 QByteArray
QJsonDocument jsonDoc(jsonObject);
QByteArray postData = jsonDoc.toJson();
// 3. 发送 POST 请求(这次包含JSON数据主体)
QNetworkReply* response = manager->post(request, postData);
// 4. 通过信号槽来处理响应
connect(response, &QNetworkReply::finished, this, [=]() {
if (response->error() == QNetworkReply::NoError)
{
// 响应正确
QString html(response->readAll());
qDebug() << "Response:" << html;
// 验证正确后跳转到对应界面
QMessageBox box(QMessageBox::Information, "提示", "登录成功", QMessageBox::Ok, this);
int ret = box.exec();
if(ret == QMessageBox::Ok)
{
this->close();
this->sig_mainwindow();
}
}
else
{
// 响应出错
QString error = response->errorString();
qDebug() << "Error:" << error;
qDebug() << "账号或密码错误";
int ret = QMessageBox::information(this, "提示", "账号或密码输入错误, 是否重新登录", QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
ui->lineEdit_passwd->clear();
else
this->close();
}
response->deleteLater();
});
}
至于验证登录的逻辑,这里不显示,因为这是后端已经完成的部分
注册功能
cpp
void Login::on_pushButton_register_clicked()
{
this->sig_register();
}
注册界面
这个界面也没什么好说的,和登录界面的逻辑基本一样,只是调用服务端的API即可
cpp
#include "register.h"
#include "ui_register.h"
#include <QMessageBox>
#include <QGridLayout>
#include <QString>
#include <QMessageBox>
#include <QJsonObject>
#include <QDebug>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
const QString& serverreq = "http://62.234.180.244:8081/register";
Register::Register(QWidget *parent) :
QDialog(parent),
ui(new Ui::Register)
{
ui->setupUi(this);
// 设置一下标题和图标
this->setWindowTitle("注册");
this->setWindowIcon(QIcon(QPixmap(":/imag/register.png")));
// 实例化对象
manager = new QNetworkAccessManager(this);
}
Register::~Register()
{
delete ui;
}
void Register::jump()
{
this->show();
}
void Register::on_pushButton_register_clicked()
{
// 点击注册后先验证账号和密码
// 把账号和密码提取出来
const QString& username = ui->lineEdit_account->text();
const QString& password = ui->lineEdit_passwd->text();
sender(username, password);
}
void Register::sender(const QString &username, const QString &password)
{
// 1. 获取到输入框中的 URL, 构造 QUrl 对象
QUrl url(serverreq);
// 2. 构造 HTTP 请求对象,并设置请求头
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// 创建 JSON 文档并填充数据
QJsonObject jsonObject;
jsonObject["username"] = username;
jsonObject["password"] = password;
// 将 JSON 文档转换为 QByteArray
QJsonDocument jsonDoc(jsonObject);
QByteArray postData = jsonDoc.toJson();
// 3. 发送 POST 请求(这次包含JSON数据主体)
QNetworkReply* response = manager->post(request, postData);
// 4. 通过信号槽来处理响应
connect(response, &QNetworkReply::finished, this, [=]() {
if (response->error() == QNetworkReply::NoError)
{
// 响应正确
QString html(response->readAll());
qDebug() << "Response:" << html;
// 验证正确后跳转到对应界面
QMessageBox box(QMessageBox::Information, "提示", "注册成功", QMessageBox::Ok, this);
int ret = box.exec();
if(ret == QMessageBox::Ok)
{
this->close();
}
}
else
{
// 响应出错
QString error = response->errorString();
qDebug() << "Error:" << error;
qDebug() << "用户名重复!";
int ret = QMessageBox::information(this, "提示", "用户名重复!是否重新注册", QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
ui->lineEdit_passwd->clear();
else
this->close();
}
response->deleteLater();
});
}
主体界面
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QGridLayout>
#include <QString>
#include <QMessageBox>
#include <QJsonObject>
#include <QDebug>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
#include <QJsonArray>
const QString& server_search = "http://62.234.180.244:8081/s";
const QString& server_hotwords = "http://62.234.180.244:8081/hotwords";
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 设置一下标题和图标
this->setWindowTitle("查找");
this->setWindowIcon(QIcon(QPixmap(":/imag/search.png")));
// 实例化对象
manager = new QNetworkAccessManager(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::jump()
{
this->show();
}
void MainWindow::on_pushButton_clicked()
{
// 当点击搜索按钮时,要传递一个/s请求
// 0. 获取到用户要搜索的关键字
const QString& user_search = ui->lineEdit_search->text();
// 1. 获取到输⼊框中的 URL, 构造 QUrl 对象
QUrl url(server_search);
// 2. 将用户搜索的关键字作为查询参数添加到URL中,构造 HTTP 请求对象
QUrlQuery query;
query.addQueryItem("word", user_search);
url.setQuery(query);
QNetworkRequest request(url);
// 3. 发送 GET 请求
QNetworkReply* response = manager->get(request);
// 4. 通过信号槽来处理响应
connect(response, &QNetworkReply::finished, this, [=]()
{
if (response->error() == QNetworkReply::NoError)
{
QString html(response->readAll());
displaySearchResults(html);
}
else
{
ui->plainTextEdit->setPlainText(response->errorString());
}
response->deleteLater();
});
// 点击搜索的时候也把热词统计显示出来
handle_hotwords();
}
void MainWindow::on_pushButton_2_clicked()
{
handle_hotwords();
}
void MainWindow::handle_hotwords()
{
// 当点击搜索按钮时,要传递一个/s请求
// 1. 获取到输⼊框中的 URL, 构造 QUrl 对象
QUrl url(server_hotwords);
// 2. 将用户搜索的关键字作为查询参数添加到URL中,构造 HTTP 请求对象
QNetworkRequest request(url);
// 3. 发送 GET 请求
QNetworkReply* response = manager->get(request);
// 4. 通过信号槽来处理响应
connect(response, &QNetworkReply::finished, this, [=]()
{
if (response->error() == QNetworkReply::NoError)
{
QString html(response->readAll());
displayHotWords(html);
}
else
{
ui->plainTextEdit_2->setPlainText(response->errorString());
}
response->deleteLater();
});
}
void MainWindow::displaySearchResults(const QString &jsonData)
{
QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
if (!doc.isArray())
{
ui->plainTextEdit->setPlainText("解析结果错误,不是有效的JSON数组");
return;
}
QStringList formattedResults;
const QJsonArray results = doc.array();
for (const QJsonValue &result : results)
{
if (result.isObject())
{
const QJsonObject obj = result.toObject();
QString title = obj["title"].toString();
QString desc = obj["desc"].toString();
QString url = obj["url"].toString();
QString line = QString("%1\n%2\n%3\n").arg(title, desc, url);
formattedResults.append(line);
// formattedResults.append("\n");
}
}
ui->plainTextEdit->setPlainText(formattedResults.join("\n"));
}
void MainWindow::displayHotWords(const QString &jsonData)
{
QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
if (!doc.isObject())
{
ui->plainTextEdit_2->setPlainText("解析结果错误,不是有效的JSON对象");
return;
}
QJsonObject jsonObj = doc.object();
if (!jsonObj.contains("hotWords") || !jsonObj["hotWords"].isArray())
{
ui->plainTextEdit_2->setPlainText("未找到或'hotWords'不是数组");
return;
}
const QJsonArray hotWordsArray = jsonObj["hotWords"].toArray();
QStringList formattedHotWords;
for (const QJsonValue &wordObj : hotWordsArray)
{
if (wordObj.isObject())
{
QJsonObject word = wordObj.toObject();
int count = word["count"].toInt();
QString wordStr = word["word"].toString();
QString line = QString("%1 :%2次\n").arg(wordStr, QString::number(count));
formattedHotWords.append(line);
}
}
// 添加分隔符或自定义样式后,设置到plainTextEdit中
ui->plainTextEdit_2->setPlainText(formattedHotWords.join("\n"));
}
main函数中绑定槽函数
cpp
#include "mainwindow.h"
#include "login.h"
#include "register.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Login log;
log.show();
MainWindow mainwindow;
Register registerPage; // 创建Register类的实例
// 建立两个槽,一个跳转到mainwindow,一个跳转到register
QObject::connect(&log, &Login::sig_mainwindow, &mainwindow, &MainWindow::jump);
QObject::connect(&log, &Login::sig_register, ®isterPage, &Register::jump); // 修正接收对象为registerPage实例
return a.exec();
}