若该文为原创文章,转载请注明原文出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130840894
红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…
Qt开发专栏:三方库开发技术
上一篇:《Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试》
下一篇:《Qt+QtWebApp开发笔记(四):http服务器使用Session和Cookie实现用户密码登录和注销功能》
前言
网页很多时候是动态的,于是本篇文章目标实现一个简答的动态页面—页静态页面互相跳转,点击可以跳转到子页面。
Demo
下载地址
链接:https://pan.baidu.com/s/1bbhcu1XTiaJRYGRQRG5a0g?pwd=1234
HTML基本页面交换
上一篇的“Hello World”应用程序确实输出了简单的纯文本。但网络的语言是HTML。因此,让看看如何生成HTML。将输出当前时间,并显示列表对象中的一些数据。
创建新的请求处理
与第一个HelloWorldController类似,创建另一个名为ListDataController的新类。
listdatacontroller.h:
#ifndefLISTDATACONTROLLER_H#defineLISTDATACONTROLLER_H#include<QList>#include<QString>#include"httprequesthandler.h"usingnamespace stefanfrings;classListDataController:publicHttpRequestHandler{
Q_OBJECT
public:ListDataController(QObject* parent=0);voidservice(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");}voidListDataController::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"newHttpListener(listenerSettings,newListDataController(&app),&app);
运行并测试应用程序。输出应该是这样的:
请求映射器
现在在应用程序中有两个不同的控制器类,但一次只能使用一个。现在创建一个“RequestMapper”类,它将在两个控制器之间切换。和以前一样,新类再次从HttpRequestHandler继承。
requestmapper.h:
#ifndefREQUESTMAPPER_H#defineREQUESTMAPPER_H#include"httprequesthandler.h"usingnamespace stefanfrings;classRequestMapper:publicHttpRequestHandler{
Q_OBJECT
public:RequestMapper(QObject* parent=0);voidservice(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}voidRequestMapper::service(HttpRequest& request, HttpResponse& response){
QByteArray path=request.getPath();qDebug("RequestMapper: path=%s",path.data());if(path=="/"|| path=="/hello"){HelloWorldController().service(request, response);}elseif(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"newHttpListener(listenerSettings,newRequestMapper(&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
#ifndefREQUESTMAPPER_H#defineREQUESTMAPPER_H#include"httprequesthandler.h"#include"helloworldcontroller.h"#include"listdatacontroller.h"usingnamespace stefanfrings;classRequestMapper:publicHttpRequestHandler{
Q_OBJECT
public:RequestMapper(QObject* parent=0);voidservice(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}voidRequestMapper::service(HttpRequest& request, HttpResponse& response){
QByteArray path=request.getPath();qDebug("RequestMapper: path=%s",path.data());if(path=="/"|| path=="/hello"){
helloWorldController.service(request, response);}elseif(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页面跳转触发
其实这个对于做网页得很简单,就是一个点击超连接,只是跳转到内部,使用来实现的。
Demo增量:实战页面跳转
步骤一:准备代码模板
准备之前的demo模板:
步骤二:新建一个主入口的消息处理
copy原来的helloworld改成index(PS:不管又不有index,直接网站也是跳入index.html页面)。
修改完类相关信息。
步骤三:网页代码中入口切换
// 启动http的监听{if(!_pHttpListenerSettings){
_pHttpListenerSettings =newQSettings(httpServerPath, QSettings::IniFormat);}
_pHttpListenerSettings->beginGroup("listener");// _pHttpListener = new HttpListener(_pHttpListenerSettings, new HelloWorldRequestHandler);
_pHttpListener =newHttpListener(_pHttpListenerSettings,new IndexRequestHandler);}
步骤四:写一个简单html跳转页面
index.html
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>长沙红胖子Qt</title></head><body><p>好, 长沙红胖子 QQ:21497936 www.hpzwl.com"</p><p><ahref="helloworld">Hello world!</a></p><p><ahref="list">list</a></p></body>
list.html
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>长沙红胖子Qt</title></head><body><ahref="javascript:history.back(-1);">返回上一页</a><tableborder="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的消息处理类
这里有个乱码问题,请查看“入坑一”:
voidIndexRequestHandler::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>";}elseif(path =="/helloworld"){
helloWorldRequestHandler.service(request, response);return;}elseif(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页面:
voidListRequestHandler::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
#ifndefINDEXREQUESTHANDLER_H#defineINDEXREQUESTHANDLER_H#include"httprequesthandler.h"#include"HelloWorldRequestHandler.h"#include"ListRequestHandler.h"usingnamespace stefanfrings;classIndexRequestHandler:publicHttpRequestHandler{public:IndexRequestHandler(QObject *parent =0);public:voidservice(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")#defineLOGqDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")usingnamespace stefanfrings;IndexRequestHandler::IndexRequestHandler(QObject *parent):HttpRequestHandler(parent){// 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码)// WINDOWS: GBK GB2312// LINUX : urf-8// _pTextCodec = QTextCodec::codecForName("utf-8");
_pTextCodec =QTextCodec::codecForName("GBK");}voidIndexRequestHandler::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>";}elseif(path =="/helloworld"){
helloWorldRequestHandler.service(request, response);return;}elseif(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
#ifndefLISTREQUESTHANDLER_H#defineLISTREQUESTHANDLER_H#include"httprequesthandler.h"usingnamespace stefanfrings;classListRequestHandler:publicHttpRequestHandler{public:ListRequestHandler(QObject *parent =0);public:voidservice(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")#defineLOGqDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")usingnamespace stefanfrings;ListRequestHandler::ListRequestHandler(QObject *parent):HttpRequestHandler(parent){// 返回文本(需要在浏览器上看,所以将Qt内部编码都转成GBK输出即可,不管他本身是哪个编码)// WINDOWS: GBK GB2312// LINUX : urf-8// _pTextCodec = QTextCodec::codecForName("utf-8");
_pTextCodec =QTextCodec::codecForName("GBK");}voidListRequestHandler::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服务器日志系统介绍、添加日志系统至Demo测试》
下一篇:《Qt+QtWebApp开发笔记(四):http服务器使用Session和Cookie实现用户密码登录和注销功能》
若该文为原创文章,转载请注明原文出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130840894
版权归原作者 长沙红胖子Qt 所有, 如有侵权,请联系我们删除。