一、开始
本文主要讲解,如何初始化一个 actix-web 项目,以及各种定义路由方式。
二、初始化一个项目
首先需要有 rust 的运行环境,使用 Rust Cargo 初始一个项目:
sh
cargo new <your_project_name>
- 添加依赖
toml
[dependencies]
actix-web = "4"
- 一个最简单的应用
rs
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(hello)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
分析:从 actix_web 包中,导入了 HTTP
相关的内容,HttpServer 用于初始化 HTTP 服务,App 用于初始化 应用服务,HttpServer 实例化的过程汇总需要一个闭包函数,在闭包函数中实例化 App, 并且在 App 中定义好路由。接下来就可以启动此服务了。
- 运行服务
sh
cargo run
三、定义路由的各种方法
3.1)route
函数单独定义
rs
use actix_web::{App, web, HttpResponse, HttpServer, Responder};
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(hello))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
此处使用 route
函数进行定义,需要 web 配合指定,方法是 get
已及它的处理函数是 hello
。
3.2)service
函数单独定义
- 以 post 方法为例
rs
use actix_web::{post, App, HttpResponse, HttpServer, Responder};
#[post("/")]
async fn echo(req_body: String) -> impl Responder {
HttpResponse::Ok().body(req_body)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(echo))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
service 与 route 不同的是, service 是通过 rust 注解的形式获取定义请求的方式和路由参数。
3.3)resource
函数成组定义
rs
pub fn resource<T: IntoPatterns>(path: T) -> Resource {
Resource::new(path)
}
- 定义资源群 resource,以下示例是:
rs
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
async fn users_list() -> impl Responder {
HttpResponse::Ok().body("List of users")
}
async fn user_info(path: web::Path<(String,)>) -> impl Responder {
let username = &path.0;
HttpResponse::Ok().body(format!("User info for: {}", username))
}
async fn create_user() -> impl Responder {
HttpResponse::Created().body("User created successfully")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::resource("/users")
.route(web::get().to(users_list)) // GET /users
.route(web::post().to(create_user)), // POST /users
)
.service(
web::resource("/users/{username}")
.route(web::get().to(user_info)), // GET /users/{username}
)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
resource 定义一个路由资源,此时就可以使用 route
方法处理不同方法的请求。在此实例中,使用 service 方法 与 web::resource 进行配合可以成组使用。service 单独使用的案例之前已经说过了。
3.4)configure
函数自定定义配置路由
rs
use actix_web::{web, App, HttpResponse, HttpServer};
fn config(cfg: &mut web::ServiceConfig) {
cfg.service(
web::resource("/app")
.route(web::get().to(|| async { HttpResponse::Ok().body("app") }))
.route(web::head().to(HttpResponse::MethodNotAllowed)),
);
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.configure(config)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
configure 方法能够定义 config
函数,在 config 函数中,获取 cfg 对象,cfg 中存在 service
, 相当于一个子服务。在模块拆分的时候非常有用。
3.5) scope
函数定义作用域
rs
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
// prefixes all resources and routes attached to it...
web::scope("/app")
// ...so this handles requests for `GET /app/index.html`
.route("/index", web::get().to(index)),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
web::scope 的用法与 web::resource 用法类似,后者针对于当前资源使用不同的方式处理,前者可以定义子路由,并指定不同的方法。scope 更加的灵活
四、小结
本文主要关注 actix-web 中定义路由的多种方式。从一个简单的示例开始,到route 函数的单独订立,然后是 service 函数定义,resource 函数定义统一方法的多重处理方式,configure 函数可以可以拆分函数配置,scope 使用作用域配置与 resource 类似,但是更加灵活。