用 Hical + MySQL 5 分钟搭建 CRUD API(C++20 协程版)

用 Hical + MySQL 5 分钟搭建 CRUD API(C++20 协程版) C++ 访问数据库难吗?2026 年不再难了。本文用 Hical 的协程 DB 中间件,带你从零搭建一个完整的 MySQL CRUD API —— 连接池管理、事务自动提交/回滚、慢查询检测,全部开箱即用,代码比大多数 Python 教程还简洁。 三种姿势对比 方式 代码量 连接池 异步 防注入 裸 mysql_query 多,手动管理连接 手写 阻塞 手拼字符串,危险 ORM(如 ODB) 少,但有运行时膨胀 内置 视实现而定 安全 Hical 协程中间件 少,原生协程 内置 非阻塞 co_await PreparedStatement Hical 走第三条路:连接池是协程化的,查询全部走 PreparedStatement 防注入,事务在中间件层自动管理,业务代码只关心 SQL 逻辑。 环境准备 构建启用数据库支持 1 2 3 4 5 6 7 8 9 10 11 12 # Linux / macOS cmake -B build -DHICAL_WITH_DATABASE=ON -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc) # Windows (MSYS2 MINGW64) cmake -B build -G Ninja -DHICAL_WITH_DATABASE=ON -DCMAKE_BUILD_TYPE=Release cmake --build build # Windows (MSVC + vcpkg) cmake -B build -DHICAL_WITH_DATABASE=ON -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake cmake --build build --config Release 依赖说明 Boost >= 1.85(DB 中间件需要 Boost.MySQL,1.85 版引入 any_connection) OpenSSL(MySQL TLS 连接可选,已是框架强依赖) CMakeLists 里加一行即可: 1 2 target_link_libraries(my_app PRIVATE hical::hical_core) # HICAL_WITH_DATABASE=ON 时 hical_core 自动链接 Boost.MySQL 建表 SQL 1 2 3 4 5 6 7 8 9 10 11 CREATE DATABASE IF NOT EXISTS demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE demo; CREATE TABLE IF NOT EXISTS users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(64) NOT NULL, email VARCHAR(128) NOT NULL UNIQUE, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 完整 main.cpp 约 80 行,包含连接池初始化、中间件注册、4 个 CRUD 路由: ...

May 1, 2026 · 6 min · 1072 words

搭建 Hical HTTP 服务器 — 多平台环境搭建指南

搭建 Hical HTTP 服务器 — 多平台环境搭建指南 概述 本文档涵盖 Hical v2.0.0 在所有支持平台上的环境搭建,包括三种安装方式(vcpkg / Conan / 源码编译)和五个平台(Windows MSYS2、Windows MSVC、Ubuntu/Debian、Fedora/Arch、macOS)。 依赖要求 组件 版本要求 用途 C++ 编译器 GCC 14+ / Clang 22+ / MSVC 2022+ C++20 协程 + C++26 反射(可选) CMake >= 3.20 构建系统 Boost >= 1.70 Asio / Beast / JSON / System OpenSSL 必需 SSL/TLS 支持 Google Test 必需 单元测试 安装方式一:vcpkg(推荐) vcpkg 是最简单的安装方式,一行命令自动解决所有依赖。 安装 vcpkg(如未安装) 1 2 3 git clone https://github.com/microsoft/vcpkg.git cd vcpkg && bootstrap-vcpkg.bat # Windows cd vcpkg && ./bootstrap-vcpkg.sh # Linux / macOS 将 vcpkg 目录加入 PATH,或记住安装路径用于后续 CMAKE_TOOLCHAIN_FILE。 ...

April 22, 2026 · 5 min · 1018 words

Hical 框架应用场景全景分析

