当前位置:首页 » 《关于电脑》 » 正文

在Qt中使用QtWebApp搭建HTTP服务器

29 人参与  2024年09月24日 10:01  分类 : 《关于电脑》  评论

点击全文阅读


最近在开发Qt的http服务器功能,研究比较了一番,选择了QtWebApp方案,相对其他开源库,比较推荐使用该方案,功能齐全,简单易用,如果赶项目的话,极力推荐。
下面介绍一下Qt集成QtWebApp步骤:

一、Qt集成QtWebApp步骤:


1、下载QtWebApp源码:KingJamesGyq/QtWebApp
把源码拉下来到本地,将httpsever目录整个移植到自己的项目工程下。

2、在pro文件包含httpserver

include ($$PWD/httpserver/httpserver.pri)

这样就完成集成源码了,剩下的就是根据你自己的业务需求去开发了,细节可以参考Demo1和Demo2。

二、在Qt中使用QtWebApp搭建HTTP服务器

第一步 下载QtWebApp导入工程中

工程示例:

第二步 编写配置文件WebApp.ini

host=192.168.255.128;服务ip地址port=8080;端口号minThreads=4;4个线程始终保持运行状态maxThreads=100;并发工作线程的最大数量cleanupInterval=60000readTimeout=60000maxRequestSize=16000maxMultiPartSize=10000000

第三步 加载配置文件,创建HTTP侦听器对象

main.cpp
#include "httplistener.h"#include "httprequesthandler.h"#include "RequestMapper.h" //自定义类请求映射器类    QSettings* listenerSettings=            new QSettings(QCoreApplication::applicationDirPath()+"/WebApp.ini",QSettings::IniFormat);    new stefanfrings::HttpListener(listenerSettings, new RequestMapper());

第四步 自定义类请求映射器类

RequestMapper.h
#ifndef REQUESTMAPPER_H#define REQUESTMAPPER_H#include "httprequesthandler.h"using namespace stefanfrings;#include "HelloController.h"class RequestMapper:public HttpRequestHandler{public:    RequestMapper();    void service(HttpRequest& request, HttpResponse& response);private:    HelloController m_helloController;};#endif // REQUESTMAPPER_H
RequestMapper.cpp
#include "RequestMapper.h"#include "json.hpp"#include <string>using namespace std;using namespace nlohmann;RequestMapper::RequestMapper(){}void RequestMapper::service(HttpRequest &request, HttpResponse &response){    QByteArray path=request.getPath();    QByteArray method = request.getMethod();    QByteArray nm = request.getParameter("nm");    qDebug() << "RequestMapper: path=" << path.data();    qDebug() << "RequestMapper: method=" << method.data();     qDebug() << "RequestMapper: nm=" << nm.data();    if ( path=="/hello") {        m_helloController.service(request,response);    }}

第五步 自定义业务请求处理类

HelloController .h
#ifndef HELLOCONTROLLER_H#define HELLOCONTROLLER_H#include <QObject>#include "httprequesthandler.h"using namespace stefanfrings;#include "json.hpp"using namespace nlohmann;#include <string>using namespace std;class HelloController : public QObject{    Q_OBJECTpublic:    explicit HelloController(QObject *parent = 0);    void service(HttpRequest& request, HttpResponse& response);signals:public slots:};#endif // HELLOCONTROLLER_H

HelloController.cpp
#include "HelloController.h"HelloController::HelloController(QObject *parent) : QObject(parent){}void HelloController::service(HttpRequest &request, HttpResponse &response){   QByteArray body = request.getBody();   qDebug() << body;    json res;    res["code"] = 200;    res["mesage"] = "success";    string str = res.dump(4);    //    response.setStatus(404);    response.write(str.c_str());}

第六步 测试

服务运行示例

浏览器发请求示例

另外:其他的映射和控制器写法:

requestmapper.h
#ifndef REQUESTMAPPER_H#define REQUESTMAPPER_H#include "QtWebApp/httpserver/httprequesthandler.h"using namespace stefanfrings;/*  The request mapper dispatches incoming HTTP requests to controller classes  depending on the requested path.*/class RequestMapper : public HttpRequestHandler {    Q_OBJECT    Q_DISABLE_COPY(RequestMapper)public:    /*      Constructor.      @param parent Parent object    */    RequestMapper(QObject* parent=0);    /*      Destructor.    */    ~RequestMapper();    /*      Dispatch incoming HTTP requests to different controllers depending on the URL.      @param request The received HTTP request      @param response Must be used to return the response    */    void service(HttpRequest& request, HttpResponse& response);    // 拦截未授权操作    bool preHandle(HttpRequest& request, HttpResponse& response);};#endif // REQUESTMAPPER_H

requestmapper.cpp

#include "requestmapper.h"#include "global.h"#include "controller/logincontroller.h"#include "controller/funcvercodecontroller.h"#include "controller/sysmsgcontroller.h"#include "controller/sysusercontroller.h"#include "controller/commoncontroller.h"#include "controller/sysmenucontroller.h"#include "controller/sysdiccontroller.h"#include "controller/sysrolecontroller.h"#include "controller/sysdeptcontroller.h"#include "controller/syslogcontroller.h"#include "controller/funcmonitorcontroller.h"#include "controller/sysusermsgcontroller.h"#include "controller/funcsmscontroller.h"#include "controller/funcemailcontroller.h"#include "controller/funcloadcontroller.h"#include "controller/funcexportcontroller.h"#include<qthread.h>RequestMapper::RequestMapper(QObject* parent)    :HttpRequestHandler(parent){    qDebug("RequestMapper: created");    qDebug()<<".................RequestMapper created......................currentThreadId():"<<QThread::currentThreadId();}RequestMapper::~RequestMapper(){    qDebug("RequestMapper: deleted");}void RequestMapper::service(HttpRequest& request, HttpResponse& response){    qDebug()<<"..............RequestMapper::service..................currentThreadId():"<<QThread::currentThreadId();    QByteArray path = request.getPath().toLower();    QString tmp = QString(path);    qDebug("RequestMapper::service e");    //实现跨域访问,js 调用API 提供了支持。    response.setHeader("Connection", "keep-alive");    auto origin = request.getHeader("Origin");    response.setHeader("Access-Control-Allow-Origin", origin);    response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");    response.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER,Content-Type,x-token,access_token");    response.setHeader("Access-Control-Max-Age", "86400");    response.setHeader("Vary", "Accept-Encoding,Origin");    response.setHeader("Keep-Alive", "timeout=2,max=99");    response.setHeader("Access-Control-Allow-Credentials", "true");    //set api header    response.setHeader("Content-Type", "application/json; charset=utf-8");    //response.setHeader("Access-Control-Allow-Origin", "*"); // also important , if not set , the html application wont run.    if (request.getMethod() == "OPTIONS")    {        response.setStatus(200,"OK");        qDebug("RequestMapper: finished request");        // Clear the log buffer        return;    }    //拦截部分,做token校验    if (path.startsWith("/func")            || path.startsWith("/sys")            || path.startsWith("/monitor/"))    {        if(!preHandle(request, response))            return;    }    if (path.startsWith("/login") || path.startsWith("/logout"))    {        LoginController().service(request, response);    }    else if (path.startsWith("/vercode"))    {        FuncVercodeController().service(request, response);    }    else if (path.startsWith("/func/message/user/"))    {        SysUserMsgController().service(request, response);    }    else if (path.startsWith("/func/message/sys/"))    {        SysMsgController().service(request, response);    }    else if (path.startsWith("/sys/user/"))    {        SysUserController().service(request, response);    }    else if (path.startsWith("/sys/menu/"))    {        SysMenuController().service(request, response);    }    else if (path.startsWith("/sys/dic/"))    {        SysDicController().service(request, response);    }    else if (path.startsWith("/sys/role/"))    {        SysRoleController().service(request, response);    }    else if (path.startsWith("/sys/dept/"))    {        SysDeptController().service(request, response);    }    else if (path.startsWith("/sys/log/"))    {        SysLogController().service(request, response);    }    else if (path.startsWith("/func/sms/"))    {        FuncSmsController().service(request, response);    }    else if (path.startsWith("/sys/email/"))    {        FuncEmailController().service(request, response);    }    else if (path.startsWith("/func/upload/"))    {        FuncLoadController().service(request, response);    }    else if (path.startsWith("/func/export/"))    {        FuncExportController().service(request, response);    }    else if (path.startsWith("/monitor"))    {        FuncMonitorController().service(request, response);    }    else if (path.startsWith("/common"))    {        CommonController().service(request, response);    }    else    {        staticFileController->service(request, response);    }    qDebug("RequestMapper: finished request");    // Clear the log buffer    if (logger)    {    //   logger->clear();    }}// 拦截未授权操作bool RequestMapper::preHandle(HttpRequest& request, HttpResponse& response){    // token校验不通过,返回1001    ResultJson result(1001, false, QStringLiteral("token已失效"));    QString accessToken = request.getHeader("access_token");    if(accessToken == NULL || accessToken.isEmpty())        accessToken = request.getParameter("access_token");    if(accessToken == NULL || accessToken.isEmpty())    {        result.failedMsg(QStringLiteral("找不到token"));        ResponseUtil::replyJson(response, result);        //staticFileController->service(request, response);        return false;    }    //根据token登录    QString username = JwtUtil::getUsername(accessToken);    if(username == NULL || username.isEmpty())    {        ResponseUtil::replyJson(response, result);        //staticFileController->service(request, response);        return false;    }    //判断token是否有效    QString token_key = username + "_token";    QString saveToken = CacheApi::instance()->get(token_key);    if(saveToken != accessToken)    {        ResponseUtil::replyJson(response, result);        //staticFileController->service(request, response);        return false;    }    //刷新token    CacheApi::instance()->insert(token_key, accessToken, JwtUtil::EXPIRED_TIME);    return true;}

