【C++ QT项目实战-02】---- C++ QT系统实现基于QT调用RESTful接口访问JSON文件中数据

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页@一伦明悦-CSDN博客

✍🏻 作者简介C++软件开发、Python机器学习爱好者

🗣️ 互动与支持💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论!

欢迎点赞加收藏支持我,点击关注,一起进步!


目录

前言

正文

01-RESTful架构简介

02-QT中实现调用RESTful接口的类的介绍

(1)QT简介         

(2)QT中类的简介

(3)QT调用RESTful 接口步骤

03-系统实现调用RESTful接口代码介绍

(1)dialog_con.h文件解释  

(2)dialog_con.cpp文件解释

 04-C++ QT项目系统功能演示

总结


前言

         本篇在做项目的基础上进行了项目中难点的一些总结,我们都知道,在如今大数据时代下,数据对项目系统开发起到决定性的作用,可以帮助企业实现实时决策、提升用户体验、实现业务智能、提高系统性能、提供定制化服务和增强业务竞争力等方面的优势,有利于项目系统的发展和成功。因此,在项目系统开发过程中,需要充分重视数据的快速读取和处理能力,以满足日益增长的数据需求和用户期望。

        当然数据可以有多种的文件存储方式,比如JSON文件,CSV 文件,XML 是一种标记语言,用于存储和传输数据,Excel文件等等,对于各行各业来说,都会采用最适合自己的存储方式,因此,项目开发中的系统也就需要满足企业需要,对企业选定的存储文件进行访问,读取所需数据。

        本文是在项目中开发过程需要访问JSON格式的数据文件,项目系统基于C++ QT混合编程语言完成,因此,这里介绍一下完成这项功能时的一些难点,附上代码和运行过程解释。

正文

01-RESTful架构简介

         REST(英文:Representational State Transfer,简称REST,直译过来表现层状态转换)是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

        它首次出现在 2000 年 Roy Thomas Fielding 的博士论文中,这篇论文定义并详细介绍了表述性状态转移(Representational State Transfer,REST)的架构风格,并且描述了 如何使用 REST 来指导现代 Web 架构的设计和开发。用他自己的原话说:

        我写这篇文章的目的是:在符合架构原理前提下,理解和评估基于网络的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构

        REST是一种基于网络标准和 HTTP 协议的架构风格,用于设计分布式系统。它是一种轻量级、灵活的通信方式,强调资源的概念和统一的接口设计,符合 RESTful 架构的应用程序易于扩展、简单快捷。

        以下是 RESTful 架构的几个核心概念:

        资源(Resources):在 RESTful 架构中,每个可访问的信息单元都被视为一个资源。资源可以是任何可命名的实体,如文档、图像、服务等。每个资源都有唯一的标识符(URI)用于定位和访问。

        统一接口(Uniform Interface):RESTful 架构要求使用统一的接口对资源进行操作,包括对资源的创建、读取、更新和删除(CRUD)。常用的 HTTP 方法(GET、POST、PUT、DELETE)与资源的操作相对应。

        状态的表述性(Stateless):RESTful 服务端不会保存客户端状态,每个请求都包含了足够的信息进行处理。服务端无需记录客户端的状态,这样可以更好地实现系统的可伸缩性和容错性。

        自描述消息(Self-descriptive Messages):RESTful 架构使用标准的媒体类型(如 JSON、XML)来表示资源的信息,使客户端和服务器能够理解和处理资源的表述形式。

        超媒体驱动(Hypermedia Driven):RESTful 架构鼓励使用超媒体链接(如超文本链接)来为客户端提供资源的相关信息和操作链接,实现动态发现和关联性。

        下面对统一接口(Uniform Interface)概念详细解释一下:

        当讨论 RESTful 架构中的统一接口时,可以通过一个架构图形象地解释。以下是一个简单的 RESTful 架构图说明,展示了资源的 URI 和常用的 HTTP 方法,以及与 CRUD 操作相对应的请求和响应示例:

        说明

        客户端(Client):表示发起请求的用户或系统。

        资源服务器(Resource Server):表示存放资源的服务器端。

        URI(Uniform Resource Identifier):表示资源的唯一标识符。        

        HTTP 方法

                GET:用于获取资源的信息,对应查询操作。

                POST:用于创建新资源,对应创建操作。

                PUT:用于更新已有资源,对应更新操作。

                DELETE:用于删除资源,对应删除操作。

        请求和响应示例

                GET 请求 /api/books 返回所有书籍信息。

                POST 请求 /api/books 添加新书籍。

                PUT 请求 /api/books/123 更新特定书籍。

                DELETE 请求 /api/books/123 删除特定书籍。

                HTTP 状态码(例如 200、201、204)和响应数据格式(如 JSON)。

        这里清晰地展示了 RESTful 架构中的统一接口设计原则,通过使用统一的 HTTP 方法和资源的 URI 对资源进行操作。客户端通过向服务器发送不同的 HTTP 请求来实现对资源的创建、读取、更新和删除,从而实现了系统的简洁性、可扩展性和易用性。

        通过遵循 RESTful 架构的统一接口设计原则,开发人员可以更容易地构建符合标准的 API,使系统的接口更易于理解和维护,同时提供更好的互操作性和用户体验。

        下面是一个简单的示例代码,用 Python 的 Flask 框架实现一个简单的 RESTful API:在这个示例中,/books 是资源的 URI,GET 方法用于获取书籍列表,POST 方法用于添加新书籍。客户端可以发送 HTTP 请求来访问资源并执行相应的操作。