Hical 是一个现代 C++ 高性能 Web 框架,基于 Boost.Asio/Beast,具备 PMR 内存池、协程异步 I/O、WebSocket、SSL/TLS、C++26 反射层等特性。本文覆盖游戏行业 + 通用行业的全部适用场景。 一、游戏行业场景(简要) 场景 说明 GM/运营后台 REST API + 静态页面 + Session 鉴权 支付/SDK 回调网关 高并发 HTTP 接入,协程非阻塞 WebSocket 实时服务 聊天、排行榜推送、GM 监控 内部微服务 HTTP 层 MetaJson/MetaRoutes 零样板代码 二、通用行业场景 1. IoT / 嵌入式设备管理后台 ⭐ 高匹配度 为什么适合: IoT 网关和嵌入式设备普遍用 C/C++ 开发,Hical 保持语言一致性 单二进制部署,无运行时依赖,适合资源受限环境(树莓派、工控机) PMR 内存池提供可预测的内存行为,避免 GC 抖动 WebSocket 双向通信天然适合设备状态实时推送 典型用例: 设备状态监控 Dashboard(HTTP + WebSocket 推送) 固件 OTA 更新接口(Multipart 文件上传) 传感器数据采集 HTTP 接口 边缘计算节点的本地 Web 管理界面 2. 高频交易 / 量化金融辅助服务 为什么适合: ...

April 13, 2026 · 2 min · 359 words

C++26 反射落地实战:双路线条件编译实现自动路由注册、JSON 序列化与 OpenAPI 文档生成

C++26 反射落地实战:双路线条件编译实现自动路由注册、JSON 序列化与 OpenAPI 文档生成 本文以 Hical 框架(v2.5)为例,展示如何在 C++26 反射尚未被主流编译器完全支持的现阶段,用"C++26 反射 + C++20 宏回退"的双路线策略,让用户享受相同的 API——从 JSON 序列化、路由注册到 OpenAPI 3.0 文档自动生成。 问题:Web 框架中的重复样板代码 每个 Web 框架都有三大类重复劳动: 1. 路由注册——每个处理函数都要手写一行注册: 1 2 3 4 5 6 router.get("/api/users", listUsers); router.get("/api/users/{id}", getUser); router.post("/api/users", createUser); router.put("/api/users/{id}", updateUser); router.del("/api/users/{id}", deleteUser); // ... 50 个路由 = 50 行手写注册 2. JSON 序列化——每个 DTO 都要手写字段映射: 1 2 3 4 json["name"] = user.name; json["age"] = user.age; json["email"] = user.email; // ... 10 个字段 = 10 行手写映射 3. API 文档——每个接口都要手写 OpenAPI 描述,且与代码脱节: ...

April 12, 2026 · 8 min · 1516 words

为 C++ Web 框架设计三层 PMR 内存池:从原理到实战

为 C++ Web 框架设计三层 PMR 内存池:从原理到实战 本文以 Hical 框架为例,深入讲解如何利用 C++17 PMR(Polymorphic Memory Resource)为高并发 Web 服务器构建三层内存池架构。 为什么 Web 服务器需要自定义内存管理? 一个 HTTP 请求的生命周期中,框架需要分配大量临时对象:解析缓冲区、路径字符串、JSON 值、响应体。在高并发场景下(如 50K QPS),new/delete 的全局锁竞争会成为显著瓶颈: 1 2 3 50,000 请求/秒 × 每请求 ~20 次分配 = 1,000,000 次/秒 new/delete ↓ 全局堆锁竞争 → CPU 空转 传统方案是自研内存池,但 C++17 提供了标准化的解决方案 —— PMR。 PMR 速览 PMR 的核心思想:把内存分配策略从容器类型中解耦。 1 2 3 4 5 // 传统方式:分配器绑定在类型中 std::vector<int> vec; // 永远用 std::allocator // PMR 方式:运行时切换分配策略 std::pmr::vector<int> vec(&myPool); // 用自定义内存池 标准库提供了三种现成的内存资源: ...

April 12, 2026 · 3 min · 438 words

告别回调地狱:在 C++ Web 框架中全面拥抱协程

