该文章用图例+代码方式演示了,一个线上软件基本框架(精简)。开发工具Qt+VS2015

一. 基本要素

这里会用简单的图例和完整代码(这里以Qt代码为例),说明一个线上软件基本的框架。

一个线上windows软件,一般分为几个大的部分

1 UI模块

负责处理来自业务逻辑层或者其它模块的数据展示

2 网络模块

A http、https请求
B websocket(该文章不做赘述)
封装post或get请求,处理请求返回、超时等

3 业务逻辑模块

这里主要处理的是网络模块返回数据的处理,并把结果通知UI模块

4 中间层

负责关联网络模块和业务逻辑模块

5 独立模块(守护进程、更新模块、日志收集模块…)

该文章不做赘述

这里UI模块并非纯UI,其中也有业务逻辑处理。 UI模块和业务逻辑模块 可以做成更低耦合,但是会有降低效率的代价

二. 图例部分

这里用精简代码演示了
1 从用户操作UI(调用UIMainWnd::sendAsk())
2 发送网络请求(Network::_post(),Network::_get())
3 到请求结果返回(Network::requestFinished())
4 对返回数据处理(BusinessLogicManager::onAskAction())
5 通知UI模块显示(UIMainWnd::on_ask_action())

三. 代码部分

这里使用精简Qt代码演示

1 配置文件模块
#pragma once
/*********************************************************************
*@file       ConfigDef.h
*@brief      管理枚举enum、定义define、QString...
*@author
*@date
*********************************************************************/
///@ 网路请求消息结构
typedef struct _tagNetMessage
{QString _type;  // 类型int  _flag;     // 标识QString _url;   // 接口UrlQString _method;  // 请求方式QByteArray _byte; // 参数
}NetMessage;// 请求接口
/// @brief 发送聊天消息
#define API_POST_ASK_ACTION "http://www.xxxx.com/tztv/ask_action.php"// 请求类型标识
/// @brief 消息类型(用来在发送和接收网络请求时,区分是哪种消息类型)
namespace RequestType {#define REQUEST_TYPE_ASK_ACTION "ask_action" // 直播间发送文本消息
};
2 UI模块
// 头文件
/*********************************************************************
*@file       UIMainWnd.h
*@brief      交互界面
*@author
*@date
*********************************************************************/
#pragma once
#include <QWidget>class UIMainWnd : public QWidget
{Q_OBJECTpublic:UIMainWnd(QWidget *parent = Q_NULLPTR);~UIMainWnd();private Q_SLOTS:// 文本消息(网络请求返回处理)void on_ask_action(bool, const QString&, int _error_code = 0);private:void initUI();// 发送文本消息(网络请求)void sendText(const QString&_text);
};
// 源文件
UIMainWnd::UIMainWnd(QWidget *parent): QWidget(parent)
{initUI();
}UIMainWnd::~UIMainWnd()
{}void UIMainWnd::initUI()
{connect(BridgeManager::instance().businessIns(), &BusinessLogicManager::sigAskAction, this, &UIDiscuss::on_ask_action);
}/**
* 发送文本消息
*/
void UIMainWnd::sendText(const QString&_text)
{QByteArray data;data.append("channel=" + DataMgr::instance().getLocalUserInfo()._user_group);std::string str = Utils::_urlencode(_text.toStdString());QString msg_param = QString::fromStdString(str);data.append("&message=" + msg_param);data.append("&client_type=client");NetMessage msg;msg._type = REQUEST_TYPE_ASK_ACTION;msg._flag = rt_ask_action;msg._url = API_POST_ASK_ACTION;msg._method = "post";msg._byte = data;BridgeManager::instance().businessIns()->networkRequest(msg);
}// 文本消息
void UIMainWnd::on_ask_action(bool bsuccess, const QString&_content, int _error_code)
{// 处理来自业务逻辑层的消息if (bsuccess){}else{}
}
2 网络模块

分为网络模块和网络管理模块,以及超时处理,cookie处理
1)网络模块和超时处理