from flask import Flask, jsonify, request

app = Flask(__name__)
books = []

# 获取所有书籍
@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)

# 添加新书籍
@app.route('/books', methods=['POST'])
def add_book():
    data = request.get_json()
    books.append(data)
    return jsonify({'message': 'Book added successfully'})

if __name__ == '__main__':
    app.run()

02-QT中实现调用RESTful接口的类的介绍

(1)QT简介         

        Qt 是一个跨平台的 C++ 应用程序开发框架,最初由挪威的 Trolltech 公司开发,现由 Digia 公司维护。Qt 提供了一套完整的工具和库,使开发人员能够轻松地构建图形用户界面(GUI)、网络应用程序、嵌入式应用程序等各种类型的应用程序。

        以下是 Qt 框架的一些主要特点和组件:

        跨平台支持:Qt 提供了一致的 API,能够在多个操作系统上运行,包括 Windows、macOS、Linux、Android 等。开发人员可以使用相同的代码库开发跨平台的应用程序。

        GUI 开发:Qt 提供了丰富的 GUI 类库,包括 QWidget、QML、Qt Quick 等,以及用户友好的设计器工具,使开发人员可以轻松地创建现代化的用户界面。

        网络和通信:Qt 包含了网络模块,如 QNetworkAccessManager,用于处理网络请求和通信。同时也支持 WebSockets、TCP/IP、UDP 等网络通信协议。

        数据库支持:Qt 提供了跨平台的数据库访问类,如 QSqlDatabase,可以和主流的数据库系统(如 MySQL、SQLite、PostgreSQL)进行集成。

        图形和多媒体:Qt 支持图形渲染、图像处理和多媒体功能,开发人员可以轻松地处理图形、音频和视频数据。

        跨平台部署工具:Qt 提供了一套工具链,包括 Qt Creator 集成开发环境、Qt Installer Framework 等,能够帮助开发人员打包和部署应用程序到不同的平台。

        开源社区支持:Qt 拥有活跃的开源社区,不仅提供了大量的文档、示例和第三方库,还有专门的邮件列表和论坛,开发人员可以在社区中获取支持和交流经验。

        总的来说,Qt 是一个功能强大、跨平台且易于学习的应用程序开发框架,适用于各种类型的应用程序开发,无论是桌面应用、移动应用、嵌入式应用还是其他类型的应用。开发人员可以通过 Qt 快速构建高质量的应用程序,并轻松地将其部署到不同的平台上。

(2)QT中类的简介

        当涉及到使用 Qt 进行网络访问和 JSON 数据处理时,QNetworkAccessManager 和 QJsonDocument 是两个重要的类。

        QNetworkAccessManager

        介绍:QNetworkAccessManager 是 Qt 提供的网络请求和响应管理类,用于处理网络通信。通过 QNetworkAccessManager,可以发送 HTTP 请求、处理响应,并管理网络请求的会话。

        功能:发送 GET、POST、PUT、DELETE 等 HTTP 请求。支持同步和异步网络操作。提供自定义请求头、身份验证和代理设置。支持重定向和 Cookie 管理。

        示例代码:以下是一个简单的示例代码,使用 QNetworkAccessManager 发送 HTTP GET 请求并处理响应:

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply *reply = manager->get(QNetworkRequest(QUrl("https://jsonplaceholder.typicode.com/posts/1")));
connect(reply, &QNetworkReply::finished, [=](){
    if(reply->error() == QNetworkReply::NoError){
        QByteArray responseData = reply->readAll();
        qDebug() << "Response data: " << responseData;
    }
    reply->deleteLater();
});

        QJsonDocument

        介绍:QJsonDocument 是 Qt 提供的 JSON 数据处理类,用于解析和生成 JSON 数据。通过 QJsonDocument,可以方便地读取和修改 JSON 数据。

        功能:将 JSON 数据转换为 QVariant 对象以便读取。将 QVariant 对象转换为 JSON 数据以便输出。支持从 JSON 字符串、二进制、以及 QJsonObject、QJsonArray 等类型创建 QJsonDocument 对象。

        示例代码:以下是一个简单的示例代码,使用 QJsonDocument 解析 JSON 数据:

QByteArray json = "{\"key\":\"value\"}";
QJsonDocument jsonDoc = QJsonDocument::fromJson(json);
if(!jsonDoc.isNull() && jsonDoc.isObject()){
    QJsonObject jsonObj = jsonDoc.object();
    QString value = jsonObj["key"].toString();
    qDebug() << "Value: " << value;
}

        通过使用 QNetworkAccessManager 和 QJsonDocument,开发人员可以方便地实现网络请求和 JSON 数据处理的功能,从而与远程服务器进行通信、获取数据和处理 JSON 数据。这两个类为 Qt 应用程序的网络通信和数据处理提供了强大的支持。       

(3)QT调用RESTful 接口步骤

        在 C++ 中使用 Qt 框架来调用 RESTful 接口并访问 JSON 文件中的数据通常需要以下步骤:

        创建Qt项目:首先需要创建一个 Qt 项目,确保项目中包含了网络模块,可以通过 Qt Creator 创建一个新的 Qt 控制台应用程序。

        发送HTTP请求:使用 Qt 的 QNetworkAccessManager 类来发送 HTTP 请求。通过创建一个 QNetworkRequest 对象,设置请求的 URL、请求头等信息,然后使用 QNetworkAccessManager 发送该请求。

        处理响应:在发送请求后,Qt 的 QNetworkAccessManager 会发送信号来处理响应。在收到响应后,可以读取 JSON 数据并进行处理。

        解析JSON:Qt 提供了 QJsonDocument 类来解析和操作 JSON 数据。可以使用 QJsonDocument::fromJson() 方法将接收到的 JSON 字符串转换为 QJsonDocument 对象,然后通过该对象获取 JSON 数据中的内容。

        处理数据:一旦获得了 JSON 数据,你可以根据需要提取其中的数据并进行进一步处理,例如显示到界面上或者进行其他业务逻辑操作。

        错误处理:在实际应用中,需要考虑网络请求失败、JSON 解析错误等异常情况的处理,确保程序的稳定性和可靠性。

         这是一个简单的示例代码,演示了如何在 C++ 中使用 Qt 访问 RESTful 接口并读取 JSON 数据:

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QNetworkAccessManager manager;
    QNetworkRequest request(QUrl("https://api.example.com/data"));
    QNetworkReply *reply = manager.get(request);

    QObject::connect(reply, &QNetworkReply::finished, [&](){
        if(reply->error() == QNetworkReply::NoError){
            QByteArray response = reply->readAll();
            QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
            QJsonObject jsonObject = jsonDoc.object();
            
            // 处理 JSON 数据
            // 例如:打印所有键值对
            for(auto it = jsonObject.begin(); it != jsonObject.end(); ++it){
                qDebug() << it.key() << ":" << it.value();
            }
        } else {
            qDebug() << "Network request failed: " << reply->errorString();
        }

        // 释放资源
        reply->deleteLater();
    });

    return a.exec();
}

03-系统实现调用RESTful接口代码介绍

       下面给出项目实现基于QT调用RESTful接口的代码,演示过程下一小节进行,这里仅对代码进行详细解释,代码分为两部分,首先是dialog_con.h通信的.h文件,后面是dialog_con.cpp通信的.cpp文件,代码解释如下:

        (1)dialog_con.h文件解释  

        这段 C++ Qt 代码主要定义了一个名为 Dialog_con 的类,这个类继承自 QDialog,并包含了一些成员变量、成员函数以及信号与槽函数。代码解释如下:

  1. 头文件包含部分

    • 通过 #pragma once 和 #ifndef...#endif 语句来确保头文件只被包含一次,避免重复定义。
    • 包含了一系列需要使用的头文件,例如 Qt 相关的头文件、第三方库的头文件等。
  2. 命名空间

    • 使用 namespace Ui 包含了一个名为 Dialog_con 的类的声明。
  3. Dialog_con 类

    • 公有成员函数:定义了类的公有成员函数,例如构造函数、析构函数以及处理网络请求的函数。
    • 成员变量:定义了一系列成员变量,包括各种配置信息、JSON 数据解析相关的变量,以及结构体 hdgl_predict_data 和其他结构体变量。
    • 私有成员函数:定义了一些私有函数用于处理内部逻辑,如解析 JSON 数据、将字节转换为浮点数等。
    • 槽函数:定义了一系列槽函数,对应不同的按钮点击事件,如发送 GET 请求、发送 POST 请求、配置参数等。
    • 信号:定义了一个信号 showmain(),可以在需要时发射信号。
  4. 结构体

    • 定义了一个名为 hdgl_predict_data 的结构体,包含了预测数据的各个字段。
    • 其他结构体变量用于存储不同类型的测量数据。
  5. 函数实现

    • 实现了一些函数,包括将字节数组转换为浮点数、解析 JSON 数据等功能。
    • 实现了各个按钮点击事件的处理函数,如返回主菜单、退出登录等。
    • 实现了读取配置信息的函数。

        总体而言,这段代码主要实现了一个用于与 PLC 进行通信和处理数据的对话框类。其中包括了网络请求、数据解析、按钮点击事件处理等功能。每个成员变量和函数都承担着不同的功能,以实现对话框类的各种操作和逻辑。