告别回调地狱:在 C++ Web 框架中全面拥抱协程 本文以 Hical 框架为例,展示如何用 C++20 协程 + Boost.Asio 构建一个全协程化的 HTTP 服务器,以及这样做的工程权衡。 回调有什么问题? 几乎所有 C++ 网络框架的 1.0 版本都是回调驱动的。一个简单的"读取请求 → 处理 → 发送响应"流程,回调版本长这样: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void onAccept(tcp::socket socket) { auto buf = std::make_shared<flat_buffer>(); auto req = std::make_shared<http::request<string_body>>(); http::async_read(socket, *buf, *req, [&socket, buf, req](error_code ec, size_t) { if (ec) return; auto res = std::make_shared<http::response<string_body>>(); // ... 处理请求,构建响应 ... http::async_write(socket, *res, [&socket, res](error_code ec, size_t) { if (ec) return; socket.shutdown(tcp::socket::shutdown_send); }); }); } 问题很明显: ...

April 12, 2026 · 3 min · 539 words

用 C++20 Concepts 设计可替换的网络后端:从 Boost.Asio 到未来的 io_uring

用 C++20 Concepts 设计可替换的网络后端:从 Boost.Asio 到未来的 io_uring 本文以 Hical 框架为例,展示如何用 C++20 Concepts 约束网络后端接口,实现编译期类型安全的后端抽象。 问题:网络后端绑定的困境 大多数 C++ 网络框架和底层网络库深度绑定。Drogon 绑定 Trantor,muduo 绑定自研的 EventLoop。一旦想换后端(比如从 epoll 切到 io_uring),基本等于重写。 原因是传统的抽象手段——虚函数继承——有两个问题: 运行时开销:每次调用都经过 vtable 接口松散:基类定义了接口,但"你的实现是否真的完整?“只能在链接期或运行时才知道 Concepts:编译期的接口约束 C++20 Concepts 提供了一种具名约束机制——在编译期验证类型是否满足一组要求: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 template <typename T> concept EventLoopLike = requires(T loop, std::function<void()> func, double delay) { { loop.run() } -> std::same_as<void>; { loop.stop() } -> std::same_as<void>; { loop.isRunning() } -> std::convertible_to<bool>; { loop.post(func) } -> std::same_as<void>; { loop.dispatch(func) } -> std::same_as<void>; { loop.runAfter(delay, func) } -> std::convertible_to<uint64_t>; { loop.runEvery(delay, func) } -> std::convertible_to<uint64_t>; { loop.cancelTimer(uint64_t{}) } -> std::same_as<void>; { loop.isInLoopThread() } -> std::convertible_to<bool>; { loop.index() } -> std::convertible_to<size_t>; { loop.allocator() } -> std::same_as<std::pmr::polymorphic_allocator<std::byte>>; }; 如果某个类型缺少 run() 方法或返回类型不对,编译器立即报错,而不是在链接时给出晦涩的"未定义引用”。 ...

April 12, 2026 · 3 min · 580 words

用 if constexpr + 模板在一份代码中同时处理 TCP 和 SSL 连接

用 if constexpr + 模板在一份代码中同时处理 TCP 和 SSL 连接 本文以 Hical 框架的 GenericConnection 为例,展示如何用 C++17 的 if constexpr + 类型萃取在一个模板类中统一 TCP 和 SSL 两种连接,实现编译期零开销分支。 问题:TCP 和 SSL 的代码高度相似 TCP 连接和 SSL 连接的区别只有三处: socket 类型不同:tcp::socket vs ssl::stream<tcp::socket> 连接建立多一步 TLS 握手 关闭多一步 ssl::stream::async_shutdown 其余 99% 的代码——读循环、写循环、缓冲区管理、回调触发、状态机——完全相同。 传统方案:继承 + 虚函数 1 2 3 4 5 6 7 8 9 class TcpConnection : public Connection { tcp::socket socket_; void doRead() override { ... } }; class SslConnection : public Connection { ssl::stream<tcp::socket> socket_; void doRead() override { ... } // 几乎一样的代码 }; 问题: 两个类 90% 的代码重复 每次调用 doRead/doWrite 都经过虚函数表间接调用 修改共同逻辑需要同步两处 Hical 方案:一个模板统一 1 2 3 4 5 6 7 8 9 template <typename SocketType> class GenericConnection : public TcpConnection { SocketType socket_; // 一份读循环、一份写循环、一份状态机 // 差异部分用 if constexpr 处理 }; using PlainConnection = GenericConnection<tcp::socket>; using SslConnection = GenericConnection<ssl::stream<tcp::socket>>; 核心技术:类型萃取 + if constexpr 类型萃取:编译期判断 socket 类型 1 2 3 4 5 6 7 8 template <typename T> struct IsSslStream : std::false_type {}; template <typename T> struct IsSslStream<boost::asio::ssl::stream<T>> : std::true_type {}; template <typename T> inline constexpr bool hIsSslStream = IsSslStream<T>::value; 这是一个经典的模板特化技巧: ...

April 12, 2026 · 3 min · 567 words