使用Rust构建GraphQL API:快速后端开发逐步教程

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程
```html

Rust 上的 GraphQL API 入门



现代 Web 开发在处理数据时需要高性能和灵活性。Rust 是一种系统编程语言,以其速度和内存安全性而闻名,而 GraphQL 是一种强大的查询语言,允许客户端只获取所需的数据。结合这些技术可以创建出极其快速且便捷的 API。



在本教程中,我们将使用流行的 crate Juniper(用于实现 GraphQL)和 Actix-web(用于 HTTP 服务器)在 Rust 上创建一个完整的 GraphQL API。您将学习如何配置项目、定义模式、实现解析器以及处理请求。



本文面向已经熟悉 Rust 基础和 Web API 基本概念的开发者。我们将使用 Rust 2021 edition 和最新的稳定版依赖项。



步骤 1:项目设置与依赖项



首先创建一个新的 Rust 项目。打开终端并执行:



cargo new graphql-rust-apicd graphql-rust-api


然后打开 Cargo.toml 文件并添加以下依赖项:



[dependencies]actix-web = "4"actix-rt = "2"juniper = "0.16"serde = { version = "1.0", features = ["derive"] }tokio = { version = "1", features = ["full"] }


  • actix-web — Rust 的异步 Web 框架。
  • juniper — 用于在 Rust 上实现 GraphQL 的库。
  • serde — 用于数据的序列化/反序列化。
  • tokio — Actix 所需的异步运行时。


更新依赖项后,执行 cargo build 以确保一切安装正确。



步骤 2:定义数据模型和 GraphQL 模式



作为示例,我们创建一个简单的“书籍”模型,包含字段:id、标题、作者和出版年份。创建文件 src/models.rs:



use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]pub struct Book { pub id: i32, pub title: String, pub author: String, pub year: i32,}


现在定义 GraphQL 模式。创建 src/graphql.rs:



use juniper::{FieldResult, GraphQLObject, GraphQLInputObject, RootNode};use crate::models::Book;

// 书籍的 GraphQL 类型(输出)#[derive(GraphQLObject)]#[graphql(description = "书籍")]pub struct BookGQL { pub id: i32, pub title: String, pub author: String, pub year: i32,}

// 用于创建书籍的输入类型#[derive(GraphQLInputObject)]#[graphql(description = "新书籍的输入数据")]pub struct NewBook { pub title: String, pub author: String, pub year: i32,}

// 内存中的“数据库”use std::sync::Mutex;lazy_static::lazy_static! { static ref BOOKS: Mutex<Vec<Book>> = Mutex::new(vec![ Book { id: 1, title: "Rust 实战".to_string(), author: "Tim McNamara".to_string(), year: 2021 }, Book { id: 2, title: "Rust 编程".to_string(), author: "Jim Blandy".to_string(), year: 2020 }, ]);}

// 根查询 (Query)pub struct QueryRoot;

#[juniper::object]impl QueryRoot { fn books() -> FieldResult<Vec<BookGQL>> { let books = BOOKS.lock().unwrap(); Ok(books.iter().map(|b| BookGQL { id: b.id, title: b.title.clone(), author: b.author.clone(), year: b.year, }).collect()) }

fn book(id: i32) -> FieldResult<BookGQL> { let books = BOOKS.lock().unwrap(); let book = books.iter().find(|b| b.id == id) .ok_or_else(|| juniper::FieldError::new("未找到书籍", graphql_value!({"code": "NOT_FOUND"})))?; Ok(BookGQL { id: book.id, ```

博客

书籍推荐