#pragma once
#ifndef DIALOG_CON_H
#define DIALOG_CON_H
#include "ui_dialog_login.h"
//#include "ui_mainwindow.h"
//#include "ui_MainWindow1.h"
#include "dialog_con.h"
#include "ui_Dialog_con.h"

//#include "MainWindow1.h"

#include <QTimer>
#include <QTime>
#include "snap7.h"

#include <QDialog>
#include <QAbstractButton>
#include <QPushButton>
#include "mainwindow.h"
#include"ui_mainwindow.h"

// #include <QtWidgets/QMainWindow>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonDocument>


enum MyMethod
{
	GET,
	POST
};


namespace Ui {
	class Dialog_con;

}

class Dialog_con : public QDialog
{
	Q_OBJECT


public:
	explicit Dialog_con(QWidget *parent = 0);
	~Dialog_con();

	void SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult);

public:
	int query_step = 1000;
	int heartbeat;


	QString clientID, clientSecret, serverIP, serviceID_get, serviceID_post, user_ID, companyCode;

	QString name, unit;

	QString mssql_serverName, mssql_dbName, mssql_username, mssql_pwd, mssql_datasource;
	QString oraclexe_serverName, oraclexe_port, oraclexe_dbName, oraclexe_username, oraclexe_pwd;
	QJsonDocument json_doc_get;
	QJsonObject doc_get_Obj;


private:
	//MainWindow q;
	Ui::Dialog_con *ui;
	TS7Client *ptrPLC;
	QTimer *timer_PLC_hf = new QTimer(this);
	float ByteToFloat(unsigned char* byteArray);
	int Dialog_con::ByteToInt(unsigned char* byteArray);

	void json_doc_get_parse();

public slots:

    void OnGETSlot();
	void OnPOSTSlot();
	void OnconfigSlot();
	bool configuration_read();


private slots:
	//void on_login_ok_Btn_clicked();
	//void on_data_import_Btn_clicked(QAbstractButton *button);
	//void on_login_ok_Btn_clicked(QAbstractButton * button);
	//private slots:
//	void on_Btn_PLC_rw_check_clicked();
	void on_Btn_Ret_clicked();                   //返回主菜单
	void on_Btn_exit_clicked();                  //退出登入
//	void read_write_PLC();
signals: 
	/**
	* 信号必须要signals关键字来声明
	* 信号没有返回值, 但可以有参数
	* 信号就是函数的声明, 无需定义
	* 使用: emit mySignal();
	* 信号可以被重载
	*/
	//void showmain();

private:

	struct hdgl_predict_data   
	{
		QString hdgl_predict_id;
		QString ENTID; 
		QString ATIME;  
		QString ST_code;
		QString ST_grade;
		QString ST_source;
		QString cal_datetime;
		QString finish_datetime;

		 
		float CH_C;


	};   // 忘加分号




public:

	hdgl_predict_data strt_hdgl_predict;

	WFC_TEMP_MEASURE wfc_temp_measure;  // 
	WFC_FLATNESS_MEASURE wfc_flatness_measure;  //
	WFC_VALVE_FLOW_MEASURE wfc_valve_flow_measure; //
	WFC_COIL_PROCESS_INFO wfc_coil_process_info;  //
	WFC_VALVE_FLOW_PRESET wfc_valve_flow_preset;  //这里和子线程不一样

};


#endif // DIALOG_CON_H

