实用指南:Drogon: 一个开源的C++高性能Web框架

news/2025/11/28 22:52:58/文章来源:https://www.cnblogs.com/ljbguanli/p/19284362

实用指南:Drogon: 一个开源的C++高性能Web框架

目录

1.简介

2.安装方法

3.快速入门示例

3.1.创建简单的Web服务

3.2.控制器类路由

3.3.数据库集成与ORM

3.4.过滤器-实现AOP切面编程

3.5.构建RESTful API

4.完整功能示例

5.性能与适用场景

6.总结

学习资源


1.简介

        Drogon是一个基于C++14/17/20编写的高性能HTTP Web应用框架,它的设计目标是充分利用 C++ 的性能优势,同时简化 Web 开发流程,适合构建高并发、低延迟的后端服务。它采用异步非阻塞的架构设计,使用epoll(Linux)和kqueue(macOS/FreeBSD)等高效事件处理机制,即使在大量并发请求下也能保持出色的性能表现。Drogon是跨平台的,支持Linux、macOS、FreeBSD、OpenBSD和Windows等多种操作系统。

        它的核心特性有:

1.高性能异步架构:基于事件驱动模型(依赖 epoll/kqueue 等 IO 复用机制),支持异步非阻塞 IO,能高效处理大量并发连接,性能接近原生 C 开发的服务。

2.全面的 HTTP 支持:

  • 支持 HTTP/1.0、HTTP/1.1,以及 HTTPS(基于 OpenSSL);
  • 内置 RESTful API 路由系统,支持多种路由定义方式(函数、lambda、控制器类);
  • 支持请求参数解析、Cookie/Session 管理、文件上传下载等。

3.WebSocket 支持:原生支持 WebSocket 协议,可轻松实现实时通信(如聊天、实时数据推送),提供回调接口处理连接建立、消息收发、断开等事件。

4.ORM 功能:内置轻量级 ORM,支持 MySQL、PostgreSQL、SQLite 等数据库,可通过 C++ 类映射数据库表,简化 CRUD 操作(无需手写 SQL)。

5.灵活路由系统:支持RESTful风格路由设计,可轻松定义各种HTTP端点

6.视图渲染:支持后端渲染,通过CSP(类JSP)模板生成动态HTML页面

7.JSON处理:内置JSON序列化与反序列化,非常适合开发RESTful API

8.过滤器机制:提供AOP支持,可轻松实现登录验证、日志记录等统一逻辑

9.灵活的扩展:支持插件机制,可自定义中间件(如日志、权限校验)、过滤器等,满足复杂业务需求。

10.跨平台:支持 Linux、macOS、Windows 等主流操作系统,依赖 C++17 及以上标准(需现代编译器如 GCC 7+、Clang 5+、MSVC 2017+)。

2.安装方法

Drogon 依赖一些基础库(如 libuuidopenssljsoncpp 等),安装前需先配置依赖,再通过源码编译安装。

Linux/macOS 示例(以 Ubuntu 为例)

1.安装依赖:

sudo apt-get install g++ cmake git libssl-dev libjsoncpp-dev libuuid-dev zlib1g-dev

2.克隆源码并编译:

git clone https://github.com/drogonframework/drogon.git
cd drogon
git submodule update --init  # 拉取子模块(如 trantor 事件库)
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local  # 指定安装路径
make -j4  # 并行编译
sudo make install

在其他操作系统上,你也可以通过包管理器安装,例如在Debian上可以使用apt-get install libdrogon-dev

3.快速入门示例

3.1.创建简单的Web服务

下面是一个简单的Drogon应用示例,它创建了一个返回JSON响应的HTTP服务:

#include 
using namespace drogon;
int main() {// 设置HTTP路由app().registerHandler("/hello",[](const HttpRequestPtr& req,std::function&& callback) {// 创建JSON响应Json::Value json;json["message"] = "Hello, Drogon!";json["status"] = "success";auto resp = HttpResponse::newHttpJsonResponse(json);callback(resp);},{Get});// 配置并启动服务器app().setLogPath("./").setLogLevel(trantor::Logger::kWarn).addListener("0.0.0.0", 8080).setThreadNum(16).run();return 0;
}

