Actix-Web路由

news/2025/11/26 17:42:53/文章来源:https://www.cnblogs.com/xiao987334176/p/19273171

一、路由

上一篇文章,介绍了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.mzph.cn/news/977449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务质量一目了然,十大留学机构实力排名发布

在留学热潮持续升温的当下,选择靠谱的留学机构成为学子和家长的核心诉求。优质机构能凭借专业服务为留学之路保驾护航,而资质参差不齐的机构则可能耽误申请进程。以下结合服务质量、申请成果、资源实力等核心维度,整…

请察看w_mess上的对象w_mess的open事件的第11问题

请察看w_mess上的对象w_mess的open事件的第11问题浪潮财务系统Ps版本客户端。 请察看w_mess上的对象w_mess的open事件的第11行程序,继续运行吗? 问题描述: 初始-科目设置和余额初始时,提示“......请察看W-MESS第11…

选择留学中介机构排名TOP10,口碑与实力双保障

在留学申请竞争愈发激烈的当下,靠谱的中介机构能为学子省去诸多麻烦、提升录取概率。以下这份 TOP10 留学中介排名,结合机构资质、服务质量、录取成果等核心维度评选,其中不乏口碑与实力兼具的优质选择,也有部分存…

2025 最新制氧机经销商权威推荐:国际协会测评认证,聚焦品质与服务的靠谱选择云南制氧机/昆明制氧机/美之氧制氧机/映美制氧机/鱼跃制氧机公司推荐

引言 随着全球健康管理意识的普遍提升,家庭氧疗与工业制氧需求持续攀升,制氧机已成为呼吸系统疾病护理、术后康复及工业生产的关键设备。然而,市场上产品质量参差不齐,部分产品存在出氧浓度不达标、核心部件寿命短…

选择机构不再迷茫:参考留学中介排行榜TOP10

面对五花八门的留学机构,很多同学和家长都会陷入选择困境。毕竟留学申请中,文书质量、规划专业性、服务透明度直接影响录取结果。下面结合文书服务、申请成果、资源实力等关键维度,整理出留学中介排行榜 TOP10,为大…

2025 最新呼吸机经销商推荐排行榜:国产新锐 + 实力经销商领衔,精准适配家庭医疗与康复需求云南呼吸机/昆明呼吸机/鱼跃呼吸机/博毅雅呼吸机/星脉呼吸机/海龟呼吸机公司推荐

引言 随着睡眠呼吸暂停综合征、慢阻肺等疾病发病率上升,家用呼吸机已成为家庭医疗与术后康复的刚需设备。但当前市场存在三大痛点:外资品牌价格居高不下,部分国产品牌缺乏核心技术,中小经销商服务体系不完善,导致…

2025年深圳装修公司最新推荐榜,深圳办公室装修设计、深圳酒店装修设计、深圳展厅装修设计、深圳写字楼装修设计、深圳厂房装修设计、深圳公寓装修设计、聚焦服务品质与特色业务竞争力深度剖析

随着深圳商业地产与居住空间升级需求持续增长,办公室、酒店、展厅等工装及公寓、店铺等家装需求日益多元化,消费者在选择装修公司时面临诸多困惑 —— 如何辨别企业专业资质、如何匹配自身空间的特色设计方案、如何规…

2025年效果好的助眠的口服液供货商权威推荐榜单:改善睡眠质量的产品‌/安神助眠的产品‌/效果好的助眠产品源头供货商精选

面对市场上琳琅满目的助眠产品,天然、安全且有效的口服液已成为失眠人群的新选择。 据《中国睡眠研究报告(2023)》显示,我国成年人失眠发生率高达38.2%,其中因焦虑、压力导致的入睡困难占比超60%。 在这一背景下,…

OIDC 身份提供商和 Harbor

⚙️ 配置步骤详解 要实现上述流程,你需要分别在 OIDC 身份提供商和 Harbor 两端进行配置。在 OIDC 身份提供商端配置首先,你需要在你的 OIDC 提供商(例如 KubeSphere、Keycloak 等)上将 Harbor 注册为一个客户端应…

云计算技术

云计算技术是一种基于互联网的计算模式,它将计算资源(如服务器、存储、数据库、网络、软件等)集中起来,以按需、可扩展的方式提供给用户,就像使用水电一样,随取随用,按量付费。核心特征按需自助服务:用户可随时…

[P4911]河童重工的计算机 - 题解

原题链接 题意简述 一道大模拟题,要求实现一种汇编语言的编译器。 主要操作有:内存操作 寄存器操作 函数调用 各种逻辑和数值计算 I/O 操作实现技巧 对于每一行的输入(除去注释),我们开一个结构体存函数名和各个参…

etcd 优化

蚂蚁集团运维着可能是全球最大的 K8s 集群:K8s 官方以 5k node 作为 K8s 规模化的顶峰,而蚂蚁集团事实上运维着规模达到 10k node 规模的 K8s 集群。一个形象的比喻就是,如果官方以及跟着官方的 K8s 使用者能想象到…

【LVGL】消息框部件

引言 仅作笔记,无参考价值。 消息框部件(lv_msgbox)消息框部件相关 api 函数示例程序 void event_cb(lv_event_t *e) {lv_obj_t *target = lv_event_get_current_target(e); /* 获取当前触发源,注意多了个 curren…

实用指南:Day49 | J.U.C集合-CopyOnWriteArrayList详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

深度揭秘 HBase 协同机制:HMaster、RegionServer 与 ZooKeeper 的三角之恋

深度揭秘 HBase 协同机制:HMaster、RegionServer 与 ZooKeeper 的三角之恋深度揭秘 HBase 协同机制:HMaster、RegionServer 与 ZooKeeper 的三角之恋摘要:HBase 的高可用并不是单纯靠 HMaster 指挥 RegionServer 来…

计算H和F矩阵变换图像 - MKT

计算H和F矩阵变换图像 import cv2 import numpy as np import matplotlib # 强制使用Agg后端,避免GUI问题 matplotlib.use(Agg) import matplotlib.pyplot as plt from matplotlib.patches import Polygon import os#…

级语言程序设计课程第七次个人作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/gjyycx/ 这个作业要求在哪里:https://edu.cnblogs.com/campus/fzu/gjyycx/homework/15587 学号:102500423 姓名:郑泽祥

工业相机成像基础:传感器和分辨率

工业相机是机器视觉系统中的一个关键组件,其最本质的功能就是将光信号转变成有序的电信号。它具有高的图像稳定性、高传输能力和高抗干扰能力等。工业相机中传感器和分辨率作为成像基础,决定了成像的清晰度。下面我们…

2025 全自动纸容器设备口碑厂家推荐:纸杯机、全伺服纸杯机、纸咖啡杯机及一次性纸杯生产线制造商全覆盖

随着环保理念的普及和外卖、餐饮行业的蓬勃发展,一次性纸制品市场需求持续攀升,与之配套的一次性纸杯机器全自动设备、一次性纸杯生产线及一次性杯子机器的重要性愈发凸显。对于生产企业而言,选择靠谱的设备厂家和制…

AI写论文工具助力学术创作:高效辅助工具推荐

随着人工智能技术的快速发展,AI写论文工具逐渐成为学术创作领域的重要辅助手段。这类工具通过自然语言处理、深度学习等技术,能够为用户提供大纲生成、内容润色、逻辑优化等多种功能,帮助提升写作效率,减轻学术创作…