(2)dialog_con.cpp文件解释

        这段代码主要是关于网络请求的处理,包括发送 POST 和 GET 请求,并处理返回的数据。下面是对每一行代码的解释:

   void Dialog_con::SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult): 定义了一个函数 SendAndGetText,接受URL、请求方法、输入参数、以及两个输出参数用于保存消息和结果。

   QNetworkRequest oNetRequest, post_NetRequest;: 声明了两个网络请求对象 oNetRequest 和 post_NetRequest

   QJsonObject json;: 声明一个 JSON 对象用于构建 JSON 数据。

   QJsonDocument document;: 声明一个 JSON 文档对象。

   QString cgl_result;: 声明一个字符串变量用于保存结果。

   QUrlQuery url_Query;: 声明一个 URL 查询对象。

   QString url_Request;: 声明一个字符串变量用于保存请求的 URL。

   oNetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);: 设置网络请求的属性,允许自动跟随重定向。

   post_NetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);: 设置另一个网络请求的属性,同样允许自动跟随重定向。

   QUrl url(strUrl);: 根据传入的 URL 字符串创建一个 URL 对象。

   bytes.append(QString("name=%1").arg(name));: 将数据添加到字节数组中。

   url_Query.addQueryItem("name", name);: 将查询参数添加到 URL 查询对象中。

   url.setQuery(url_Query);: 将查询参数设置到 URL 对象中。

   qDebug() << url;: 输出 URL 信息。

   oNetRequest.setUrl(url);: 设置一个网络请求的 URL。

   post_NetRequest.setUrl(url);: 设置另一个网络请求的 URL。

        接下来是一系列关于 JSON 数据处理的代码,包括构建 JSON 数据和设置请求的头部信息等。

   QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);: 创建一个用于发送表单数据的 HTTP 多部分对象。

        接下来是构建 POST 请求的具体数据部分,包括参数和内容的设置。

   QNetworkAccessManager oNetAccessManager;: 创建一个网络访问管理器对象。

   QNetworkReply* oNetReply = NULL;: 声明一个网络回复对象。

        根据请求方法(GET 或 POST)发送网络请求,并等待请求完成。

        处理请求完成后的相关逻辑,包括读取返回数据、处理错误信息等。

   void Dialog_con::OnPOSTSlot(): 定义了一个槽函数 OnPOSTSlot,用于处理 POST 请求。

   void Dialog_con::OnGETSlot(): 定义了一个槽函数 OnGETSlot,用于处理 GET 请求。

   file.write(json_doc_get.toJson(QJsonDocument::Indented));: 将获取到的 JSON 数据写入文件。

        以上是对代码中每一行的简要解释,涵盖了网络请求的发送和处理、JSON 数据的构建和解析等内容。

        接下来的这部分代码主要包括两个函数:json_doc_get_parse 和 extractJsonValue

        1. json_doc_get_parse 函数:

        这个函数用于解析 JSON 文档 json_doc_get 中的数据。

        首先判断 json_doc_get 是否为空,如果为空则记录错误信息;否则记录解析开始信息。

        接着判断 doc_get_Obj 中是否包含键名为 “Coil_first” 的对象。

        如果有,就获取该对象,并从中提取出特定的键值信息(如 aentid、atime、acode、agrade、asource、C 等)。

        使用 extractJsonValue 函数来提取 task_zone0_Obj 中的 “C_CH” 键对应的值,并将结果存储在变量 C 中。

        将提取的信息赋值给 strt_hdgl_predict 结构体中的对应成员变量,并更新 UI 上相关的文本框内容。

        2. extractJsonValue 模板函数:

        这是一个通用的模板函数,用于从 QJsonObject 对象中提取特定类型的值。

        参数包括一个 QJsonObject 对象和一个键名 key

        通过 obj[key] 获取对应键的值,然后通过 toVariant() 转换为 QVariant 类型,最后通过 value<T>() 转换为指定的类型 T 并返回。

        综上所述,json_doc_get_parse 函数用于解析 JSON 数据并更新 UI,而 extractJsonValue 函数则作为一个通用的值提取函数被调用。请注意,以上是根据提供的代码片段推断的解释,具体情况可能还需要参考其他相关代码来确定。

//#include "ui_MainWindow1.h"
#include "ui_dialog_pred_init.h"
#include "ui_dialog_data_log.h"
#include "ui_dialog_login.h"
//#include "ui_mainwindow.h"
#include "ui_dialog_pred_init.h"
#include "ui_dialog_data_log.h"
#include "ui_dialog_login.h"

#include "dialog_con.h"
#include "windows.h"
#include "qdebug.h"
#include <qstring.h>
#include "mainwindow.h"
#include"ui_mainwindow.h"
#pragma comment(lib,".\\lib\\fmtd.lib")

#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QUrlQuery>
#include <QHttpMultiPart>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include <QSysInfo>
#include <QSslSocket>

#include "spdlog/fmt/ostr.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include <memory>
#include <string>

