欢迎光临散文网 会员登陆 & 注册

Qt+QtWebApp开发笔记(三):http服务器动态html连接跳转基础交互

2023-05-24 11:19 作者:红胖子_AAA红模仿  | 我要投稿

前言

  网页很多时候是动态的,于是本篇文章目标实现一个简答的动态页面—页静态页面互相跳转,点击可以跳转到子页面。

Demo

  

下载地址

  链接:https://pan.baidu.com/s/1bbhcu1XTiaJRYGRQRG5a0g?pwd=1234

HTML基本页面交换

  上一篇的“Hello World”应用程序确实输出了简单的纯文本。但网络的语言是HTML。因此,让看看如何生成HTML。将输出当前时间,并显示列表对象中的一些数据。

创建新的请求处理

  与第一个HelloWorldController类似,创建另一个名为ListDataController的新类。

listdatacontroller.h:

#ifndef LISTDATACONTROLLER_H #define LISTDATACONTROLLER_H #include <QList> #include <QString> #include "httprequesthandler.h" using namespace stefanfrings; class ListDataController: public HttpRequestHandler {     Q_OBJECT public:     ListDataController(QObject* parent=0);     void service(HttpRequest& request, HttpResponse& response); private:     QList<QString> list; }; #endif // LISTDATACONTROLLER_H

listdatacontroller.cpp:

#include <QTime> #include "listdatacontroller.h" ListDataController::ListDataController(QObject* parent)     : HttpRequestHandler(parent) {     list.append("Robert");     list.append("Lisa");     list.append("Hannah");     list.append("Ludwig");     list.append("Miranda");     list.append("Francesco");     list.append("Kim");     list.append("Jacko"); } void ListDataController::service(HttpRequest &request, HttpResponse &response) {     response.setHeader("Content-Type", "text/html; charset=UTF-8");     response.write("<html><body>");     response.write("The time is ");     QString now=QTime::currentTime().toString("HH:mm:ss");     response.write(now.toUtf8());     response.write("<p>List of names:");     response.write("<table border='1' cellspacing='0'>");     for(int i=0; i<list.size(); i++) {         QString number=QString::number(i);         QString name=list.at(i);         response.write("<tr><td>");         response.write(number.toUtf8());         response.write("</td><td>");         response.write(name.toUtf8());         response.write("</td></tr>");     }     response.write("</table>");     response.write("</body></header>",true); }

  构造函数用一些名称填充列表。该服务方法输出一个具有当前时间的HTML文档和一个显示列表对象内容的表。
  请注意,在编写文档之前设置了一个HTTP响应头,它告诉浏览器使用的文件格式(请参阅Internet Media Types)和字符编码。
  用新的控制器替换main.cpp中的控制器:

#include "listdatacontroller.h"     new HttpListener(listenerSettings,new ListDataController(&app),&app);

  运行并测试应用程序。输出应该是这样的:
  

请求映射器

  现在在应用程序中有两个不同的控制器类,但一次只能使用一个。现在创建一个“RequestMapper”类,它将在两个控制器之间切换。和以前一样,新类再次从HttpRequestHandler继承。

requestmapper.h:

#ifndef REQUESTMAPPER_H #define REQUESTMAPPER_H #include "httprequesthandler.h" using namespace stefanfrings; class RequestMapper : public HttpRequestHandler {     Q_OBJECT public:     RequestMapper(QObject* parent=0);     void service(HttpRequest& request, HttpResponse& response); }; #endif // REQUESTMAPPER_H

requestmapper.cpp:

#include "requestmapper.h" #include "helloworldcontroller.h" #include "listdatacontroller.h" RequestMapper::RequestMapper(QObject* parent)     : HttpRequestHandler(parent) {     // empty } void RequestMapper::service(HttpRequest& request, HttpResponse& response) {     QByteArray path=request.getPath();     qDebug("RequestMapper: path=%s",path.data());     if (path=="/" || path=="/hello") {         HelloWorldController().service(request, response);     }     else if (path=="/list") {         ListDataController().service(request, response);     }     else {         response.setStatus(404,"Not found");         response.write("The URL is wrong, no such document.",true);     }     qDebug("RequestMapper: finished request"); }

  用新的请求映射程序替换main.cpp中的旧控制器:

#include "requestmapper.h"     new HttpListener(listenerSettings,new RequestMapper(&app),&app);

  请求映射器根据请求的路径调用两个控制器中的一个。所以

  • 当打开http://localhost:8080/或http://localhost:8080/hello,会看到“Hello World”页面。

  • 当打开http://localhost:8080/list,获得姓名列表。

  例如,如果试图打开任何错误的URLhttp://localhost:8080/lalala,然后会收到错误消息“URL错误…”以及状态代码404,这是“未找到”的技术值。一些程序使用它来处理错误。如果没有设置状态代码,那么将使用默认的200,这意味着“成功”。请参阅维基百科中的HTTP状态代码列表。
如果多个并发HTTP请求同时传入,那么service()方法将并行执行多次。所以这个方法是多线程的。当访问在service()方法外部声明的变量时,必须考虑这一点。
  请求映射器是“singleton”或处于“application scope”,因为它只有一个实例。
两个控制器类(HelloWorldController和ListDataController)位于“请求范围”中,这意味着每个请求都由该类的新实例处理。这会降低一些性能,但会稍微简化编程。

一个接口对一个控制器优化效率

  一个小的修改将两个控制器类的范围更改为“应用程序范围”。(PS:这个就是每次运行的时候,不是去新new)
  

new requestmapper.h

#ifndef REQUESTMAPPER_H #define REQUESTMAPPER_H #include "httprequesthandler.h" #include "helloworldcontroller.h" #include "listdatacontroller.h" using namespace stefanfrings; class RequestMapper : public HttpRequestHandler {     Q_OBJECT public:     RequestMapper(QObject* parent=0);     void service(HttpRequest& request, HttpResponse& response); private:     HelloWorldController helloWorldController;     ListDataController listDataController; }; #endif // REQUESTMAPPER_H

new requestmapper.cpp

#include "requestmapper.h" RequestMapper::RequestMapper(QObject* parent)     : HttpRequestHandler(parent) {     // empty } void RequestMapper::service(HttpRequest& request, HttpResponse& response) {     QByteArray path=request.getPath();     qDebug("RequestMapper: path=%s",path.data());     if (path=="/" || path=="/hello") {         helloWorldController.service(request, response);     }     else if (path=="/list") {         listDataController.service(request, response);     }     else {         response.setStatus(404,"Not found");         response.write("The URL is wrong, no such document.");     }     qDebug("RequestMapper: finished request"); }

  现在,每个请求都只重新使用一个HelloWorldController或ListDataController实例。在启动期间只创建一次,因为HttpRequestMapper也只存在一次。
  使用会话后,还可以为每个会话创建控制器实例,并将它们存储在会话存储中。然后就有了一个“会话范围”。会话将在后面进行解释。

请求映射程序项目

  按照上面得,实际上就是刚开始出一个列表,/和/hello会出现helloworld,而/list则会返回list列表,这是直接通过url后得子网页来切换(PS:并不是通过点击主页面来切换,这个后面会解说到)。

Web页面跳转触发

  其实这个对于做网页得很简单,就是一个点击超连接,只是跳转到内部,使用<a>来实现的。

Demo增量:实战页面跳转

步骤一:准备代码模板

  准备之前的demo模板:
   

步骤二:新建一个主入口的消息处理

  copy原来的helloworld改成index(PS:不管又不有index,直接网站也是跳入index.html页面)。
  


  修改完类相关信息。

步骤三:网页代码中入口切换

  

  // 启动http的监听     {         if(!_pHttpListenerSettings)         {             _pHttpListenerSettings = new QSettings(httpServerPath, QSettings::IniFormat);         }         _pHttpListenerSettings->beginGroup("listener"); //        _pHttpListener = new HttpListener(_pHttpListenerSettings, new HelloWorldRequestHandler);         _pHttpListener = new HttpListener(_pHttpListenerSettings, new IndexRequestHandler);     }

