这段时间研究了一下C++的Web框架Drogon。从设计原理上面来说和Python的Web框架是大同小异的,但是难点在于编译项目上面,所以现在记录一下编译的过程。下面图是我项目的目录。其中include放的是头文件,src放的是视图文件,static放的是网页渲染的模板,drogon是框架名字,这里直接把drogon放到项目里面一起编译,CMake上面会引入。
下面我们编写一个最简单Helloworld视图,这个视图直接集成到main.cpp里面。
#include <drogon/drogon.h>
#include "greeting.h"
#include "upload_font.h"
#include "upload_endpoint.h"
using namespace drogon;
int main(){
// 直接注册视图函数
app().registerHandler(
"/",
[](const HttpRequestPtr &,
std::function<void(const HttpResponsePtr &)> &&callback) {
auto resp = HttpResponse::newHttpResponse();
resp->setBody("Hello, this is homepage!");
callback(resp);
},
{Get});
app().setLogPath("./")
.setLogLevel(trantor::Logger::kWarn)
.addListener("0.0.0.0", 8085)
.setThreadNum(16)
.run();
}
上面代码除了业务逻辑返回hello以外,其他都是固定写法的,包括服务器的启动等等。但是把所有的views写在main里面显然是不合理的,所以需要用到controller去解耦。
使用下面命令可以快速创建一个controller,通俗点说就是视图函数。
drogon_ctl create controller greeting
上面的语句就生成了一个greeting.h头文件,用于申明视图函数,以及一个greeting.cc文件,用于写相关的业务逻辑。
greeting.h
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class greeting : public drogon::HttpSimpleController<greeting>
{
public:
void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
PATH_LIST_BEGIN
// list path definitions here;
// PATH_ADD("/path", "filter1", "filter2", HttpMethod1, HttpMethod2...);
PATH_ADD("/greeting",Get);
PATH_LIST_END
};
可以看到greeting.h中是可以定义我们的路由的,我们把它移动到include文件夹下面。
greeting.cc
#include "greeting.h"
void greeting::asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)
{
// write your application logic here
auto resp = HttpResponse::newHttpResponse();
resp->setBody("hello, this is a greeting page created by drogon_ctl.");
resp->setExpiredTime(0);
callback(resp);
}
greeting.cc 是执行相应处理函数,我们把它放在src文件夹下面,这样一个完成的controller就建好了,我们也不需要做什么去注册到程序中,只需要再CMake中添加source的路径和inclue的路径就OK了,最后我们来讲一下项目的关键CMake.txt要如何写。
上面的项目的CMake应该是这样子的。
cmake_minimum_required(VERSION 3.0.0)
project(drogon_demo VERSION 0.1.0 LANGUAGES C CXX)
include(CTest)
enable_testing()
# 导入项目的头文件
include_directories(${PROJECT_SOURCE_DIR}/include)
# 导入项目的代码文件
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
# 连接DROGON框架
# 方法一:使用find_package自动查找在系统安装好的DROGON库,一般都找不到
# 因为DROGON的CMake不像OpenCV这种顶级库那么规范,所以对find_package不友好
# find_package(Drogon)
# if (DROGON_FOUND)
# target_include_directories(web_demo PUBLIC ${DROGON_INCLUDE_DIR})
# target_link_libraries(web_demo ${DROGON_LIBRARY})
# message(${DROGON_INCLUDE_DIR})
# message(${DROGON_LIBRARY})
# else(DROGON_FOUND)
# message("DROGON NOT FOUND IN SYSTEM, COMPLIE IT IN LOACAL PROJECT.")
# endif(DROGON_FOUND)
# 方法二:把依赖项目于放入项目文件夹并一起编译
add_subdirectory(${PROJECT_SOURCE_DIR}/drogon)
add_executable(drogon_demo ${SRC_LIST})
# 第二个参数:加入csp的source文件目录,用于渲染模板
drogon_create_views(drogon_demo
${CMAKE_CURRENT_SOURCE_DIR}/static
${CMAKE_CURRENT_BINARY_DIR})
# 链接已经编译好的DROGON库
target_link_libraries(drogon_demo PUBLIC drogon)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
上面的文件最关键是include_directories引入刚刚controller的头文件,aux_source_directory引入代码的文件。add_subdirectory引入我们的Drogon框架,add_executable指定入口文件夹,这个文件夹里面必须有个main.cpp唯一入口,CMake回去扫描。drogon_create_views这个用于设置模板文件的路径,我把csp的html模板文件放在static下面。有这句话才能找到csp模板,我模板渲染也成功了,但是drogon中upload_file的那个demo里面的upload_enpoint接口还是有问题,浏览器调用失败了,目前还没有解决办法,我感觉还是我CMake写的不对,呜呜,CMake真难!如果有大师知道怎么解决,非常感谢评论区可以不吝赐教。