简介:为什么 GraphQL 与 C++ 是强大组合
GraphQL 已成为现代 API 的标准,相比 REST 提供了灵活性和效率。但如何在以高性能和严谨性著称的 C++ 语言中实现它呢?在本教程中,我们将使用 cppgraphqlgen 库逐步创建完整的 GraphQL API。您将学习如何定义模式、编写解析器、处理查询和变更。代码示例将注重实用性,方便您立即应用到项目中。
读完本文后,您将能够用 C++ 创建一个简单但可运行的 GraphQL 服务端,接收请求并返回数据。让我们开始吧!
安装并配置环境
我们需要准备以下工具:
- 支持 C++17 的编译器(例如 GCC 8+ 或 Clang 7+)
- CMake(3.14 以上版本)
cppgraphqlgen库(从 GraphQL 模式生成代码)- HTTP 服务端(为简单起见,使用
cpp-httplib)
我们将通过 vcpkg 安装依赖项,或手动构建。本教程使用 vcpkg:
git clone https://github.com/Microsoft/vcpkg.gitcd vcpkg./bootstrap-vcpkg.sh./vcpkg install cppgraphqlgen cpp-httplib创建项目目录结构:
graphql-cpp-tutorial/├── schema.graphql├── CMakeLists.txt├── src/│ ├── main.cpp│ ├── resolver.cpp│ └── resolver.h第一步:定义 GraphQL 模式
创建 schema.graphql 文件,包含用于管理任务的简单模式(Todo):
type Query { todos: [Todo!]! todo(id: ID!): Todo}
type Mutation { addTodo(title: String!): Todo! completeTodo(id: ID!): Todo}
type Todo { id: ID! title: String! completed: Boolean!}该模式描述了:
- Query — 获取任务列表或根据 ID 获取单个任务
- Mutation — 添加新任务和标记任务为已完成
- Todo 类型 — 包含 id、title、completed 字段的对象
模式是我们 API 的契约。接下来,我们将根据它生成 C++ 代码。
第二步:从模式生成 C++ 代码
使用来自 cppgraphqlgen 包的 graphqlgenerategen 工具:
graphqlgenerategen schema.graphql --output-dir ./generated执行后,generated 文件夹中将出现以下文件:
TodoObject.h— Todo 类型的类定义QueryObject.h— Query 解析器的基类MutationObject.h— Mutation 解析器的基类schema.h— 模式集成
这些文件包含我们需要实现的生成接口。
第三步:实现解析器
创建 resolver.h 文件,包含声明:
#include "generated/QueryObject.h"#include "generated/MutationObject.h"#include <vector>#include <memory>
struct Todo { std::string id; std::string title; bool completed;};
class QueryResolver : public graphql::todo::QueryObject {public: std::vector<std::shared_ptr<graphql::todo::TodoObject>> getTodos() const override; std::shared_ptr<graphql::todo::TodoObject> getTodo(const std::string& id) const override;
private: static std::vector<Todo> todos_;};
class MutationResolver : public graphql::todo::MutationObject {public: std::shared_ptr<graphql::todo::TodoObject> applyAddTodo(const std::string& title) override; std::shared_ptr<graphql::todo::TodoObject> applyCompleteTodo(const std::string& id) override;};现在在 resolver.cpp 中实现逻辑:
#include "