亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

在Qt中使用QtWebApp搭建HTTP服務器的詳細步驟

 更新時間:2024年07月29日 09:23:11   作者:高亞奇  
QtWebApp是一個開源項目,它基于著名的Qt?Framework開發(fā),提供了一種在C++環(huán)境中構建HTTP服務器的解決方案,這篇文章主要給大家介紹了關于在Qt中使用QtWebApp搭建HTTP服務器的詳細步驟,需要的朋友可以參考下

前言

最近在開發(fā)Qt的http服務器功能,研究比較了一番,選擇了QtWebApp方案,相對其他開源庫,比較推薦使用該方案,功能齊全,簡單易用,如果趕項目的話,極力推薦。

下面介紹一下Qt集成QtWebApp步驟:

一、Qt集成QtWebApp步驟:

1、下載QtWebApp源碼:KingJamesGyq/QtWebApp把源碼拉下來到本地,將httpsever目錄整個移植到自己的項目工程下。

2、在pro文件包含httpserver

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

這樣就完成集成源碼了,剩下的就是根據你自己的業(yè)務需求去開發(fā)了,細節(jié)可以參考Demo1和Demo2。

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

第一步 下載QtWebApp導入工程中

工程示例:

第二步 編寫配置文件WebApp.ini

host=192.168.255.128	;服務ip地址
port=8080				;端口號
minThreads=4			;4個線程始終保持運行狀態(tài)
maxThreads=100			;并發(fā)工作線程的最大數量
cleanupInterval=60000
readTimeout=60000
maxRequestSize=16000
maxMultiPartSize=10000000

第三步 加載配置文件,創(chuàng)建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);
    }


}

第五步 自定義業(yè)務請求處理類

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_OBJECT
public:
    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());
}

第六步 測試

服務運行示例

瀏覽器發(fā)請求示例

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

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);
}

總結 

到此這篇關于在Qt中使用QtWebApp搭建HTTP服務器的文章就介紹到這了,更多相關Qt QtWebApp搭建HTTP服務器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • 從匯編看c++中引用與指針的使用分析

    從匯編看c++中引用與指針的使用分析

    在c++中,引用和指針具有相同的作用,都可以用來在函數里面給變函數外面對象或者變量的值,下面就來看他們的原理
    2013-05-05
  • C語言實現簡單推箱子游戲

    C語言實現簡單推箱子游戲

    這篇文章主要為大家詳細介紹了C語言實現簡單推箱子游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 深入解析C++編程中類的封裝特性

    深入解析C++編程中類的封裝特性

    這篇文章主要介紹了深入解析C++編程中類的封裝特性,是C++入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • 用C語言來實現一個簡單的虛擬機

    用C語言來實現一個簡單的虛擬機

    這篇文章主要介紹了用C語言來實現一個簡單的虛擬機,其中棧數組的部分非常值得學習,需要的朋友可以參考下
    2015-07-07
  • C++中this指針用法詳解及實例

    C++中this指針用法詳解及實例

    這篇文章主要介紹了C++中this指針用法詳解及實例的相關資料,需要的朋友可以參考下
    2017-04-04
  • 教你分辨C++堆與棧的區(qū)別

    教你分辨C++堆與棧的區(qū)別

    堆與棧的區(qū)別有:1、棧由系統(tǒng)自動分配,而堆是人為申請開辟;2、棧獲得的空間較小,而堆獲得的空間較大;3、棧由系統(tǒng)自動分配,速度較快,而堆一般速度比較慢;4、棧是連續(xù)的空間,而堆是不連續(xù)的空間
    2021-06-06
  • C++詳細講解圖論的基礎與圖的儲存

    C++詳細講解圖論的基礎與圖的儲存

    圖論〔Graph?Theory〕是數學的一個分支。它以圖為研究對象。圖論中的圖是由若干給定的點及連接兩點的線所構成的圖形,這種圖形通常用來描述某些事物之間的某種特定關系,用點代表事物,用連接兩點的線表示相應兩個事物間具有這種關系
    2022-05-05
  • C++如何用智能指針管理內存資源

    C++如何用智能指針管理內存資源

    這篇文章主要介紹了C++如何用智能指針管理內存資源,幫助大家更好的理解和使用c++開發(fā),感興趣的朋友可以了解下
    2020-08-08
  • C語言文件操作函數freopen詳細解析

    C語言文件操作函數freopen詳細解析

    替換一個流,或者說重新分配文件指針,實現重定向。如果stream流已經打開,則先關閉該流。如果該流已經定向,則freopen將會清除該定向。此函數一般用于將一個指定的文件打開一個預定義的流:標準輸入、標準輸出或者標準出錯
    2013-10-10
  • C++特性之智能指針shared_ptr詳解

    C++特性之智能指針shared_ptr詳解

    shared_ptr是C++11提供的一種智能指針類,它足夠智能,可以在任何地方都不使用時自動刪除相關指針,從而幫助徹底消除內存泄漏和懸空指針的問題。本文主要是來和大家聊聊shared_ptr的使用,需要的可以參考一下
    2022-12-12

最新評論