这个简单示例展示了Drogon的基本用法:

  • 注册一个处理函数到路径/hello
  • 当收到GET请求时,返回一个JSON响应
  • 服务器监听在8080端口,使用16个处理线程

编译命令(假设文件名为 main.cpp):

g++ main.cpp -o app -ldrogon -std=c++17

运行后访问 http://localhost:8080/hello 即可看到结果。

3.2.控制器类路由

对于复杂业务,推荐使用控制器类管理路由,通过宏定义简化配置。

#include 
using namespace drogon;
// 定义控制器类
class UserController : public HttpController {
public:// 路由映射:GET /user/{id}METHOD_LIST_BEGIN// 绑定 "/user/{id}" 到 getUser 方法,支持 GETADD_METHOD_TO(UserController::getUser, "/user/{id}", Get);METHOD_LIST_END// 处理函数:参数从路由中提取({id} 对应 path 中的 id)void getUser(const HttpRequestPtr& req,std::function&& callback,int id) {auto resp = HttpResponse::newHttpResponse();resp->setBody("User ID: " + std::to_string(id));callback(resp);}
};
int main() {// 注册控制器(Drogon 会自动解析路由)drogon::app().registerController(std::make_shared());drogon::app().run();return 0;
}

访问 http://localhost:8080/user/123 会返回 User ID: 123

3.3.数据库集成与ORM

Drogon内置了ORM支持,可以轻松操作数据库。以下是一个使用ORM的示例:

假设数据库中有 users 表(字段:id INT, name VARCHAR(50), age INT),用 Drogon ORM 操作:

1.定义数据模型(映射表结构):

#include 
using namespace drogon::orm;
// 映射 users 表
class User : public DbModel {
public:// 定义字段(与表字段对应)Field id;Field name;Field age;// 绑定表名和主键TABLE_NAME("users")PRIMARY_KEY(id)
};

2.数据库操作(查询 / 插入):

#include 
#include "User.h"  // 引入模型
int main() {// 配置数据库连接(MySQL 示例)drogon::app().addDbClient("mysql", "host=localhost port=3306 dbname=test user=root password=123456");// 获取数据库客户端auto client = drogon::app().getDbClient();// 插入一条记录client->insert(User{}.setName("Alice").setAge(25)).then([](const Result& res) {std::cout << "Inserted ID: " << res.lastInsertId() << std::endl;}).catchError([](const DrogonDbException& e) {std::cerr << "Insert error: " << e.what() << std::endl;});// 查询 age > 20 的用户client->query(Select(User::name, User::age).where(User::age > 20)).then([](const std::vector& users) {for (const auto& u : users) {std::cout << "Name: " << u.name << ", Age: " << u.age << std::endl;}}).catchError([](const DrogonDbException& e) {std::cerr << "Query error: " << e.what() << std::endl;});drogon::app().run();return 0;
}

3.4.过滤器-实现AOP切面编程

Drogon的过滤器功能允许你在请求到达处理器之前执行通用逻辑,比如身份验证:

class LoginFilter : public drogon::HttpFilter
{
public:virtual void doFilter(const HttpRequestPtr &req,FilterCallback &&fcb,FilterChainCallback &&fccb) override{// 检查用户是否登录auto session = req->getSession();if (session->find("user")) {// 用户已登录,继续处理fccb();} else {// 用户未登录,返回错误Json::Value json;json["error"] = "Unauthorized";json["message"] = "Please login first";auto resp = HttpResponse::newHttpJsonResponse(json);resp->setStatusCode(k401Unauthorized);fcb(resp);}}
};

然后在控制器中注册过滤器:

PATH_LIST_BEGIN
PATH_ADD("/profile", Get, "LoginFilter");
PATH_LIST_END

3.5.构建RESTful API

结合上述功能,我们可以构建一个完整的RESTful API:

#include 
using namespace drogon;
class UserAPI : public HttpSimpleController
{
public:void asyncHandleHttpRequest(const HttpRequestPtr& req,std::function&& callback) override{auto method = req->getMethod();Json::Value response;if (method == Get) {// 获取用户列表response["users"] = Json::arrayValue;response["count"] = 0;} else if (method == Post) {// 创建新用户auto json = req->getJsonObject();if (json) {response["status"] = "user created";response["id"] = 1001;} else {response["error"] = "invalid input";}} else if (method == Put) {// 更新用户response["status"] = "user updated";} else if (method == Delete) {// 删除用户response["status"] = "user deleted";}auto resp = HttpResponse::newHttpJsonResponse(response);callback(resp);}PATH_LIST_BEGINPATH_ADD("/api/users", Get, Post, Put, Delete);PATH_LIST_END
};

配置文件

Drogon支持通过JSON文件配置应用:

config.json:

{"app": {"log_path": "./","log_level": "WARN"},"listeners": [{"address": "0.0.0.0","port": 8080,"https": false}],"db_clients": [{"name": "default","type": "postgresql","host": "localhost","port": 5432,"dbname": "mydatabase","user": "myuser","passwd": "mypassword"}],"thread_num": 16
}

在代码中加载配置:

app().loadConfigFile("../config.json");
app().run();

4.完整功能示例

下面提供一个使用 Drogon 实现的简单 Web 应用示例,包含首页展示带参数的用户信息页表单提交与处理三个核心功能,覆盖了 Drogon 的路由配置、控制器使用、HTTP 请求处理等基础用法。

示例功能说明

  1. 访问 GET /:显示首页(HTML 页面),包含导航链接。
  2. 访问 GET /user/{id}:通过用户 ID 查询模拟的用户信息(使用控制器类实现)。
  3. 访问 GET /form:显示一个表单页面,支持提交用户名和邮箱。
  4. 提交表单到 POST /submit:处理表单数据并返回结果。

完整代码(main.cpp

#include 
#include 
#include 
using namespace drogon;
using namespace std;
// 1. 首页路由处理(直接通过handler注册)
void handleHome(const HttpRequestPtr& req, function&& callback) {// 构建HTML首页内容string html = R"(Drogon 示例应用

欢迎使用 Drogon 示例应用

  • 查看用户1的信息
  • 查看用户2的信息
  • 提交表单
)";auto resp = HttpResponse::newHttpResponse();resp->setBody(html);resp->setContentTypeCode(CT_TEXT_HTML); // 声明为HTML类型callback(resp); } // 2. 用户信息控制器(处理带参数的路由) class UserController : public HttpController { public:// 路由映射:GET /user/{id}METHOD_LIST_BEGINADD_METHOD_TO(UserController::getUserInfo, "/user/{id}", Get);METHOD_LIST_END// 处理用户信息请求(从路由参数中获取id)void getUserInfo(const HttpRequestPtr& req,function&& callback,int userId) {// 模拟用户数据(实际项目中可能从数据库查询)string userName;string userEmail;if (userId == 1) {userName = "张三";userEmail = "zhangsan@example.com";} else if (userId == 2) {userName = "李四";userEmail = "lisi@example.com";} else {userName = "未知用户";userEmail = "未知邮箱";}// 构建用户信息HTMLstring html = fmt::format(R"(用户信息

用户 {} 的信息

ID: {}

姓名: {}

邮箱: {}

返回首页)", userId, userId, userName, userEmail);auto resp = HttpResponse::newHttpResponse();resp->setBody(html);resp->setContentTypeCode(CT_TEXT_HTML);callback(resp);} }; // 3. 表单处理相关路由 // 3.1 显示表单页面 void showForm(const HttpRequestPtr& req, function&& callback) {string html = R"(提交表单

用户表单



返回首页)";auto resp = HttpResponse::newHttpResponse();resp->setBody(html);resp->setContentTypeCode(CT_TEXT_HTML);callback(resp); } // 3.2 处理表单提交(POST请求) void handleSubmit(const HttpRequestPtr& req, function&& callback) {// 从表单中获取数据(POST表单数据在req->getParameters()中)auto params = req->getParameters();string username = params["username"];string email = params["email"];// 构建提交结果HTMLstring html = fmt::format(R"(提交成功

表单提交成功!

您提交的信息:

用户名: {}

邮箱: {}

返回表单 | 返回首页)", username, email);auto resp = HttpResponse::newHttpResponse();resp->setBody(html);resp->setContentTypeCode(CT_TEXT_HTML);callback(resp); } int main() {// 注册路由app().registerHandler("/", handleHome, {Get}); // 首页app().registerHandler("/form", showForm, {Get}); // 表单页面app().registerHandler("/submit", handleSubmit, {Post}); // 表单提交处理app().registerController(make_shared()); // 注册用户控制器// 配置服务(端口8080,日志级别INFO)app().setLogLevel(trantor::Logger::kInfo);app().addListener("0.0.0.0", 8080);// 启动服务cout << "服务已启动,访问 http://localhost:8080" << endl;app().run();return 0; }

编译代码

g++ main.cpp -o drogon_app -ldrogon -std=c++17
  • -ldrogon:链接 Drogon 库
  • -std=c++17:指定 C++17 标准(Drogon 依赖)

运行程序

./drogon_app

终端会输出 服务已启动,访问 http://localhost:8080,表示服务正常运行。

测试功能

  1. 访问 http://localhost:8080:查看首页,点击链接导航到其他页面。
  2. 访问 http://localhost:8080/user/1 或 http://localhost:8080/user/2:查看模拟的用户信息。
  3. 访问 http://localhost:8080/form:填写表单并提交,会显示提交结果。

代码解析

  • 路由注册:通过registerHandler直接注册简单路由(如首页、表单页),通过registerController注册控制器类(如用户信息页),支持 RESTful 风格的参数提取(/user/{id})。
  • HTTP 方法:通过{Get}{Post}指定路由支持的 HTTP 方法,避免非法请求。
  • 响应处理:通过HttpResponse构建响应,设置Content-Typetext/html以正确显示 HTML 内容。
  • 表单数据:POST 表单数据通过req->getParameters()获取,键为表单字段名(如usernameemail)。

5.性能与适用场景

  • 性能:得益于异步 IO 和 C++ 的高效性,Drogon 在高并发场景下表现优异(可轻松处理数万 QPS)。
  • 适用场景:后端 API 服务、微服务、实时通信服务(如 WebSocket)、需要高性能的业务系统等。

6.总结

        Drogon框架通过其异步非阻塞的架构和丰富的功能集,为C++开发者提供了构建高性能Web服务的强大工具。无论是简单的API端点还是复杂的企业级应用,Drogon都能提供出色的性能和开发体验。

学习资源

  • 官方仓库:github.com/drogonframework/drogon
  • 官方文档:drogonframework.github.io/drogon
  • 示例代码:仓库中 examples 目录包含各种场景的示例(HTTP、WebSocket、ORM 等)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/980158.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mini Auto Key Programmer: Remotely Unlock Copy 96Bit ID48/NCF29xx Car Keys

The Modern Car Key Programming Dilemma: A Challenge for Mechanics and Owners Alike In today’s automotive world, car keys are far more than just access tools—they’re sophisticated electronic componen…

从零开始的云原生之旅(十一):压测实战:验证弹性伸缩效果 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

AI浪潮下的机遇与挑战:从技术突破到就业现实

最近刷到不少AI相关的新闻,感觉整个科技圈都在疯狂内卷。一边是DeepSeek开源模型在数学竞赛中击败谷歌,另一边却是苹果的AI论文翻车导致程序员加班。这种冰火两重天的景象,让我这个学软件的不禁思考:AI到底给我们带…

11.19 jdbc

url:"jdbc:mysql://ip:端口/数据库名称" Connection=DriverMan

用C语言和文本文件实现一个简单的,可保存的通讯录

我们先思考一个通讯录都有那些信息,很明显通讯录记录的是人 人有哪些信息呢 这里我就写5个吧,分别是姓名,年龄,电话,性别,地址 然后我们把他们写成一个结构体,最好定义在头文件里,这样在使用的时候更方便 我们…

Ai元人文:价值的惊险一跃——当AI伦理告别“救火”迈向“共生”

Ai元人文:价值的惊险一跃——当AI伦理告别“救火”迈向“共生” 我们正身处一个巨大的认知裂谷之上。裂谷的一侧,是日新月异、以“数值优化”为圭臬的技术逻辑;另一侧,是古老而复杂、以“意义判断”为内核的人类价…

HarmonyOS 应用开发:深入探索截屏与录屏API的创新实践 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

11.28每日总结

今天主要的课程有人机交互技术和机器学习,人机交互的实验做完了,机器学习的实验跟着课程在做,明天去驾校报名,在剩下的大学时间里把能做的多做些

搞定多数据源 + 统一数据格式!用工厂 / 策略 / 适配器模式解决用户端与管理端协同开发痛点

作为一名后端开发,最近在做会员活动相关的用户端系统时,踩了个典型的协同开发坑:管理端和用户端并行开发,管理端负责配置活动规则,用户端需要根据配置展示活动内容,但测试数据源和生产数据源格式不统一、切换数据…

测试档案

测试1测试文章测试标头测试代码

GPU内存层次结构如何影响计算体验

本文深入探讨GPU内存层次结构对计算性能的影响,涵盖CUDA内存类型、缓存层级以及H100系列的新特性,帮助开发者优化内存访问延迟、最大化内存带宽并降低功耗,实现GPU性能的极致发挥。GPU内存层次结构:隐藏的性能瓶颈…

P13270 【模板】最小表示法

题目背景 原模板题:P1368 工艺。 题目描述 若长度为 \(n\) 的字符串 \(s\) 中可以选择一个位置 \(i\),使得 \(\overline{s_i\cdots s_ns_1\cdots s_{i-1}}=t\),则称 \(s\) 与 \(t\) 循环同构。字符串 \(s\) 的最小表…

P5357 【模板】AC 自动机

题目背景 本题原为“AC 自动机(二次加强版)”。完成本题前可以先完成 AC 自动机(简单版) 和 AC 自动机(简单版 II) 两道题,为 AC 自动机更简单的应用。 题目描述 给你一个文本串 \(S\) 和 \(n\) 个模式串 \(T_{…

分布式Session会话实现优秀的方案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Revive Adserver存储型XSS漏洞技术分析

本文详细分析了Revive Adserver广告管理系统中的存储型XSS安全漏洞,涉及inventory-retrieve.php和campaign-edit.php文件,包含漏洞复现步骤、技术原理和修复方案,已分配CVE-2025-52667编号。Revive Adserver存储型X…

2025年终总结

多好的35岁,人生黄金期,全盛时期。 2024年年终总结写道:“2024年是个好年份。今年过得真好,有滋有味。果真人生至味是清欢。2024年第一次享受平静,第一次没有大的目标、计划、挑战。只是静心生活,学习,做事。20…

局域网---局域网传输文件及共享桌面

我想要在局域网内进行文件传输以及共享桌面,可以使用文件快传:https://transfer.52python.cn/软件界面:该软件可以联网使用,可以本地部署使用:打完收工!

P2709 【模板】莫队 / 小B的询问

题目描述 小 B 有一个长为 \(n\) 的整数序列 \(a\),值域为 \([1,k]\)。 他一共有 \(m\) 个询问,每个询问给定一个区间 \([l,r]\),求: \[\sum\limits_{i=1}^k c_i^2 \]其中 \(c_i\) 表示数字 \(i\) 在 \([l,r]\) 中…

并不打算的

光和热发货的干扰星级酒店工业

P1903 【模板】带修莫队 / [国家集训队] 数颜色 / 维护队列

题目描述 墨墨购买了一套 \(N\) 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:\(Q\ L\ R\) 代表询问你从第 \(L\) 支画笔到第 \(R\) 支画笔中共有几种不同颜色的画笔…