QtWebAPP使用

2017-03-02 10:12:40来源:oschina作者:木易火山人点击

QtWebApp是德国码农Stefan Frings基于Qt开发的轻量级web服务器,主要是用于嵌入式系统。官网:http://www.stefanfrings.de/qtwebapp/tutorial/index.html,资料详细,容易上手。


下面介绍下QtWebApp的用法,helloworld之类的直接跳过,直接讲一个基本的web服务器的基础代码。QtWebApp是作为一个console application运行,所以我们首先看main.cpp。


using namespace std;

int main(int argc, char *argv[])


{


QCoreApplication a(argc, argv);


QString configFileName = exePath() + "server.ini";

// Session store


QSettings* sessionSettings=new QSettings(configFileName,QSettings::IniFormat,&a);


sessionSettings->beginGroup("sessions");


RequestMapper::sessionStore=new HttpSessionStore(sessionSettings,&a);

// Static file controller


QSettings* fileSettings=new QSettings(configFileName,QSettings::IniFormat,&a);


fileSettings->beginGroup("files");


RequestMapper::staticFileController=new StaticFileController(fileSettings,&a);

// Configure template cache


QSettings* templateSettings=new QSettings(configFileName,QSettings::IniFormat,&a);


templateSettings->beginGroup("templates");


RequestMapper::templateCache=new TemplateCache(templateSettings,&a);

// HTTP server


QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&a);


listenerSettings->beginGroup("listener");


RequestMapper *rm = new RequestMapper(&a);


rm->setUrl(listenerSettings->value("url").toString());


new HttpListener(listenerSettings, rm, &a);

return a.exec();


}


QtWebApp使用ini作为配置文件,文件中可以配置ip,端口号,最大线程数,最小线程数,超时时间等。可以看出QtWebApp是采用线程模型,对每个客户端请求单独建立一个线程进行处理。main函数中用到了HttpSessionStore,StaticFileController,TemplateCache,RequestMapper4个类,下面我们分别介绍。


1、RequestMapper

void RequestMapper::service(HttpRequest &request, HttpResponse &response)


{


QByteArray path=request.getPath();


qDebug("RequestMapper: path=%s",path.data());


QByteArray sessionId=sessionStore->getSessionId(request,response);

if(sessionId.isEmpty() && !path.startsWith("/login"))


{


QString sCallBackUrl = m_url + "/login";


response.redirect(YunService::getLoginUrl(sCallBackUrl).toLocal8Bit());


}


else if (path.startsWith("/login"))


{


loginc.service(request, response);


}


else if ((path=="/index") || (path=="/"))


{


pagec.service(request, response);


}


else if (path=="/gbq")


{


gbqc.service(request, response);


}


else if (path=="/qdk")


{


qdkc.service(request, response);


}


else if (path=="/err_login.html")


{


staticFileController->service(request, response);


}


else if (path.startsWith("/js/") || path.startsWith("/css/") || path.startsWith("/img/"))


{


staticFileController->service(request, response);


}


else {


response.setStatus(404,"Not found");


response.write("The URL is wrong, no such document.");


}

qDebug("RequestMapper: finished request");


}


RequestMapper从HttpRequestHandler继承,并派生了service方法,在程序中用来作为路由,通过path将请求交给不同的处理器处理。其他的各个处理器也是从HttpRequestHandler派生,所以可以直接处理参数request和response。


2、HttpSessionStore

HttpSessionStore是QtWebApp本身的类,负责Session的管理。


class DECLSPEC HttpSessionStore : public QObject {


Q_OBJECT


Q_DISABLE_COPY(HttpSessionStore)


public:

/** Constructor. */


HttpSessionStore(QSettings* settings, QObject* parent=NULL);

/** Destructor */


virtual ~HttpSessionStore();

/**


Get the ID of the current HTTP session, if it is valid.


This method is thread safe.


@warning Sessions may expire at any time, so subsequent calls of


getSession() might return a new session with a different ID.


@param request Used to get the session cookie


@param response Used to get and set the new session cookie


@return Empty string, if there is no valid session.


*/


QByteArray getSessionId(HttpRequest& request, HttpResponse& response);

/**


Get the session of a HTTP request, eventually create a new one.


This method is thread safe. New sessions can only be created before


the first byte has been written to the HTTP response.


@param request Used to get the session cookie


@param response Used to get and set the new session cookie


@param allowCreate can be set to false, to disable the automatic creation of a new session.


@return If autoCreate is disabled, the function returns a null session if there is no session.


@see HttpSession::isNull()


*/


HttpSession getSession(HttpRequest& request, HttpResponse& response, bool allowCreate=true);

/**


Get a HTTP session by it's ID number.


This method is thread safe.


@return If there is no such session, the function returns a null session.


@param id ID number of the session


@see HttpSession::isNull()


*/


HttpSession getSession(const QByteArray id);

/** Delete a session */


void removeSession(HttpSession session);

protected:


/** Storage for the sessions */


QMap sessions;

private:

/** Configuration settings */


QSettings* settings;

/** Timer to remove expired sessions */


QTimer cleanupTimer;

/** Name of the session cookie */


QByteArray cookieName;

/** Time when sessions expire (in ms)*/


int expirationTime;

/** Used to synchronize threads */


QMutex mutex;

private slots:

/** Called every minute to cleanup expired sessions. */


void sessionTimerEvent();


};

session也可以通过ini文件配置一些属性,如果不配置的话会使用默认属性。在我们程序中使用session保存用户名和token,用户名是在登录成功后写入session中,这样就可以通过session判断用户是否成功登录过。


3、StaticFileController

StaticFileController是QtWebApp本身提供的类,从HttpRequestHandler继承,专门用来处理http的静态文件请求。


class DECLSPEC StaticFileController : public HttpRequestHandler {


Q_OBJECT


Q_DISABLE_COPY(StaticFileController)


public:

/** Constructor */


StaticFileController(QSettings* settings, QObject* parent = NULL);

/** Generates the response */


void service(HttpRequest& request, HttpResponse& response);

private:

/** Encoding of text files */


QString encoding;

/** Root directory of documents */


QString docroot;

/** Maximum age of files in the browser cache */


int maxAge;

struct CacheEntry {


QByteArray document;


qint64 created;


QByteArray filename;


};

/** Timeout for each cached file */


int cacheTimeout;

/** Maximum size of files in cache, larger files are not cached */


int maxCachedFileSize;

/** Cache storage */


QCache cache;

/** Used to synchronize cache access for threads */


QMutex mutex;

/** Set a content-type header in the response depending on the ending of the filename */


void setContentType(QString file, HttpResponse& response) const;


};

我们只需要在ini文件中配置静态文件的路径,这个类就会处理客户端的文件请求,而且处理了文件的缓存。


4、TemplateCache

TemplateCache也是QtWebApp本身的类,用来处理html模板,只需要通过配置文件配置模板所在的路径就可以了。


比如我们想在首页中显示用户的名称,可以把首页的html放在模板目录下,html中使用变量{name},然后在c++代码中给变量赋值。赋值代码如下:


void PageController::service(HttpRequest &request, HttpResponse &response)


{


HttpSession session = RequestMapper::sessionStore->getSession(request,response,true);


QString username = session.get("username").toString();


QByteArray language = request.getHeader("Accept-Language");


response.setHeader("Content-Type", "text/html; charset=UTF-8");


Template t = RequestMapper::templateCache->getTemplate("index",language);


t.setVariable("name", username);


response.write(t.toUtf8(),true);


}


代码从session中读取username,通过templateCache获得模板对象,然后通过模板对象的setVariable写入username,最后把模板对象转换成字符串返回到客户端。


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台