步骤四:写一个简单html跳转页面

index.html

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>长沙红胖子Qt</title> </head> <body>     <p>好, 长沙红胖子 QQ:21497936 www.hpzwl.com"</p>     <p><a href="helloworld">Hello world!</a></p>     <p><a href="list">list</a></p> </body>

list.html

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>长沙红胖子Qt</title> </head> <body>     <a href="javascript:history.back(-1);">返回上一页</a>     <table border="2">          <tr>             <td>row 1, cell 1</td>             <td>row 1, cell 2</td>         </tr>         <tr>             <td>row 2, cell 1</td>             <td>row 2, cell 2</td>         </tr>     </table> </body>

步骤五:修改index.html的消息处理类

  

  这里有个乱码问题,请查看“入坑一”:

  

void IndexRequestHandler::service(HttpRequest &request, HttpResponse &response) {     QString str;     QString path = request.getPath();     LOG << path;     if(path == "/" || path == "/index")     {         str += "<!DOCTYPE html>"                "<html lang=\"en\">"                "<head>"                "<meta charset=\"UTF-8\">"                "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"                "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"                "<title>长沙红胖子Qt</title>"                "</head>"                "<body>"                "    <p>好, 长沙红胖子 QQ:21497936 www.hpzwl.com</p>"                "    <p><a href=\"helloworld\">Hello world!</a></p>"                "    <p><a href=\"list\">list</a></p>"                "</body>";     }else if(path == "/helloworld")     {         helloWorldRequestHandler.service(request, response);         return;     }else if(path == "/list")     {         listRequestHandler.service(request, response);         return;     }else {         response.setStatus(404,"Not found");         str = "The URL is wrong, no such document.";     }     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码) //    QByteArray byteArray = _pTextCodec->fromUnicode(str);     QByteArray byteArray = str.toUtf8();     response.write(byteArray); }

步骤六:新建一个list.html修改消息处理类

  

  修改好宏类名,然后嵌入list.html页面:
  

void ListRequestHandler::service(HttpRequest &request, HttpResponse &response) {     QString str;     LOG << request.getPath();     str = "<!DOCTYPE html>"           "<html lang=\"en\">"           "<head>"           "<meta charset=\"UTF-8\">"           "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"           "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"           "<title>长沙红胖子Qt</title>"           "</head>"           "<body>"           "<a href=\"javascript:history.back(-1);\">返回上一页</a>"           "<table border=\"2\">"           "        <tr>"           "            <td>row 1, cell 1</td>"           "            <td>row 1, cell 2</td>"           "        </tr>"           "        <tr>"           "            <td>row 2, cell 1</td>"           "            <td>row 2, cell 2</td>"           "        </tr>"           "    </table>"           "</body>";     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码) //    QByteArray byteArray = _pTextCodec->fromUnicode(str);     QByteArray byteArray = str.toUtf8();     response.write(byteArray); }

Demo源码

IndexRequestHandler.h

#ifndef INDEXREQUESTHANDLER_H #define INDEXREQUESTHANDLER_H #include "httprequesthandler.h" #include "HelloWorldRequestHandler.h" #include "ListRequestHandler.h" using namespace stefanfrings; class IndexRequestHandler : public HttpRequestHandler { public:     IndexRequestHandler(QObject *parent = 0); public:     void service(HttpRequest& request, HttpResponse& response); private:     QTextCodec *_pTextCodec; private:     HelloWorldRequestHandler helloWorldRequestHandler;  // hellowold消息处理     ListRequestHandler listRequestHandler;              // list消息处理 }; #endif // INDEXREQUESTHANDLER_H

IndexRequestHandler.cpp