logincontroller.h
#ifndef LOGINCONTROLLER_H#define LOGINCONTROLLER_H#include "global.h"#include <QMap>using namespace stefanfrings;class LoginController: public HttpRequestHandler {    Q_OBJECT    Q_DISABLE_COPY(LoginController)public:    LoginController();    void service(HttpRequest& request, HttpResponse& response);    void   login(HttpRequest& request, HttpResponse& response); //登录    void  logout(HttpRequest& request, HttpResponse& response); //退出private:    SqlHelper* m_pHelper;    typedef void (LoginController::*pServFunc)(HttpRequest& request, HttpResponse& response);    QMap<QString, pServFunc> m_mapFunc;};#endif // LOGINCONTROLLER_H

logincontroller.cpp
#include "logincontroller.h"#include <QCryptographicHash>#include <qthread.h>LoginController::LoginController(){    qDebug()<<"....................LoginController........................currentThreadId():"<<QThread::currentThreadId();//    m_pHelper = SqlHelper::instance();    m_pHelper = new SqlHelper();    m_pHelper->initDB("QtWebAdmin.db");    m_mapFunc.insert("/login",   &LoginController::login);      //登录    m_mapFunc.insert("/logout",  &LoginController::logout);     //登出}void LoginController::service(HttpRequest& request, HttpResponse& response){    qDebug()<<"...................LoginController::service........................currentThreadId():"<<QThread::currentThreadId();    QByteArray path = request.getPath().toLower();    if(m_mapFunc.contains(path))    {        pServFunc func = m_mapFunc.value(path);        (this->*func)(request, response);    }}void LoginController::login(HttpRequest& request, HttpResponse& response){    qDebug()<<"..................LoginController::login...................currentThreadId():"<<QThread::currentThreadId();    ResultJson ret(0, true, QStringLiteral("登入成功"));    QString body = request.getBody();    QString username = request.getParameter("username");    QString password = request.getParameter("password");    QString vercode = request.getParameter("vercode");    QString access_token = request.getParameter("access_token");    QString codeid = request.getParameter("codeid");    HttpSession session = sessionStore->getSession(request, response, true);    if(username.isEmpty())    {        ret.failedMsg(QStringLiteral("用户名为空"));        response.write(ret.toString().toLocal8Bit());        return;    }    if(password.isEmpty())    {        ret.failedMsg(QStringLiteral("密码为空"));        response.write(ret.toString().toLocal8Bit());        return;    }    if(vercode.isEmpty())    {        ret.failedMsg(QStringLiteral("验证码为空"));        response.write(ret.toString().toLocal8Bit());        return;    }    ////    if(!session.contains("vercode"))//    {//        ret.failedMsg(QStringLiteral("未找到验证码"));//        response.write(ret.toString().toLocal8Bit());//        return;//    }    //跨域情况下,以网页请求时附带UUID,作为验证码标志    QString sessionCode = CacheApi::instance()->get(codeid + "_vercode");    if(sessionCode.isNull())    {        ret.failedMsg(QStringLiteral("未找到验证码或验证码已过期"));        response.write(ret.toString().toLocal8Bit());        return;    }    //QString sessionCode = session.get("vercode").toString();    if(sessionCode.toLower() != vercode.toLower())    {        ret.failedMsg(QStringLiteral("验证码不匹配"));        response.write(ret.toString().toLocal8Bit());        return;    }    //................检查密码    SysUser loginUser;    if(!m_pHelper->selectUserByName(loginUser, username))    {        ret.failedMsg(QStringLiteral("未找到用户或密码不正确!"));        response.write(ret.toString().toLocal8Bit());        return;    }    SysLog log("system", SysLog::LOGIN, QStringLiteral("用户登录"),                username,               QString(__FILE__),               QString(__FUNCTION__),                GlobalFunc::JsonToString(request.getParameterJson()),                request.getPeerAddress().toString(),                request.getHeader("User-Agent"),                QStringLiteral("用户成功登录"));    QString pwdAndSalt = password + loginUser.getSalt();    QString md5Pwd = QString(QCryptographicHash::hash(pwdAndSalt.toLocal8Bit(), QCryptographicHash::Md5).toHex());    if(md5Pwd != loginUser.getPassword())    {        ret.failedMsg(QStringLiteral("密码不正确!"));        response.write(ret.toString().toLocal8Bit());        log.setMemo(QStringLiteral("密码不正确!"));        m_pHelper->insertEntity(&log);        return;    }    //JWT获取,并存入缓存    QString accessToken = JwtUtil::sign(username, password);    CacheApi::instance()->insert(username + "_token", accessToken, JwtUtil::EXPIRED_TIME);    //session保存账户名和登录时间    session.set("username", username);    session.set("logintime", QTime::currentTime());    //返回token    ret.setData("access_token", accessToken);    ResponseUtil::replyJson(response, ret);    m_pHelper->insertEntity(&log);}// /logout?access_token=?void LoginController::logout(HttpRequest& request, HttpResponse& response){    QString access_token = request.getParameter("access_token");    QString username = JwtUtil::getUsername(access_token);    CacheApi::instance()->remove(username + "_token");    QJsonObject objParam = request.getParameterJson();    objParam.insert("access_token", "?");//    ResponseUtil::replyJson(response, ResultJson(0, true, QStringLiteral("操作成功")));    SysLog log("system", SysLog::LOGOUT, QStringLiteral("用户退出"),                username,                QString(__FILE__),                QString(__FUNCTION__),                GlobalFunc::JsonToString(objParam),                request.getPeerAddress().toString(),                request.getHeader("User-Agent"),                QStringLiteral("用户退出成功"));    m_pHelper->insertEntity(&log);}


点击全文阅读


本文链接:http://zhangshiyu.com/post/163805.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1