/*********************************************************************
*@file       Network.h
*@brief      网络模块封装
*@author
*@date
*********************************************************************/
#pragma once
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>class Network : public QObject
{Q_OBJECTpublic:Network(QObject *parent);~Network();void _get(const QUrl& _url);void _post(const QUrl& _url, const QByteArray& _bytes);void _setType(const QString& _type,); // 设置该请求的类型RequestTypevoid _setCookieJar(QNetworkCookieJar *cookieJar); //设置cookieQ_SIGNALS:// 网络模块->通知网络管理层/// 网络请求返回数据void sigReply(const QString &_type_net, const QByteArray &_byte_array);/// 网络请求失败void sigReplyError(const QString &_type_net, const int &_error_code, const QString &_error_string);/// 网络请求超时void sigTimeout(const QString& _type_net);private Q_SLOTS:// 对于网络请求返回的处理一般有三种情况:返回成功,返回失败,请求超时void requestFinished(QNetworkReply* _reply); // 网络请求返回处理(返回成功、返回失败)void on_timeout(); // 超时处理private:QString m_netType = tr(""); // 配置模块中RequestTypeQNetworkRequest m_httpRequest;QNetworkAccessManager m_networkAccessManager;
};// 超时处理
class QReplyTimeout : public QObject
{Q_OBJECTpublic:QReplyTimeout(QNetworkReply *reply, const int timeout);signals:void sigTimeout();private slots:void on_timeout();
};
#include "Network.h"Network::Network(QObject *parent): QObject(parent)
{QMetaObject::Connection connRet = QObject::connect(&m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));Q_ASSERT(connRet);
}Network::~Network()
{m_networkAccessManager.disconnect();
}void Network::_setType(const QString& _type)
{m_netType = _type;}void Network::_setCookieJar(QNetworkCookieJar *cookieJar)
{m_networkAccessManager.setCookieJar(cookieJar);
}void Network::_get(const QUrl& _url)
{m_httpRequest.setUrl(_url);QNetworkReply *_reply = m_networkAccessManager.get(m_httpRequest);// 请求超时QReplyTimeout *pTimeout = new QReplyTimeout(_reply, 5000);connect(pTimeout, &QReplyTimeout::sigTimeout, this, &Network::on_timeout);
}void Network::_post(const QUrl& _url, const QByteArray& _bytes)
{QNetworkRequest _request;_request.setUrl(_url);QNetworkReply *_reply = m_networkAccessManager.post(_request, _bytes);// 请求超时QReplyTimeout *pTimeout = new QReplyTimeout(_reply, 5000);connect(pTimeout, &QReplyTimeout::sigTimeout, this, &Network::on_timeout);
}void Network::requestFinished(QNetworkReply* _reply)
{if (_reply->error() == QNetworkReply::NoError){// request successQByteArray _byteArray = _reply->readAll();// 这里是日志,方便在日志文件中查看。关于日志生成的看后续文章QString _str_error = QString("%1 : request_reply_source_data = %2").arg(m_netType).arg(QString(_byteArray));LINFO(L"%s", _str_error.toStdWString().c_str());emit sigReply(m_netType, _byteArray);}else{// request failint _error_code = _reply->error();QString _log_error = QString("%1 : request_reply_network_error_code = %2").arg(m_netType).arg(QString::number(_error_code));LINFO(L"%s", _log_error.toStdWString().c_str());QString _error_str = _reply->errorString();emit sigReplyError(m_netType, _error_code, _error_str);}_reply->deleteLater();
}void Network::on_timeout()
{// request timeoutQNetworkReply* _reply = (QNetworkReply*)sender();int _error_code = _reply->error();QString _log_error = QString("%1 : request_reply_timeout = %2").arg(m_netType).arg(QString::number(_error_code));LINFO(L"%s", _log_error.toStdWString().c_str());emit sigTimeout(m_netType);
}QReplyTimeout::QReplyTimeout(QNetworkReply *reply, const int timeout): QObject(reply)
{Q_ASSERT(reply);if (reply && reply->isRunning()) {  // 启动单次定时器QTimer::singleShot(timeout, this, SLOT(on_timeout()));}
}void QReplyTimeout::on_timeout()
{  // 处理超时QNetworkReply *reply = static_cast<QNetworkReply*>(parent());if (reply->isRunning()) {reply->abort();reply->deleteLater();emit sigTimeout();}
}

2)网络管理模块

#pragma once
/*********************************************************************
*@file       NetWorkManager.h
*@brief      网络管理层(接收来自业务层请求,把请求结果返回业务层,通过中间层关联)
*@author
*@date
*********************************************************************/
#include <QObject>class NetworkManager : public QObject
{Q_OBJECTpublic:NetworkManager(QObject *parent);~NetworkManager();Q_SIGNALS:/// @网络层->业务层(网络层通知业务层)void sigReply(const QString& _type, const QByteArray& _byte_array);void sigReplyError(const QString &_type_net, const int &_error_code, const QString &_error_string);void sigTimeout(const QString& _type_net);public Q_SLOTS:/// @来自业务层的请求void on_net_request_activated(NetMessage &);
};
#include "NetworkManager.h"
#include "Network.h"
#include "NetworkCookie.h"
#include <QNetworkConfiguration>NetworkManager::NetworkManager(QObject *parent): QObject(parent)
{//gu_networkManager->activeConfiguration();
}NetworkManager::~NetworkManager()
{}void NetworkManager::on_net_request_activated(NetMessage &_msg)
{Network *_network = new Network(this);// 通知业务层connect(_network, &Network::sigReply, [this](const QString &_type_net, const QByteArray &_byte_array) {emit sigReply(_type_net, _byte_array);});connect(_network, &Network::sigReplyError, [this](const QString &_type_net, const int &_error_code, const QString &_error_string) {emit sigReplyError(_type_net,  _error_code, _error_string);});connect(_network, &Network::sigTimeout, [this](const QString& _type) {emit sigTimeout(_type);});_network->_setType(_msg._type);_network->_setCookieJar(&NetworkCookie::instance());// 请求方式if (_msg._method == "post"){_network->_post(_msg._url, _msg._byte);}else if (_msg._method == "get"){_network->_get(QUrl(_msg._url));}
}

3)cookie处理