#include <QTimer>
#include "snap7.h"


#include <QSqlError>
#include <QSqlDatabase>
#include <QSqlQuery>


#include "snap7.h"
#pragma comment(lib,"snap7.lib")
using namespace std::literals;
using namespace std;
namespace spd = spdlog;

auto console_con = spd::stdout_color_mt("Iplat4j大数据平台通讯测试");

auto rotating_logger_con = spdlog::rotating_logger_mt("baori_CA08_Iplat4j_chk_rotating", "logs/baori_CA08_rotating.logger", 1048576 * 5, 12);


Dialog_con::Dialog_con(QWidget *parent) :
	QDialog(parent),
	ui(new Ui::Dialog_con)
{
	ui->setupUi(this);
	setWindowTitle(QString::fromLocal8Bit("基础通信"));
	//configuration_read();
	connect(ui->Config_Btn, SIGNAL(clicked()), this, SLOT(OnconfigSlot()));
	connect(ui->GET_Btn, SIGNAL(clicked()), this, SLOT(OnGETSlot()));

}

Dialog_con::~Dialog_con()
{
	delete ui;
}


void Dialog_con::SendAndGetText(QString strUrl, MyMethod thod, QString strInput, QString &strMessage, QString &strResult)
{

	QNetworkRequest oNetRequest, post_NetRequest;
	QJsonObject json;
	QJsonDocument document;
	QString cgl_result;
	QUrlQuery url_Query;
	QString url_Request;

	oNetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //让Qt自动为你跳转
	post_NetRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //让Qt自动为你跳转

	QUrl url(strUrl);



	QByteArray bytes;
	bytes.append(QString("name=%1").arg(name));  // Qt 作为变量输入
	bytes.append(QString("unit=%1").arg(unit));  // Qt 作为变量输入
	url_Query.addQueryItem("name", name);
	url_Query.addQueryItem("unit", unit);

	url.setQuery(url_Query);

	//QUrl url(strUrl);
	qDebug() << url;

	oNetRequest.setUrl(url);
	post_NetRequest.setUrl(url);


	QByteArray dataArray;


	float THF = 100.0;
	cgl_result = "THF:" + QString::number(THF, 'f', 2);

	// Json数据提交
	json.insert("age", "25");
	json.insert("user", "APIInfo");


	document.setObject(json);

	dataArray = document.toJson(QJsonDocument::Compact);


	QHttpPart part_token;
	QHttpPart part_name, part_unit;
	QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

	part_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
	part_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"name\""));
	part_name.setBody(name.toUtf8());

	part_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
	part_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"unit\""));
	part_name.setBody(unit.toUtf8());

	multiPart->append(part_name);
	multiPart->append(part_unit);

	oNetRequest.setRawHeader("Content-Type", "application/json");
	post_NetRequest.setRawHeader("Content-Type", "application/json");

	QByteArray params;
	//QByteArray bodyData;

	QString tokenInfo = strInput;

	//tokenInfo = tokenInfo + ": ";
	QByteArray tokenData = tokenInfo.toLocal8Bit().toBase64();
	QString headerData = "Token " + tokenData;

	params.append("access_token=" + tokenInfo);
	params.append("access_token=");

	QString ss1 = strInput.toLocal8Bit();

	QNetworkAccessManager oNetAccessManager;
	QNetworkReply* oNetReply = NULL;
	QByteArray inputTmp;
	if (thod == POST)
	{
		
		oNetReply = oNetAccessManager.post(post_NetRequest, dataArray);
	}
	else if (thod == GET)
	{
		oNetReply = oNetAccessManager.get(oNetRequest);
	}

	QEventLoop loop;
	connect(oNetReply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	//记录httpCode
	int httpsCode = oNetReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

	QNetworkReply::NetworkError e = oNetReply->error();
	strResult = oNetReply->readAll();
	if (e)
	{
		strMessage = oNetReply->errorString();
		console_con->error("Iplat4j大数据平台连接失败[Dialog_con]!");
		
	}
	else 
	{
		console_con->info("http连接正常");

		console_con->info("Iplat4j大数据平台连接成功[Dialog_con]!");
		
	



	}
}
void Dialog_con::OnPOSTSlot()
{

	QString strMessage;
	QString strResult;
	QString strUrl;
	QString strInput;

	strUrl = serverIP + serviceID_post;
	strInput = clientSecret;

	SendAndGetText(strUrl, POST, strInput, strMessage, strResult);
	ui->Url_QLE->setText(strUrl);
	ui->ErrorMessage_QTE->setText(strMessage);
	ui->Result_QTE->setText(strResult);
}