#include "IndexRequestHandler.h" #include "ListRequestHandler.h" #include <QTextCodec> #include <QDebug> #include <QDateTime> //#define LOG qDebug()<<__FILE__<<__LINE__ //#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__ //#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread() //#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd") #define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") using namespace stefanfrings; IndexRequestHandler::IndexRequestHandler(QObject *parent)     : HttpRequestHandler(parent) {     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码)     // WINDOWS: GBK  GB2312     // LINUX  : urf-8 //    _pTextCodec = QTextCodec::codecForName("utf-8");     _pTextCodec = QTextCodec::codecForName("GBK"); } void IndexRequestHandler::service(HttpRequest &request, HttpResponse &response) {     QString str;     QString path = request.getPath();     LOG << path;     if(path == "/" || path == "/index")     {         str += "<!DOCTYPE html>"                "<html lang=\"en\">"                "<head>"                "<meta charset=\"UTF-8\">"                "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"                "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"                "<title>长沙红胖子Qt</title>"                "</head>"                "<body>"                "    <p>好, 长沙红胖子 QQ:21497936 www.hpzwl.com</p>"                "    <p><a href=\"helloworld\">Hello world!</a></p>"                "    <p><a href=\"list\">list</a></p>"                "</body>";     }else if(path == "/helloworld")     {         helloWorldRequestHandler.service(request, response);         return;     }else if(path == "/list")     {         listRequestHandler.service(request, response);         return;     }else {         response.setStatus(404,"Not found");         str = "The URL is wrong, no such document.";     }     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码) //    QByteArray byteArray = _pTextCodec->fromUnicode(str);     QByteArray byteArray = str.toUtf8();     response.write(byteArray); }

ListRequestHandler.h

#ifndef LISTREQUESTHANDLER_H #define LISTREQUESTHANDLER_H #include "httprequesthandler.h" using namespace stefanfrings; class ListRequestHandler : public HttpRequestHandler { public:     ListRequestHandler(QObject *parent = 0); public:     void service(HttpRequest& request, HttpResponse& response); private:     QTextCodec *_pTextCodec; }; #endif // LISTREQUESTHANDLER_H

ListRequestHandler.cpp

#include "ListRequestHandler.h" #include <QTextCodec> #include <QDebug> #include <QDateTime> //#define LOG qDebug()<<__FILE__<<__LINE__ //#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__ //#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread() //#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd") #define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") using namespace stefanfrings; ListRequestHandler::ListRequestHandler(QObject *parent)     : HttpRequestHandler(parent) {     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码)     // WINDOWS: GBK  GB2312     // LINUX  : urf-8 //    _pTextCodec = QTextCodec::codecForName("utf-8");     _pTextCodec = QTextCodec::codecForName("GBK"); } void ListRequestHandler::service(HttpRequest &request, HttpResponse &response) {     QString str;     LOG << request.getPath();     str = "<!DOCTYPE html>"           "<html lang=\"en\">"           "<head>"           "<meta charset=\"UTF-8\">"           "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"           "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"           "<title>长沙红胖子Qt</title>"           "</head>"           "<body>"           "<a href=\"javascript:history.back(-1);\">返回上一页</a>"           "<table border=\"2\">"           "        <tr>"           "            <td>row 1, cell 1</td>"           "            <td>row 1, cell 2</td>"           "        </tr>"           "        <tr>"           "            <td>row 2, cell 1</td>"           "            <td>row 2, cell 2</td>"           "        </tr>"           "    </table>"           "</body>";     // 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码) //    QByteArray byteArray = _pTextCodec->fromUnicode(str);     QByteArray byteArray = str.toUtf8();     response.write(byteArray); }

工程模板v1.2.0

  

入坑

入坑一:编码问题乱码

问题

   乱码
  

原因

  之前的网页没有编码,直接转换的,新建的页面有编码,标识了utf-8,所以无需转码gbk了。

解决

  当表示好页面的编码未utf-8之后,则无需字符转换编码。
  


  


Qt+QtWebApp开发笔记(三):http服务器动态html连接跳转基础交互的评论 (共 条)

分享到微博请遵守国家法律