当前位置: 首页 > news >正文

Actix-Web路由

一、路由

上一篇文章,介绍了Actix-Web入门知识,链接如下:https://www.cnblogs.com/xiao987334176/p/19271995

接下来介绍路由

基础路由

修改主代码 src/main.rs

use actix_web::{get, post, put, delete, web, HttpResponse};
use serde::{Deserialize, Serialize};#[derive(Serialize, Deserialize)]
struct User {id: u32,name: String,email: String,
}// GET 请求
#[get("/users")]
async fn get_users() -> HttpResponse {let users = vec![User {id: 1,name: "Alice".to_string(),email: "alice@example.com".to_string(),},User {id: 2,name: "Bob".to_string(),email: "bob@example.com".to_string(),},];HttpResponse::Ok().json(users)
}// GET 请求(带路径参数)
#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> HttpResponse {let user_id = path.into_inner();let user = User {id: user_id,name: "Alice".to_string(),email: "alice@example.com".to_string(),};HttpResponse::Ok().json(user)
}// POST 请求(创建资源)
#[post("/users")]
async fn create_user(user: web::Json<User>) -> HttpResponse {println!("创建用户: {:?}", user.name);HttpResponse::Created().json(user.into_inner())
}// PUT 请求(更新资源)
#[put("/users/{id}")]
async fn update_user(path: web::Path<u32>,user: web::Json<User>,
) -> HttpResponse {let user_id = path.into_inner();println!("更新用户 {}: {:?}", user_id, user.name);HttpResponse::Ok().json(user.into_inner())
}// DELETE 请求
#[delete("/users/{id}")]
async fn delete_user(path: web::Path<u32>) -> HttpResponse {let user_id = path.into_inner();println!("删除用户: {}", user_id);HttpResponse::NoContent().finish()
}

以上是示例代码,看不出效果。接下来,将以上接口注册到Swagger

use actix_web::{delete, get, post, put, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use utoipa::{OpenApi, ToSchema};
use utoipa_swagger_ui::SwaggerUi;#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
struct User {id: u32,name: String,email: String,
}/* ---------- hello ---------- */
#[derive(Serialize, ToSchema)]
struct HelloReply {message: String,
}/// 根路径接口
#[utoipa::path(get,path = "/",responses((status = 200, description = "Say hello", body = HelloReply)),tag = "hello"
)]
#[get("/")]
async fn hello() -> impl Responder {web::Json(HelloReply {message: "Hello, world!".to_owned(),})
}/* ---------- user ---------- */
/// 列表用户
#[utoipa::path(get,path = "/users",responses((status = 200, description = "用户列表", body = Vec<User>)),tag = "user"
)]
#[get("/users")]
async fn get_users() -> HttpResponse {HttpResponse::Ok().json(vec![User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },User { id: 2, name: "Bob".into(),   email: "bob@example.com".into() },])
}/// 根据 ID 查用户
#[utoipa::path(get,path = "/users/{id}",params(("id" = u32, Path, description = "用户主键")),responses((status = 200, description = "单个用户", body = User)),tag = "user"
)]
#[get("/users/{id}")]
async fn get_user(id: web::Path<u32>) -> HttpResponse {HttpResponse::Ok().json(User {id: *id,name: "Alice".into(),email: "alice@example.com".into(),})
}/// 新建用户
#[utoipa::path(post,path = "/users",request_body = User,responses((status = 201, description = "创建成功", body = User)),tag = "user"
)]
#[post("/users")]
async fn create_user(user: web::Json<User>) -> HttpResponse {HttpResponse::Created().json(user.into_inner())
}/// 更新用户
#[utoipa::path(put,path = "/users/{id}",params(("id" = u32, Path, description = "用户主键")),request_body = User,responses((status = 200, description = "更新成功", body = User)),tag = "user"
)]
#[put("/users/{id}")]
async fn update_user(id: web::Path<u32>, user: web::Json<User>) -> HttpResponse {let _ = id.into_inner();HttpResponse::Ok().json(user.into_inner())
}/// 删除用户
#[utoipa::path(delete,path = "/users/{id}",params(("id" = u32, Path, description = "用户主键")),responses((status = 204, description = "删除成功")),tag = "user"
)]
#[delete("/users/{id}")]
async fn delete_user(id: web::Path<u32>) -> HttpResponse {let _ = id.into_inner();HttpResponse::NoContent().finish()
}/// OpenApi 文档
#[derive(OpenApi)]
#[openapi(paths(hello, get_users, get_user, create_user, update_user, delete_user),components(schemas(HelloReply, User)),tags((name = "hello", description = "hello接口"),(name = "user",    description = "用户管理接口"))
)]
struct ApiDoc;#[actix_web::main]
async fn main() -> std::io::Result<()> {env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));log::info!("Starting HTTP server on http://127.0.0.1:8080");HttpServer::new(|| {App::new().service(hello).service(get_users).service(get_user).service(create_user).service(update_user).service(delete_user).service(SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-doc/openapi.json", ApiDoc::openapi()),)}).bind(("127.0.0.1", 8080))?.run().await
}

重新运行,访问Swagger UI:http://localhost:8080/swagger-ui/

image

这样就比较清晰了,接口做了分组显示。

先来测试列表用户,点击“Try it out”调试,可以看到返回了2条用户信息

image

查询参数与表单处理

 修改主代码 src/main.rs

use actix_web::{web,get,post, HttpResponse,HttpServer,App};
use serde::Deserialize;#[derive(Deserialize)]
struct QueryParams {page: Option<u32>,limit: Option<u32>,search: Option<String>,
}// 查询参数
#[get("/search")]
async fn search(query: web::Query<QueryParams>) -> HttpResponse {let page = query.page.unwrap_or(1);let limit = query.limit.unwrap_or(10);let search_term = query.search.as_deref().unwrap_or("");HttpResponse::Ok().json(serde_json::json!({"page": page,"limit": limit,"search": search_term,"results": []}))
}// 表单数据
#[derive(Deserialize)]
struct LoginForm {username: String,password: String,
}#[post("/login")]
async fn login(form: web::Json<LoginForm>) -> HttpResponse {println!("登录用户: {}", form.username);// 模拟验证if form.username == "admin" && form.password == "password" {HttpResponse::Ok().json(serde_json::json!({"status": "success","token": "mock-jwt-token"}))} else {HttpResponse::Unauthorized().json(serde_json::json!({"status": "error","message": "Invalid credentials"}))}
}#[actix_web::main]
async fn main() -> std::io::Result<()> {env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));log::info!("Starting HTTP server on http://127.0.0.1:8080");HttpServer::new(|| {App::new().service(search).service(login)}).bind(("127.0.0.1", 8080))?.run().await
}