void Dialog_con::OnGETSlot()
{
	QString strMessage;
	QString strResult;
	QString strUrl;
	QString strInput;
	QFile file(QApplication::applicationDirPath() + "/1.json");
	if (!file.open(QIODevice::WriteOnly)) {
		qDebug() << "File open failed!";
	}
	else {
		qDebug() << "File open successfully!";
	}


	strUrl = serverIP + serviceID_get;
	strInput = clientSecret;
	SendAndGetText(strUrl, GET, strInput, strMessage, strResult);

	QJsonParseError jsonError;
	QByteArray byteResult = strResult.toUtf8();//QString转QByteArray
											   //QJsonDocument json = QJsonDocument::fromJson(byteResult, &jsonError);
	json_doc_get = QJsonDocument::fromJson(byteResult, &jsonError);

	if (json_doc_get.isNull())
	{
		console_con->critical("json文件为空文档");
		
		rotating_logger_con->critical("json格式错误[json_doc_get_slot]");
		
	}
	else if (jsonError.error != QJsonParseError::NoError)
	{
		console_con->critical("json格式错误[json_doc_get_slot]" + jsonError.errorString().toStdString());
		//qDebug() << jsonError.errorString();
		rotating_logger_con->critical("json格式错误[json_doc_get_slot]");
	}
	else {
		if (json_doc_get.isObject()) {
			doc_get_Obj = json_doc_get.object();
		}
	}
	json_doc_get_parse();

	file.write(json_doc_get.toJson(QJsonDocument::Indented)); //Indented:表示自动添加/n回车符
	file.close();
	ui->Url_QLE->setText(strUrl);
	ui->ErrorMessage_QTE->setText(strMessage);
	ui->Result_QTE->setText(strResult);

}


// 这里就是打开配置文件的
void Dialog_con::OnconfigSlot()
{
	configuration_read();
}
bool Dialog_con::configuration_read()
{
	string err;
	QFile config_ini("config.ini");
	//QFile config_ini("config_baori.ini");  打开baori配置文件,如果需要访问宝日大数据平台,就需要打开baori配置文件
	if (!config_ini.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		console_con->critical("配置文件config.ini不能打开!");
		rotating_logger_con->critical("配置文件config.ini不能打开!");
		//		std::cout << "configuration.ini Open failed." << endl;
		return false;
	}
	console_con->info("配置文件config.ini已打开! ");
	rotating_logger_con->info("配置文件config.ini已打开! ");

	QTextStream config_txtInput(&config_ini);
	QString config_lineStr;

	config_lineStr = config_txtInput.readLine();

	config_lineStr = config_txtInput.readLine();
	clientID = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	clientSecret = config_lineStr.mid(13);
	config_lineStr = config_txtInput.readLine();
	serverIP = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	serviceID_get = config_lineStr.mid(14);
	config_lineStr = config_txtInput.readLine();
	serviceID_post = config_lineStr.mid(15);


	

	return true;
}

template<typename T>
T extractJsonValue(const QJsonObject& obj, const QString& key) {
	QVariant variant = obj[key].toVariant();
	return variant.value<T>();
}

void Dialog_con::json_doc_get_parse()
{

	//总的思路是:对象.value(),如果取到string、int、double类型 就直接.toString()等输出;
	//如果取到object或array类型 ,就通过toObject()或toArray() 转到对象或数组类型,接着取值。。循环
	if (json_doc_get.isNull())
	{
		console_con->critical("unable to parse! ");
		rotating_logger_con->critical("unable to parse! ");
	}
	else
	{
		console_con->info("parse start! ");
		rotating_logger_con->info("parse start! ");
	}
	
	if (doc_get_Obj.contains(QStringLiteral("Coil_first")))
	{
		
		QJsonObject task_zone0_Obj = doc_get_Obj["Coil_first"].toObject();
		QString aentid,atime, acode, agrade, asource;
		
		aentid = task_zone0_Obj["aentid"].toString();
		atime = task_zone0_Obj["atime"].toString();
		acode = task_zone0_Obj["acode"].toString();
		agrade = task_zone0_Obj["agrade"].toString();
		asource = task_zone0_Obj["asource"].toString();
		// 使用方式
		float C = extractJsonValue<float>(task_zone0_Obj, "C_CH");


		strt_hdgl_predict.ENTID = aentid;
		strt_hdgl_predict.ATIME = atime;
		strt_hdgl_predict.ST_code = acode;
		strt_hdgl_predict.ST_grade = agrade;
		strt_hdgl_predict.ST_source = asource;
		strt_hdgl_predict.CH_C = C;
	

		ui->ENTID_QLE->setText(strt_hdgl_predict.ENTID);
		ui->ATIME_QLE->setText(strt_hdgl_predict.ATIME);
		ui->ST_code_QLE->setText(strt_hdgl_predict.ST_code);
		ui->ST_grade_QLE->setText(strt_hdgl_predict.ST_grade);
		ui->ST_source_QLE->setText(strt_hdgl_predict.ST_source);

		ui->CH_C_QLE->setText(QString("%1").arg(QString::number(strt_hdgl_predict.CH_C, 'f', 4)));
		
	}
	//	}


}


