此门课程学习采用actix-web框架完成一个生产级别的rust应用,在 actix-web
中,Extractors
是一个非常重要的概念,它们用于从传入的 HTTP 请求中提取特定的信息片段。actix-web
提供了多种内置的提取器,以满足常见的使用场景。说白了,就是传入的参数怎么通过服务端的框架能提取出来。
常用的提取器及其用途(如果精通spring 或熟悉web开发本章节可以忽略):
常用的 Extractors
1. Path Extractor
-
- 用途:从请求的路径中提取动态路径段
- 示例:/users/{id}, 把id作为入参
use actix_web::{web, App, HttpResponse, HttpServer, Responder};async fn get_user(info: web::Path<(String,)>) -> impl Responder {let user_id = info.into_inner().0;HttpResponse::Ok().body(format!("User ID: {}", user_id))
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().route("/users/{id}", web::get().to(get_user))).bind("127.0.0.1:8080")?.run().await
}浏览器中输入 http://127.0.0.1:8080/users/14 返回结果如下
2. Query Extractor
- 用途:从请求的查询参数中提取信息。
- 示例
use actix_web::{web, App, HttpServer, Responder};
use serde::Deserialize;#[derive(Deserialize)]
struct Info {username: String,password: String,
}async fn login(info: web::Query<Info>) -> impl Responder {format!("Welcome, {} your password is {}!",info.username, info.password)
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().route("/login", web::get().to(login))).bind("127.0.0.1:8080")?.run().await
}
浏览器输入:http://127.0.0.1:8080/login?username=zhangsan&password=123
3. Json Extractor
- 用途:从请求体中解析 JSON 编码的数据。
- 实例
use actix_web::{web, App, HttpServer, Responder};
use serde::Deserialize;#[derive(Deserialize)]
struct User {name: String,email: String,
}async fn create_user(user: web::Json<User>) -> impl Responder {format!("User created: {}, email:{}", user.name, user.email)
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().route("/users", web::post().to(create_user))).bind("127.0.0.1:8080")?.run().await
}
用户api调试工具显示如下
4. Form Extractor
- 用途:从请求体中解析表单数据
- 示例
use actix_web::{web, App, HttpServer, Responder};
use serde::Deserialize;#[derive(Deserialize)]
struct FormData {name: String,email: String,
}async fn submit_form(form: web::Form<FormData>) -> impl Responder {format!("Form submitted: Name: {}, Email: {}", form.name, form.email)
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().route("/submit", web::post().to(submit_form))).bind("127.0.0.1:8080")?.run().await
}
用户api调试工具显示如下
编写订阅功能的代码
在Cargo.toml 文件中加入序列化依赖配置
[dependencies]
actix-web = "4"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
serde = { version = "1", features = ["derive"] }
结合我们之前所学的知识,看看改如何定义订阅处理方法
#[derive(serde::Deserialize)]
pub struct FormData {email: String,name: String,
}
async fn subscribe(_form: web::Form<FormData>) -> HttpResponse {HttpResponse::Ok().finish()
}
整体流程(原书里面写的有点啰嗦)
- 请求到达:当一个HTTP POST请求到达
/subscribe
路径时,actix-web会调用subscribe
函数来处理这个请求。 - 数据提取:
web::Form<FormData>
提取器会从请求体中读取数据,并尝试将其反序列化为FormData
结构体。这里假设请求体是URL编码的格式(例如,email=user@example.com&name=JohnDoe
)。 - 反序列化:
serde_urlencoded
库会被用于将URL编码的数据反序列化为FormData
结构体。 - 错误处理:如果反序列化失败(例如,请求体格式不正确),actix-web会自动返回一个400 Bad Request响应。
- 处理逻辑:如果反序列化成功,
subscribe
函数会被调用。在这个示例中,subscribe
函数只是简单地返回一个200 OK响应,没有实际处理FormData
中的数据。
这本书从实战的角度出发,本人结合作者的观点将学习心得记录下来,供大家学习。 本人也是在学习Rust的过程中发现问题、排查问题、解决问题,如有错误的理解,欢迎指正提出宝贵意见,这样才能进步。
注:各位亲爱的小伙伴们,今年是我从事软件行业的第20年,通过博客记录的方式将我知道的、理解的、有帮助的都分享给大家。同时,也提供就业指导,专业简历优化服务。你们的支持是我最大的动力