#pragma once
/*********************************************************************
*@file        NetworkCookie.h
*@brief      cookie
*@author
*@date
*********************************************************************/
#include <QObject>
#include <QtNetwork/QNetworkCookie>
#include <QtNetwork/QNetworkCookieJar>class NetworkCookie : public QNetworkCookieJar
{Q_OBJECTpublic:static NetworkCookie& instance();QList<QNetworkCookie> getCookies();void setCookies(const QList<QNetworkCookie>& cookieList);private:NetworkCookie(QObject *parent);~NetworkCookie();
};
#include "NetworkCookie.h"NetworkCookie::NetworkCookie(QObject *parent): QNetworkCookieJar(parent)
{}NetworkCookie::~NetworkCookie()
{}NetworkCookie& NetworkCookie::instance()
{static NetworkCookie _uniqueInstance(Q_NULLPTR);return _uniqueInstance;
}QList<QNetworkCookie> NetworkCookie::getCookies()
{return allCookies();
}void NetworkCookie::setCookies(const QList<QNetworkCookie>& cookieList)
{if (this == NULL)return;this->setAllCookies(cookieList);
}
3 业务逻辑模块
#pragma once
/*********************************************************************
*@file       BusinessLogicManager.h
*@brief      业务逻辑层
*@author
*@date
*********************************************************************/
#include <QObject>
#include <map>
#include <functional>class BusinessLogicManager : public QObject
{Q_OBJECTpublic:explicit BusinessLogicManager(QObject *parent = nullptr);~BusinessLogicManager();void networkRequest(NetMessage&);Q_SIGNALS:/// @ 业务层->网络层(UI层通过业务层发送网络请求)void sigNetworkRequest(NetMessage&);public Q_SLOTS:// 网络请求返回成功消息通知void on_comming_msg(const QString &_type, const QByteArray&);// 网络请求返回失败消息通知void on_comming_error(const QString &_type, const int &_error_code, const QString &_error_string);// 网络请求超时消息通知void on_comming_timeout(const QString &_type);Q_SIGNALS:void sigAskAction(bool, const QString&,  int _error_code = 0);private:/// @发送文本消息void onAskAction(const QString &_type, const QByteArray& _byte_array);
}
#include "BusinessLogicManager.h"
#include "NetWorkLayer\NetworkCookie.h"
BusinessLogicManager::BusinessLogicManager(QObject *parent): QObject(parent)
{
}BusinessLogicManager::~BusinessLogicManager()
{}void BusinessLogicManager::networkRequest(NetMessage&_msg)
{emit sigNetRequest(_msg);
}// 【这里如果请求过多 会出现打来你给ifelse,后续会出关于优化ifelse文章】
void BusinessLogicManager::on_comming_msg(const QString &_type, const QByteArray&_byte)
{if (_type == NET_TYPE_ASK_ACTION){// 网络请求成功onAskAction(_type, _byte_array);}
}void BusinessLogicManager::on_comming_error(const QString &_type, const int &_error_code, const QString &_error_string)
{if (_type == NET_TYPE_ASK_ACTION){// 网络请求错误通知emit sigAskAction(false, tr("网络请求错误通知"));}
}void BusinessLogicManager::on_comming_timeout(const QString &_type)
{if (_type == NET_TYPE_ASK_ACTION){// 超时处理emit sigAskAction(false, tr("超时处理"));}
}/**
* 发送文本消息
*/
void BusinessLogicManager::onAskAction(const QString &_type, const QByteArray& _byte_array)
{// 这里是对网络请求返回的数据进行处理,然后通知UI模块std::string _f = Jsonc::instance().getJsonValueStringByKey(Utils::byteArray2string(_byte_array), "f");QString f = QString::fromStdString(_f);QString _context = tr("回复成功");if (f == "0"){_context = tr("回复成功");emit sigAskAction(true, tr(""));}else if (f == "2"){_context = tr("未登录");emit sigReLogin();}else if (f == "3"){_context = tr("字数大于80");emit sigAskAction(false, tr("字数大于80"));}else if (f == "4"){_context = tr("内容为空");emit sigAskAction(false, tr("内容为空"));}else if (f == "5"){_context = tr("3秒后再发言");emit sigAskAction(false, tr("3秒后再发言"));}else if (f == "6"){_context = tr("您已被禁言");emit sigAskAction(false, tr("您已被禁言"));}else if (f == "7"){_context = tr("未绑定手机号");emit sigAskAction(false, tr("未绑定手机号"));}
}
4 中间层
#pragma once
/*********************************************************************
*@file        BridgeManager.h
*@brief      中间控制层(UI、业务逻辑、网络)
*@author
*@date
*********************************************************************/
#include <QObject>
#include "NetWorkLayer\NetworkManager.h"
#include "BusinessLogicLayer\BusinessLogicManager.h"class BridgeManager : public QObject
{Q_OBJECTpublic:static BridgeManager& instance();// 得到网络层 和 业务逻辑层 实例BusinessLogicManager* businessIns()const;NetworkManager* networkIns()const;private:BridgeManager(QObject *parent);~BridgeManager();private:NetworkManager *m_networkManager = nullptr;BusinessLogicManager *m_businessLogicManager = nullptr;
};
#include "BridgeManager.h"BridgeManager::BridgeManager(QObject *parent): QObject(parent)
{m_businessLogicManager = new BusinessLogicManager(this);m_networkManager = new NetworkManager(this);//这里的实例化得注意了(this 会导致NetWork崩溃)// 业务层->网络层connect(m_businessLogicManager, &BusinessLogicManager::sigNetworkRequest, m_networkManager, &NetworkManager::on_net_request_activated);// 网络层->业务层connect(m_networkManager, &NetworkManager::sigReply, m_businessLogicManager, &BusinessLogicManager::on_comming_msg);connect(m_networkManager, &NetworkManager::sigReplyError, m_businessLogicManager, &BusinessLogicManager::on_comming_error);connect(m_networkManager, &NetworkManager::sigTimeout, m_businessLogicManager, &BusinessLogicManager::on_comming_timeout);
}BridgeManager::~BridgeManager()
{}BridgeManager& BridgeManager::instance()
{static BridgeManager _uniqueInstance(Q_NULLPTR);return _uniqueInstance;
}BusinessLogicManager* BridgeManager::businessIns()const
{return m_businessLogicManager;
}NetworkManager* BridgeManager::networkIns()const
{return m_networkManager;
}

Qt 软件开发框架(详细版)相关推荐

  1. mingw版本下qt与HTML,QT5.10开发(2) 在Windows 10下使用MinGW编译 静态Qt 5.10 release版 详细过程...

    Qt建议安装动态链接Dbug版和编译安装静态链接release版 前提: 先安装动态链接Dbug版,方法:QT5.10开发(1)安装QT5.10 地址:http://blog.csdn.net/qq_ ...

  2. Qt软件发布(版本信息,Release版程序,代码打包,制作安装包)

    序言 当我们完成了Qt程序的开发,希望交予测试,或是正式发布的时候,需要将我们的程序进行层层封装,最终以一个安装包的形式呈现给用户.专业版的软件发布,以Qt软件为例,需要三个步骤:生成版本信息,生成R ...

  3. JAVA软件IDEA安装教程详细版

    写在前面,由于最近换电脑了,于是乎又重新安装了软件,之前都是找人帮忙安装,自己多装了几次才会. 卸载原IDEA 在卸载程序里找到IDEA,清除一下. 准备工作 1.JDK下载 官方下载软件:https ...

  4. c gui qt 4编程第二版_一本专门学习PyQt5 GUI编程的书

    Python作为一个开源的解释型编程软件,在教学.科研.实际项目中用得越来越多.Python易学易用,程序资源丰富,在编程解决一些科学计算问题时比较实用,但是Python自带的Tkinter包设计GU ...

  5. QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64)

    QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64) 1.编译方式介绍: 2.动态编译方式打包发布QT程序: 方法一:手动复制 方法二:使用工具 问题& ...

  6. iOS App上架流程(2016详细版)

    iOS App上架流程(2016详细版) 原文地址:http://www.jianshu.com/p/b1b77d804254 感谢大神整理的这么详细 一.前言: 作为一名iOSer,把开发出来的Ap ...

  7. 使用keil建立标准STM32工程模版(图文详细版!)

    1.   模板工程的创建(超级详细版,使用的是keil 4.5版本) 1.1创建工程目录 良好的工程结构能让文件的管理更科学,让开发更容易更方便,希望大家养成良好的习惯,使用具有合理结构的工程目录,当 ...

  8. 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)

    手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版) SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式, ...

  9. Eclipse连接Hadoop集群(详细版)

    颜子之不较,孟子之自反,是贤人处横逆之方 子贡之无谄,原思之坐弦,是贤人守贫穷之法 相关连接 HDFS相关知识 Hadoop分布式文件系统(HDFS)快速入门 Hadoop分布式文件系统(HDFS)知 ...