void Dialog_con::on_Btn_Ret_clicked()
{
  this->hide();
  MainWindow *qMainWindow = new MainWindow();
  qMainWindow->show();
}

// 退出登入界面,这里对于按钮槽函数命名直接以on_按钮名_信号名命名,因此无需调用connect函数
// 当然槽函数需要在.h文件中进行定义
void Dialog_con::on_Btn_exit_clicked()
{
 this->hide();
 Dialog_login *login = new Dialog_login();         //登入界面显示
 login->show();
}
float Dialog_con::ByteToFloat(unsigned char* byteArray)
{
	return *((float*)byteArray);
}

int Dialog_con::ByteToInt(unsigned char* byteArray)
{
	return *((int*)byteArray);
}

04-C++ QT项目系统功能演示

        首先,需要配置一个JSON文件的环境,里面存储了一部分数据,用于模拟读取过程,这里是使用Java语言进行模拟的JSON环境,如下图所示,必须运行之后,C++系统才可以进行访问,并且需要访问同一网址才行。

        如下图所示,为系统登录界面,登录之后,才可以对各种功能进行操作。

        如下图所示,为通信界面,在这里可以模拟访问JSON文件数据,并且在对应控件上显示出来

         点击打开配置文件,然后再点击读取数据按钮,即可读取JSON文件中的所有数据,在结果显示中便可以查看。

总结

         使用 Qt 调用 RESTful 接口来访问 JSON 文件数据的方式具有以下优点:

        跨平台性:Qt 是跨平台的开发框架,可以在多种操作系统上运行,包括 Windows、macOS、Linux 等,因此可以保证应用在不同平台上的一致性。

        简洁易用:Qt 提供了丰富的网络模块和 JSON 处理功能,使得编写网络请求和数据解析的过程变得简单和直观。

        强大的网络支持:QNetworkAccessManager 提供了对网络请求的支持,可以方便地发送 HTTP 请求并处理响应,支持常见的 HTTP 请求方法,如 GET、POST 等。

        良好的异步处理:Qt 采用事件驱动的机制,在处理网络请求时能够实现异步操作,防止阻塞主线程,使得应用在进行网络通讯时仍然能够保持响应性。

        丰富的错误处理:通过监视请求的错误状态,可以对网络请求中可能出现的各种错误情况进行处理,保证应用的稳定性和可靠性。

        总的来说,使用 Qt 调用 RESTful 接口访问 JSON 文件数据的方式具有高效、稳定和可靠的特点,能够帮助开发者快速地实现网络数据的获取和处理,提高开发效率和用户体验。

  • 34
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
springboot和vue是现代web开发最常用的后端和前端框架之一。前后端分离是一种架构模式,将前端和后端的开发分离,通过接口来进行数据传输和交互。 在线教育系统作为一个实战项目,可以基于springboot和vue来开发。首先,我们可以使用springboot来构建后端的RESTful API,处理用户请求、数据持久化等功能。通过使用springboot的优秀特性,可以快速搭建项目的基础框架,并集成常用的开发组件,如Spring MVC、Spring Data JPA等。 而在前端方面,可以使用vue来开发用户界面。vue是一个轻量级的JavaScript框架,可以帮助我们构建交互式的用户界面。通过vue的组件化开发数据绑定机制,可以提高前端开发效率,并实现良好的用户体验。 在实现前后端分离的时候,可以通过定义RESTful API接口来进行数据的传输和交互。后端使用springboot提供的@RestController注解来处理HTTP请求,并返回JSON格式的数据。前端通过vue的axios库来进行异步请求和交互,获取后端提供的数据并展示在页面上。 在线教育系统常见的功能包括用户登录、课程管理、视频播放等。用户登录可以通过JWT来实现身份认证和授权。课程管理可以包括课程的发布、编辑、删除等功能,通过操作数据库来实现数据的增删改查。视频播放可以通过集成第三方视频播放器,如video.js来实现。 总结来说,使用springboot和vue进行前后端分离的在线教育系统的实战项目,可以通过定义RESTful API接口、使用axios进行数据交互和展示、集成第三方插件实现各种功能。通过这种方式,可以提高项目的开发效率、降低耦合性,并实现良好的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一伦明悦

感谢,您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值