引言:为什么 Rust 和 GraphQL 是理想组合
\n现代 Web 开发需要高性能和强类型。Rust 以其内存安全性和速度著称,成为构建后端的绝佳选择。而 GraphQL 则提供了一种灵活高效的数据处理方式。在本教程中,我们将使用 async-graphql 库和 actix-web 框架,用 Rust 构建一个完整的 GraphQL API。您将学习如何定义模式、编写解析器以及处理请求。
到文章结尾,您将拥有一个可运行的服务端,随时可集成到实际项目中。所有代码示例均经过验证,可直接运行。
\n\n项目配置与依赖安装
\n首先,创建一个新的 Rust 项目。请确保您已安装 Rust(建议版本 1.75+)。
\ncargo new graphql-rust-api\ncd graphql-rust-api\n打开 Cargo.toml 并添加以下依赖:
[dependencies]\nactix-web = "4"\nactix-rt = "2"\nasync-graphql = "7"\nasync-graphql-actix-web = "7"\nserde = { version = "1", features = ["derive"] }\ntokio = { version = "1", features = ["macros"] }\n运行 cargo build 以下载并编译所有依赖。首次运行可能需要几分钟。
项目结构
\n创建以下文件夹和文件结构:
\nsrc/\n├── main.rs\n├── schema.rs\n├── models.rs\n└── resolvers.rs\n我们将逐步填充每个文件。
\n\n定义 GraphQL 模型与模式
\n首先创建一个简单的数据模型。在 models.rs 中描述 User 结构体:
use serde::{Deserialize, Serialize};\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct User {\n pub id: u32,\n pub name: String,\n pub email: String,\n}\n现在转到 schema.rs。在这里定义 GraphQL 对象和查询:
use async_graphql::{Context, Object, SimpleObject};\nuse crate::models::User;\nuse crate::resolvers::get_all_users;\n\n#[derive(SimpleObject)]\npub struct UserObject {\n pub id: u32,\n pub name: String,\n pub email: String,\n}\n\npub struct QueryRoot;\n\n#[Object]\nimpl QueryRoot {\n async fn users(&self, ctx: &Context<'_>) -> Vec<UserObject> {\n let users = get_all_users(ctx).await;\n users.into_iter().map(|u| UserObject {\n id: u.id,\n name: u.name,\n email: u.email,\n }).collect()\n }\n}\n注意使用 #[derive(SimpleObject)]——这是 async-graphql 的宏,用于自动生成 GraphQL 类型。
解析器:业务逻辑
\n在 resolvers.rs 文件中实现数据获取函数。为简单起见,我们使用静态列表:
use async_graphql::Context;\nuse crate::models::User;\n\npub async fn get_all_users(_ctx: &Context<'_>) -> Vec<User> {\n vec![\n User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },\n User { id: 2, name: "Bob".into(), email: "bob@example.com".into() },\n User { id: 3, name: "Charlie".into(), email: "charlie@example.com".into() },\n ]\n}\n在实际项目中,这里可能会涉及数据库或外部 API 的调用。
\n\n在 Actix-web 上构建服务器
\n现在最关键的一步——在 main.rs 中将所有内容整合在一起:
use actix_web::{web, App, HttpServer, HttpResponse};\nuse async_graphql::{Schema, EmptyMutation, EmptySubscription};\nuse async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};\nuse crate::schema::QueryRoot;\n\nmod models;\nmod schema;\nmod resolvers;\n\ntype AppSchema = Schema<QueryRoot, EmptyMutation, EmptySubscription>;\n\nasync fn graphql_handler(\n schema