最新文章

  1. pip install numpy/pandas时报错的解决方法
  2. java socket抓取资源_Java 通过 Socket 的形式抓取网页内容
  3. Android Studio:missing feature Watch
  4. nginx 超时时间_我眼中的 Nginx(四):是什么让你的 Nginx 服务退出这么慢?
  5. 电话圈(floyd)
  6. Python《爬取各种帅哥图片》
  7. [JZOJ5553][20190625]谜
  8. java 规则引擎roolie_【智能决策引擎】规则引擎介绍
  9. PyCharm创造起名自动生成起名·创造者·日期·时间模板
  10. Xshell、MobaXterm、Secure CRT等工具用法
  11. Error running ...: No jdk for module
  12. WISP、Client+AP和WDS 区别
  13. 饿了么即时配送分流的可运营架构演变
  14. 微软常用运行库合集(3264位)
  15. PS朋友们有福了 PhotoShop CS2 最新汉化补丁出炉
  16. 汽车行业使用LDO直接连接电池的应用
  17. SVN出现黄色感叹号,红绿双箭头
  18. SSM+手机销售网站 毕业设计-附源码161043
  19. 做自媒体没素材怎么办?
  20. 程序员初入职场第一年—— 程序员羊皮卷 连载 13

热门文章

  1. 微信公众平台 微接口 接口100 API100 接口大全(转) 开发微信功能简便了
  2. 【数据结构和算法】赫夫曼树 | 实战演练(二)
  3. 如何用python制作三维动画_python-如何在m??atplotlib中更新3D箭头动画
  4. 中序和后序(前序和中序)序列确定一颗二叉树
  5. 动态代理[JDK]机制解析
  6. 线上会议竞品调研报告
  7. Java开发导入腾讯地图描点_腾讯地图点聚合开发-实现地图找房功能
  8. ArcGIS10.8安装教程
  9. 音频技术的下一个“热点”,会出现在哪个领域?丨一期一会 • 音频工程师专场
  10. 天勤python_天勤量化策略库:网格交易策略(难度:中级)