重新运行,访问:http://127.0.0.1:8080/search

效果如下:

image

 

使用postman调用接口,http://127.0.0.1:8080/login

指定请求头类型为json

image

 输出json参数

{"username":"admin","password":"password"
}

请求接口,就可以得到json返回信息,效果如下

image

 

路由组织(Scope)

use actix_web::{web,get,post, HttpResponse,HttpServer,App};
use serde::Deserialize;
use actix_web::web::Path; #[derive(Deserialize)]
struct QueryParams {page: Option<u32>,limit: Option<u32>,search: Option<String>,
}// 查询参数
#[get("/search")]
async fn search(query: web::Query<QueryParams>) -> HttpResponse {let page = query.page.unwrap_or(1);let limit = query.limit.unwrap_or(10);let search_term = query.search.as_deref().unwrap_or("");HttpResponse::Ok().json(serde_json::json!({"page": page,"limit": limit,"search": search_term,"results": []}))
}// 表单数据
#[derive(Deserialize)]
struct LoginForm {username: String,password: String,
}#[post("/login")]
async fn login(form: web::Json<LoginForm>) -> HttpResponse {println!("登录用户: {}", form.username);// 模拟验证if form.username == "admin" && form.password == "password" {HttpResponse::Ok().json(serde_json::json!({"status": "success","token": "mock-jwt-token"}))} else {HttpResponse::Unauthorized().json(serde_json::json!({"status": "error","message": "Invalid credentials"}))}
}#[actix_web::main]
async fn main() -> std::io::Result<()> {env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));log::info!("Starting HTTP server on http://127.0.0.1:8080");HttpServer::new(|| {App::new()// API v1 路由组
            .service(web::scope("/api/v1").service(web::scope("/users").service(search)).service(web::scope("/posts").route("", web::get().to(get_posts)).route("/{id}", web::get().to(get_post))))// API v2 路由组
            .service(web::scope("/api/v2").service(search))}).bind(("127.0.0.1", 8080))?.run().await
}async fn get_posts() -> HttpResponse {HttpResponse::Ok().json(Vec::<String>::new())
}async fn get_post(id: Path<PostId>) -> HttpResponse {println!("收到 post id: {}", id.id);          // <-- 这里打印idHttpResponse::Ok().json(serde_json::json!({"post_id": id.id}))
}// 路径参数结构体
#[derive(serde::Deserialize)]
struct PostId {id: String,   // 如果想用 u32 也行,这里先用 String 更宽松
}

