本篇介绍如何使用QtWebApp搭建一个win环境下的http服务器。
QtWebApp教程如下:
在第一个链接中,可以下载最新版的QtWebApp,目录如下:
配置文件中各参数解释:
new stefanfrings::HttpListener(listenerSettings,new stefanfrings::StaticFileController(listenerSettings), this);
或
new stefanfrings::HttpListener(listenerSettings, new RequestMapper(), this);
参数可以是一个单独的控制器,也可以是一个请求映射器。
这里实现一个文件下载的控制器类,重点代码如下:
void StaticFileController::service(HttpRequest &request, HttpResponse &response)
{
QByteArray path=request.getPath();
qDebug()<<"Tami path ="<<path;
QByteArray parameter = request.getParameter("fileName");
qDebug()<<"Tami parameter ="<<parameter;
// Check if we have the file in cache
qint64 now=QDateTime::currentMSecsSinceEpoch();
mutex.lock();
CacheEntry* entry = cache.object(path);
if (entry && (cacheTimeout==0 || entry->created > now-cacheTimeout))
{
QByteArray document = entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock.
QByteArray filename = entry->filename;
qDebug()<<"Tami filename ="<<filename;
mutex.unlock();
qDebug("StaticFileController: Cache hit for %s",path.data());
setContentType(filename,response);
response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
response.write(document,true);
}
else
{
mutex.unlock();
// The file is not in cache.
qDebug("StaticFileController: Cache miss for %s",path.data());
// Forbid access to files outside the docroot directory
if (path.contains("/.."))
{
qWarning("StaticFileController: detected forbidden characters in path %s",path.data());
response.setStatus(403,"forbidden");
response.write("403 forbidden",true);
return;
}
// If the filename is a directory, append index.html.
if (QFileInfo(docroot+"/"+parameter/*path*/).isDir())
{
qDebug()<<"Tami 111111111";
path+="/index.html";
}
// Try to open the file
QFile file(docroot+"/"+parameter/*path*/);
qDebug("StaticFileController: Open file %s",qPrintable(file.fileName()));
if (file.open(QIODevice::ReadOnly))
{
setContentType(parameter,response);
response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
response.setHeader("Content-Length",QByteArray::number(file.size()));
if (file.size() <= maxCachedFileSize)
{
// Return the file content and store it also in the cache
entry=new CacheEntry();
while (!file.atEnd() && !file.error())
{
QByteArray buffer=file.read(65536);
response.write(buffer);
entry->document.append(buffer);
}
entry->created=now;
entry->filename=path;
mutex.lock();
cache.insert(request.getPath(),entry,entry->document.size());
mutex.unlock();
}
else
{
// Return the file content, do not store in cache
while (!file.atEnd() && !file.error())
{
response.write(file.read(65536));
}
}
file.close();
}
else {
if (file.exists())
{
qWarning("StaticFileController: Cannot open existing file %s for reading",qPrintable(file.fileName()));
response.setStatus(403,"forbidden");
response.write("403 forbidden",true);
}
else
{
response.setStatus(404,"not found");
response.write("404 not found",true);
}
}
}
}
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=="/file") {
StaticFileController(listenerSettings).service(request, response);
}
else if(path == "/doctor")
{
DoctorController().service(request, response);
}
else if(path == "/drug")
{
DrugController().service(request, response);
}
else {
response.setStatus(404,"Not found");
response.write("The URL is wrong, no such document.");
}
qDebug("RequestMapper: finished request");
}
实现了一个http服务器后,就可以通过浏览器进行http请求,如下:
当收到http请求后,请求映射器类进行分类处理,具体实现依然在控制器类中实现。比如,上面的值班医生信息请求,具体实现如下:
void DoctorController::service(HttpRequest &request, HttpResponse &response)
{
//response.write("Hello World",true);
QByteArray path=request.getPath();
qDebug()<<"Tami path ="<<path;
QByteArray parameter = request.getParameter("date");
qDebug()<<"Tami parameter ="<<parameter;
// Check if we have the file in cache
qint64 now=QDateTime::currentMSecsSinceEpoch();
mutex.lock();
CacheEntry* entry = cache.object(path);
if (entry && (cacheTimeout == 0 || entry->created > now-cacheTimeout))
{
QByteArray document = entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock.
QByteArray filename = entry->filename;
qDebug()<<"Tami filename ="<<filename;
mutex.unlock();
qDebug("DoctorController: Cache hit for %s",path.data());
setContentType(filename,response);
response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
response.write(document,true);
}
else
{
mutex.unlock();
// The file is not in cache.
qDebug("DoctorController: Cache miss for %s",path.data());
// Forbid access to files outside the docroot directory
if (path.contains("/.."))
{
qWarning("DoctorController: detected forbidden characters in path %s",path.data());
response.setStatus(403,"forbidden");
response.write("403 forbidden",true);
return;
}
//
QByteArray array = g_pDataBase->selectDoctorData(QString(parameter));
if(array.isEmpty())
{
response.setStatus(404,"not found");
response.write("404 not found",true);
}
else
{
setContentType(".json",response);
response.write(array);
}
}
}
上述代码,可以看到,我的数据是存放在mysql中的,数据库查询代码如下:
QByteArray Tmdatabase::selectDoctorData(QString date)
{
QString strSelectData;
strSelectData.clear();
//
strSelectData = QString("select * from doctor where scheduleDate='%1'").arg(date);
//
QSqlQuery m_doctorQuery(database);
m_doctorQuery.prepare(strSelectData);
//
QJsonObject json;
if(!m_doctorQuery.exec())
{
qDebug()<<m_doctorQuery.lastError();
}
else
{
//
json.insert("status",0);
json.insert("errorMsg","");
//
QJsonArray jsonArray;
while(m_doctorQuery.next())
{
//
QJsonObject jsonItem;
jsonItem.insert("deptName",m_doctorQuery.value(0).toString());
jsonItem.insert("doctorName",m_doctorQuery.value(1).toString());
jsonItem.insert("scheduleDate",m_doctorQuery.value(2).toString());
jsonItem.insert("periodStart",m_doctorQuery.value(3).toString());
jsonItem.insert("periodEnd",m_doctorQuery.value(4).toString());
jsonItem.insert("classes",m_doctorQuery.value(5).toString());
jsonItem.insert("fee",m_doctorQuery.value(6).toString());
jsonItem.insert("remain",m_doctorQuery.value(7).toString());
jsonArray.append(jsonItem);
}
json.insert("data",QJsonValue(jsonArray));
}
m_doctorQuery.finish();
//
QJsonDocument document;
document.setObject(json);
QByteArray byteArray = document.toJson(QJsonDocument::Compact);
//QString strJson(byteArray);
return byteArray;
}
至于https请求,具体实现没有研究,感兴趣的可以尝试一下。