返回文章列表

Actix-web 框架入門:核心概念與 RESTful API 構建

本文為一份 Actix-web 框架的入門指南,從其高效能的非同步特性出發,逐步拆解核心概念,並指導如何建立一個基礎的 RESTful API。內容涵蓋路由設定、處理函式編寫、應用程式狀態管理,並輔以架構圖與循序圖,幫助初學者快速掌握 Actix-web 開發。

Web 開發 Rust

在 Rust 的高效能 Web 框架中,Actix-web 以其卓越的速度和原生的非同步支援脫穎而出,成為構建現代網路服務的熱門選擇。本文將作為一份入門指南,帶領您從零開始,逐步建立一個簡單的 RESTful API,並深入解析 Actix-web 的核心概念,包括路由、處理函式 (Handler) 以及至關重要的應用程式狀態管理。

步驟一:您的第一個 Actix-web 應用

讓我們從一個最經典的 “Hello World” 範例開始,快速感受 Actix-web 的開發流程。

1. 專案設定

首先,建立一個新的 Rust 專案並加入 actix-web 依賴:

cargo new basic-server
cd basic-server
cargo add actix-web

2. 編寫伺服器程式碼

src/main.rs 中,我們將編寫一個最精簡的伺服器:

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use std::io;

// 這是一個「處理函式」(Handler),負責處理特定路由的請求
async fn health_check_handler() -> impl Responder {
    HttpResponse::Ok().json("EzyTutors is alive and kicking!")
}

#[actix_web::main]
async fn main() -> io::Result<()> {
    println!("正在監聽 http://127.0.0.1:3000");

    // 建立一個 HttpServer
    HttpServer::new(move || {
        // 建立一個 App,並設定路由
        App::new().route("/health", web::get().to(health_check_handler))
    })
    .bind("127.0.0.1:3000")?
    .run()
    .await
}

執行 cargo run 後,使用 curl http://127.0.0.1:3000/health,您將會收到一個 JSON 回應。

步驟二:核心概念拆解

剛剛的範例雖然簡單,卻包含了 Actix-web 的幾個核心元件。

圖表解說:Actix-web 核心元件關係圖

此組件圖展示了 Actix-web 應用的主要構成部分及其層次關係。

@startuml
!theme _none_
skinparam dpi auto
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam minClassWidth 100
skinparam defaultFontSize 16
title Actix-web 核心元件

node "HttpServer" {
  node "App" {
    node "Route: /health" as Route {
      node "Handler: health_check_handler" as Handler
    }
  }
}
@enduml
  • HttpServer: 負責監聽 TCP 連線,並將原始的 HTTP 請求分派給 App。它會啟動多個工作執行緒 (worker threads) 來並行處理請求。
  • App: 應用程式的核心,作為路由的容器。您可以把它想像成一個總機,負責根據請求的路徑和方法,將其轉接到對應的分機 (Handler)。
  • Route: 一條路由規則,它將一個特定的路徑 (如 /health) 和一個 HTTP 方法 (如 GET) 綁定到一個處理函式。
  • Handler: 一個非同步函式,負責處理請求的具體邏輯,並回傳一個實作了 Responder trait 的回應 (如 HttpResponse)。

圖表解說:請求處理流程

此循序圖詳細展示了一個 HTTP 請求從被接收到最終回傳的完整生命週期。

@startuml
!theme _none_
skinparam dpi auto
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam minClassWidth 100
skinparam defaultFontSize 16
title HTTP 請求處理循序圖

participant "Client" as Client
participant "HttpServer" as Server
participant "App" as App
participant "Handler" as Handler

Client -> Server : GET /health
Server -> App : 傳遞請求
App -> App : 根據路徑和方法\n匹配路由
App -> Handler : 呼叫 health_check_handler()
Handler -> Handler : 執行業務邏輯
Handler --> App : 回傳 HttpResponse
App --> Server : 回傳 HttpResponse
Server --> Client : 回應 200 OK (含 JSON Body)

@enduml

步驟三:引入應用程式狀態管理

在真實應用中,我們常需要在不同的 handler 之間共享資料,例如資料庫連線池或應用設定。這就是「應用程式狀態」(App State) 的用武之地。

1. 為何需要共享狀態?

Actix-web 的每個工作執行緒都擁有一個獨立的 App 實例。預設情況下,它們之間不共享任何資料。為了讓所有 handler 都能存取同一個資源(例如,一個全域的訪問計數器),我們需要一個執行緒安全的共享機制。

2. 定義並註冊狀態

我們定義一個 AppState 結構體,並使用 std::sync::Mutex 來保護需要被修改的資料,以確保執行緒安全。

use std::sync::Mutex;

pub struct AppState {
    pub health_check_response: String,
    pub visit_count: Mutex<u32>,
}

接著,在 main 函式中初始化 AppState,並使用 web::Data 將其註冊為應用程式的共享資料。

// 在 main 函式中
let shared_data = web::Data::new(AppState {
    health_check_response: "I'm good. You've already asked me ".to_string(),
    visit_count: Mutex::new(0),
});

HttpServer::new(move || {
    App::new()
        .app_data(shared_data.clone()) // 註冊共享狀態
        .route("/health", web::get().to(health_check_handler))
})
// ...

程式碼解說:

  • web::Data 是一個執行緒安全的智慧指標 (Arc),專為在 Actix-web 中共享狀態而設計。
  • .app_data() 方法將 web::Data 實例註冊到 App 中,使其對所有 handler 可用。

3. 在 Handler 中使用狀態

最後,我們修改 health_check_handler,使其能夠存取並修改這個共享狀態。

use actix_web::web;
use crate::state::AppState; // 假設 AppState 在 state.rs 中

pub async fn health_check_handler(app_state: web::Data<AppState>) -> impl Responder {
    let mut visit_count = app_state.visit_count.lock().unwrap();
    *visit_count += 1;

    let response = format!("{} {} times", &app_state.health_check_response, visit_count);
    HttpResponse::Ok().json(response)
}

程式碼解說:

  • app_state: web::Data<AppState>: handler 透過這個參數簽名,來「提取」(extract) 我們之前註冊的共享狀態。Actix-web 的依賴注入機制會自動完成這個過程。
  • .lock().unwrap(): 這是存取 Mutex 保護資料的標準方式。當 MutexGuard (即 visit_count) 離開作用域時,鎖會自動釋放。

透過以上步驟,您不僅建立了一個基礎的 RESTful API,更掌握了 Actix-web 框架中路由、處理函式以及狀態管理等最核心的概念,為後續開發更複雜的應用打下了堅實的基礎。