路由结构可视化:

/api/v1├── /users│   ├── GET    /          (获取用户列表)│   ├── GET    /{id}      (获取单个用户)│   ├── POST   /          (创建用户)│   ├── PUT    /{id}      (更新用户)│   └── DELETE /{id}      (删除用户)└── /posts├── GET    /          (获取文章列表)└── GET    /{id}      (获取单篇文章)

 

以上代码,可以访问以下几个接口

api v1

http://127.0.0.1:8080/api/v1/users/search

image

 http://127.0.0.1:8080/api/v1/posts

输出:[]

http://127.0.0.1:8080/api/v1/posts/123

这里会打印出id参数

image

 

api v2

http://127.0.0.1:8080/api/v2/search

image

 

 

本文参考链接:https://blog.csdn.net/sinat_41617212/article/details/154069236

 
 
http://www.jsqmd.com/news/51804/

相关文章:

  • 服务质量一目了然,十大留学机构实力排名发布
  • 请察看w_mess上的对象w_mess的open事件的第11问题
  • 选择留学中介机构排名TOP10,口碑与实力双保障
  • 2025 最新制氧机经销商权威推荐:国际协会测评认证,聚焦品质与服务的靠谱选择云南制氧机/昆明制氧机/美之氧制氧机/映美制氧机/鱼跃制氧机公司推荐
  • 选择机构不再迷茫:参考留学中介排行榜TOP10
  • 2025 最新呼吸机经销商推荐排行榜:国产新锐 + 实力经销商领衔,精准适配家庭医疗与康复需求云南呼吸机/昆明呼吸机/鱼跃呼吸机/博毅雅呼吸机/星脉呼吸机/海龟呼吸机公司推荐
  • 2025年深圳装修公司最新推荐榜,深圳办公室装修设计、深圳酒店装修设计、深圳展厅装修设计、深圳写字楼装修设计、深圳厂房装修设计、深圳公寓装修设计、聚焦服务品质与特色业务竞争力深度剖析
  • 2025年效果好的助眠的口服液供货商权威推荐榜单:改善睡眠质量的产品‌/安神助眠的产品‌/效果好的助眠产品源头供货商精选
  • OIDC 身份提供商和 Harbor
  • 云计算技术
  • [P4911]河童重工的计算机 - 题解
  • etcd 优化
  • 【LVGL】消息框部件
  • 实用指南:Day49 | J.U.C集合-CopyOnWriteArrayList详解
  • 深度揭秘 HBase 协同机制:HMaster、RegionServer 与 ZooKeeper 的三角之恋
  • 计算H和F矩阵变换图像 - MKT
  • 级语言程序设计课程第七次个人作业
  • 工业相机成像基础:传感器和分辨率
  • 2025 全自动纸容器设备口碑厂家推荐:纸杯机、全伺服纸杯机、纸咖啡杯机及一次性纸杯生产线制造商全覆盖
  • AI写论文工具助力学术创作:高效辅助工具推荐
  • 专业的北京子女抚养权律师推荐及服务解析
  • 2025 纸盘机及配套设备优质厂家合集:纸杯机、全自动纸杯机、纸盖机等靠谱制造商,创业 / 工厂省心之选
  • permutation
  • 2025英国留学机构十大口碑推荐榜!教育行业认证,唯寻国际教育摘冠
  • 中美电力对比
  • 2025 纸咖啡杯机优质制造商汇总:纸盘机、全伺服纸杯机、纸碗机等全品类 + 服务一站式覆盖
  • 评测姬
  • Kuscia 1.1.0 发布:新增带宽调度、Envoy 粘性会话与全面安全升级
  • 北京离婚股权分割律师有哪些?专业团队实力推荐
  • 推荐专业的北京离婚财产纠纷律师及相关法律服务参考