
NG是什么意思:深度解析與應(yīng)用
actix-web =
"
4
"
是一個(gè)基于 Rust 的框架,用于構(gòu)建 Web 應(yīng)用程序。
serde = "1.0.136"
是一個(gè)用于序列化和反序列化 Rust 數(shù)據(jù)結(jié)構(gòu)的框架。例如,將 Rust 結(jié)構(gòu)轉(zhuǎn)換為 JSON。
dotenv = "0.15.0"
是一個(gè)用于管理環(huán)境變量的庫(kù)。
futures = "0.3"
是一個(gè)用 Rust 進(jìn)行異步編程的庫(kù)
[dependencies.mongodb]
是用于連接 MongoDB 的驅(qū)動(dòng)程序。它還指定所需的版本和功能類(lèi)型(異步 API)。
我們需要運(yùn)行以下命令來(lái)安裝依賴項(xiàng):
cargo build
安裝項(xiàng)目依賴項(xiàng)之后,請(qǐng)修改位于src
文件夾中的main.rs
文件,將其內(nèi)容更新為以下所示:
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
HttpResponse::Ok().json("Hello from rust and mongoDB")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(hello))
.bind(("localhost", 8080))?
.run()
.await
}
上面的代碼片段執(zhí)行以下操作:
hello
的處理程序,該程序利用Rust宏來(lái)指定HTTP方法以及路由路徑/
,并且返回JSON格式的數(shù)據(jù),內(nèi)容為“Hello from rust and mongoDB
”。#[actix_web::main]
宏在Actix運(yùn)行時(shí)內(nèi)異步運(yùn)行一個(gè)main
函數(shù),該main
函數(shù)執(zhí)行以下操作:
HttpServer
服務(wù)器,該服務(wù)器通過(guò)閉包與一個(gè)App
實(shí)例相結(jié)合,用于處理傳入的請(qǐng)求。App
負(fù)責(zé)注冊(cè)各種處理程序,例如hello
處理程序。在這個(gè)架構(gòu)中,HttpServer
扮演著應(yīng)用程序核心支柱的角色,它處理請(qǐng)求、管理允許的最大連接數(shù)、實(shí)施分層安全性等關(guān)鍵任務(wù);而App
則專注于處理應(yīng)用程序邏輯,包括請(qǐng)求處理程序、中間件、路由等。localhost:8080
上的 HTTP 請(qǐng)求。接下來(lái),我們可以通過(guò)在終端中運(yùn)行以下命令來(lái)測(cè)試我們的應(yīng)用程序。
cargo run
在Rust中,模塊是一種機(jī)制,用于將代碼拆分為可重用的組件,并管理這些組件之間的可見(jiàn)性。模塊有助于我們維護(hù)項(xiàng)目,使其具有良好的結(jié)構(gòu)。
為此,我們需要導(dǎo)航到該src
文件夾??并創(chuàng)建api
、models
和repository
文件夾以及相應(yīng)的mod.rs
文件來(lái)管理可見(jiàn)性。
api
用于模塊化 API 處理程序。
models
用于模塊化數(shù)據(jù)邏輯。
repository
用于模塊化數(shù)據(jù)庫(kù)邏輯。
添加對(duì)模塊的引用
要使用模塊中的代碼,我們需要將它們聲明為模塊并將它們導(dǎo)入到main.rs
文件中。
//add the modules
mod api;
mod models;
mod repository;
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
// the remaining part of our code goes here
完成后,我們需要登錄或注冊(cè)我們的MongoDB帳戶。單擊項(xiàng)目下拉菜單,然后單擊“新建項(xiàng)目”按鈕。
輸入rust-api
為項(xiàng)目名稱,單擊Next,然后單擊Create Project..
單擊構(gòu)建數(shù)據(jù)庫(kù)
選擇共享作為數(shù)據(jù)庫(kù)類(lèi)型。
單擊“創(chuàng)建”以設(shè)置集群。這可能需要一些時(shí)間來(lái)設(shè)置。
接下來(lái),我們需要?jiǎng)?chuàng)建一個(gè)用戶來(lái)從外部訪問(wèn)數(shù)據(jù)庫(kù),輸入用戶名、密碼,然后單擊創(chuàng)建用戶。我們還需要點(diǎn)擊“添加我當(dāng)前的IP地址”按鈕,以便添加IP地址從而安全地連接到數(shù)據(jù)庫(kù)。之后,點(diǎn)擊“完成并關(guān)閉”以保存所做的更改。
保存更改后,我們應(yīng)該看到數(shù)據(jù)庫(kù)部署屏幕,如下所示:
完成配置后,我們需要將應(yīng)用程序與創(chuàng)建的數(shù)據(jù)庫(kù)連接起來(lái)。為此,請(qǐng)單擊“連接”按鈕
單擊“連接您的應(yīng)用程序”,將“驅(qū)動(dòng)程序”更改為“版本”,如下所示。然后單擊復(fù)制圖標(biāo)復(fù)制連接字符串。
設(shè)置環(huán)境變量
接下來(lái),我們需要使用之前創(chuàng)建的用戶密碼來(lái)修改復(fù)制的連接字符串,并同時(shí)更改數(shù)據(jù)庫(kù)的名稱。為了完成這個(gè)任務(wù),首先,我們需要在項(xiàng)目的根目錄下創(chuàng)建一個(gè)名為.env
的文件,并將復(fù)制的代碼片段粘貼到這個(gè)文件中。
MONGOURI=mongodb+srv://<YOUR USERNAME HERE>:<YOUR PASSWORD HERE>@cluster0.e5akf.mongodb.net/myFirstDatabese?retryWrites=true&w=majority
下面是正確填充的連接字符串的示例:
MONGOURI=mongodb+srv://malomz:malomzPassword@cluster0.e5akf.mongodb.net/golangDB?retryWrites=true&w=majority
設(shè)置完成后,我們需要?jiǎng)?chuàng)建一個(gè)模型來(lái)表示我們的應(yīng)用程序數(shù)據(jù)。為此,我們需要導(dǎo)航到該models
文件夾??,并在此文件夾中創(chuàng)建一個(gè)user_model.rs
文件并添加以下代碼片段:
use mongodb::bson::oid::ObjectId;
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct User {
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
pub id: Option<ObjectId>,
pub name: String,
pub location: String,
pub title: String,
}
上面的代碼片段執(zhí)行以下操作:
derive
宏生成對(duì)格式化輸出、序列化和反序列化數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)支持。User
具有所需屬性的結(jié)構(gòu)。我們還向?qū)傩蕴砑恿俗侄螌傩?code>id,以重命名并忽略該字段(如果該字段為空)。PS:修飾符pub
使結(jié)構(gòu)及其屬性公開(kāi),并且可以從其他文件/模塊訪問(wèn)。
接下來(lái),我們需要將user_model.rs
文件注冊(cè)為models
模塊的一部分。為此,請(qǐng)打開(kāi)位于models
文件夾中的mod.rs
文件,并添加以下代碼片段:
pub mod user_model;
創(chuàng)建用戶端點(diǎn)
模型完全設(shè)置并可供使用后,我們現(xiàn)在可以創(chuàng)建數(shù)據(jù)庫(kù)邏輯來(lái)創(chuàng)建用戶。為此,首先,我們需要導(dǎo)航到該repository
文件夾??,并在此文件夾中創(chuàng)建一個(gè)mongodb_repo.rs
文件并添加以下代碼片段:
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use mongodb::{
bson::{extjson::de::Error},
results::{ InsertOneResult},
Client, Collection,
};
use crate::models::user_model::User;
pub struct MongoRepo {
col: Collection<User>,
}
impl MongoRepo {
pub async fn init() -> Self {
dotenv().ok();
let uri = match env::var("MONGOURI") {
Ok(v) => v.to_string(),
Err(_) => format!("Error loading env variable"),
};
let client = Client::with_uri_str(uri).unwrap();
let db = client.database("rustDB");
let col: Collection<User> = db.collection("User");
MongoRepo { col }
}
pub async fn create_user(&self, new_user: User) -> Result<InsertOneResult, Error> {
let new_doc = User {
id: None,
name: new_user.name,
location: new_user.location,
title: new_user.title,
};
let user = self
.col
.insert_one(new_doc, None)
.await
.ok()
.expect("Error creating user");
Ok(user)
}
}
上面的代碼片段執(zhí)行以下操作:
MongoRepo
帶有col
字段的結(jié)構(gòu)體來(lái)訪問(wèn) MongoDB 集合MongoRepo
創(chuàng)建一個(gè)向結(jié)構(gòu)體添加方法的實(shí)現(xiàn)塊MongoRepo
結(jié)構(gòu)體的實(shí)現(xiàn)塊中添加一個(gè)方法,這個(gè)方法的作用是加載環(huán)境變量、建立到數(shù)據(jù)庫(kù)的連接,并最終返回MongoRepo
的一個(gè)實(shí)例,我們可以將這個(gè)方法命名為init
。create_user
方法,該方法接受self
和new_user
作為參數(shù)并返回創(chuàng)建的用戶或錯(cuò)誤。在該方法內(nèi)部,我們首先利用User
結(jié)構(gòu)體創(chuàng)建了一個(gè)新的文檔。接著,我們通過(guò)self
引用來(lái)訪問(wèn)MongoRepo
結(jié)構(gòu)體中的insert_one
函數(shù)(該函數(shù)作用于某個(gè)集合),以便創(chuàng)建新的用戶。在處理過(guò)程中,我們還對(duì)可能出現(xiàn)的錯(cuò)誤進(jìn)行了處理。最后,方法返回了所創(chuàng)建的用戶信息。接下來(lái),我們必須將該mongodb_repo.rs
文件注冊(cè)為repository
模塊的一部分。為了完成這個(gè)任務(wù),請(qǐng)打開(kāi)位于repository
文件夾中的mod.rs
文件,并向其中添加以下代碼片段:
pub mod mongodb_repos;
其次,我們需要?jiǎng)?chuàng)建一個(gè)處理程序,使用 create_user
中的方法來(lái)創(chuàng)建用戶。為此,我們需要導(dǎo)航到該api
文件夾??,并在此文件夾中創(chuàng)建一個(gè)user_api.rs
文件并添加以下代碼片段:
use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo};
use actix_web::{
post,
web::{Data, Json},
HttpResponse,
};
#[post("/user")]
pub async fn create_user(db: Data<MongoRepo>, new_user: Json<User>) -> HttpResponse {
let data = User {
id: None,
name: new_user.name.to_owned(),
location: new_user.location.to_owned(),
title: new_user.title.to_owned(),
};
let user_detail = db.create_user(data).await;
match user_detail {
Ok(user) => HttpResponse::Ok().json(user),
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}
上面的代碼片段執(zhí)行以下操作:
create_user
處理程序,該處理程序接受db
、 MongoRepo
的類(lèi)型和 一個(gè)new_user
作為參數(shù)。在處理程序內(nèi)部,我們創(chuàng)建了一個(gè)data
用于創(chuàng)建用戶的變量,我們應(yīng)該使用該方法將數(shù)據(jù)插入到數(shù)據(jù)庫(kù)的db.create_user
中,并根據(jù)插入操作是否成功或者是否發(fā)生錯(cuò)誤,返回相應(yīng)的響應(yīng)。PS: 定義參數(shù)時(shí)使用的 DataJson
和結(jié)構(gòu)分別用于管理跨路由共享的應(yīng)用程序狀態(tài)和從請(qǐng)求負(fù)載中提取 JSON 數(shù)據(jù)。
最后,我們需要修改應(yīng)用程序入口點(diǎn)以包含create_user
處理程序。為此,我們需要導(dǎo)航到該main.rs
文件并對(duì)其進(jìn)行修改,如下所示:
mod api;
mod models;
mod repository;
//modify imports below
use actix_web::{web::Data, App, HttpServer};
use api::user_api::{create_user};
use repository::mongodb_repo::MongoRepo;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = MongoRepo::init().await;
let db_data = Data::new(db);
HttpServer::new(move || {
App::new()
.app_data(db_data.clone())
.service(create_user)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
上面的代碼片段執(zhí)行以下操作:
db
變量以通過(guò)調(diào)用該方法建立與 MongoDB 的連接init()
,并將其添加到該Data
結(jié)構(gòu)的新實(shí)例中,以便數(shù)據(jù)庫(kù)狀態(tài)可以在整個(gè)應(yīng)用程序范圍內(nèi)可用。app_data
和service
函數(shù)將應(yīng)用程序數(shù)據(jù)和處理程序添加到App
實(shí)例。PS:關(guān)鍵字move
用于閉包中,它的作用是賦予閉包對(duì)MongoDB配置的所有權(quán)。
獲取用戶端點(diǎn)
要獲取用戶的詳細(xì)信息,我們必須首先通過(guò)get_user
向?qū)崿F(xiàn)塊mongodb_repo.rs
添加方法來(lái)修改文件。
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use mongodb::{
bson::{extjson::de::Error, oid::ObjectId, doc}, //modify here
results::{ InsertOneResult},
Client, Collection,
};
use crate::models::user_model::User;
pub struct MongoRepo {
col: Collection<User>,
}
impl MongoRepo {
pub async fn init() -> Self {
//init code goes here
}
pub async fn create_user(&self, new_user: User) -> Result<InsertOneResult, Error> {
//create_user code goes here
}
pub async fn get_user(&self, id: &String) -> Result<User, Error> {
let obj_id = ObjectId::parse_str(id).unwrap();
let filter = doc! {"_id": obj_id};
let user_detail = self
.col
.find_one(filter, None)
.await
.ok()
.expect("Error getting user's detail");
Ok(user_detail.unwrap())
}
}
上面的代碼片段執(zhí)行以下操作:
oid::ObjectId
和doc
,我們需要對(duì)依賴項(xiàng)進(jìn)行修改。get_user
方法,該方法接受self
和id
作為參數(shù)并返回用戶詳細(xì)信息或錯(cuò)誤。在方法內(nèi)部,我們將 id
轉(zhuǎn)換為 ObjectId
并將其用作過(guò)濾器來(lái)獲取匹配的文檔。然后,我們使用self
引用該MongoRepo
結(jié)構(gòu)體來(lái)訪問(wèn)find_one
集合中的函數(shù),以獲取用戶的詳細(xì)信息并處理錯(cuò)誤。最后我們返回了創(chuàng)建的用戶信息。其次,我們需要user_api.rs
通過(guò)創(chuàng)建一個(gè)處理程序來(lái)進(jìn)行修改,該處理程序使用 get_user
中的方法來(lái)repository
獲取用戶。
use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo};
use actix_web::{
post, get, //modify here
web::{Data, Json, Path}, //modify here
HttpResponse,
};
#[post("/user")]
pub async fn create_user(db: Data<MongoRepo>, new_user: Json<User>) -> HttpResponse {
//create_user code goes here
}
#[get("/user/{id}")]
pub async fn get_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
let id = path.into_inner();
if id.is_empty() {
return HttpResponse::BadRequest().body("invalid ID");
}
let user_detail = db.get_user(&id).await;
match user_detail {
Ok(user) => HttpResponse::Ok().json(user),
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}
上面的代碼片段執(zhí)行以下操作:
get
和Path
get_user
處理程序,它接收db
(數(shù)據(jù)庫(kù)連接或?qū)嵗?code>MongoRepo(數(shù)據(jù)庫(kù)操作倉(cāng)庫(kù)的實(shí)例)以及path
(路由路徑參數(shù))作為輸入。在處理程序內(nèi)部,我們首先從請(qǐng)求中提取用戶ID并存儲(chǔ)在變量id
中,然后調(diào)用db
(或MongoRepo
的)get_user
方法根據(jù)ID獲取用戶信息。若請(qǐng)求成功且用戶信息被檢索到,則返回包含用戶信息的正確響應(yīng);若請(qǐng)求失敗或發(fā)生錯(cuò)誤,則返回相應(yīng)的錯(cuò)誤響應(yīng)。最后,我們需要修改應(yīng)用程序入口點(diǎn)(main.rs
)get_user
以通過(guò)導(dǎo)入處理程序并為其添加新服務(wù)來(lái)包含該處理程序。
mod api;
mod models;
mod repository;
//modify imports below
use actix_web::{web::Data, App, HttpServer};
use api::user_api::{create_user, get_user}; //import the handler here
use repository::mongodb_repo::MongoRepo;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = MongoRepo::init().await;
let db_data = Data::new(db);
HttpServer::new(move || {
App::new()
.app_data(db_data.clone())
.service(create_user)
.service(get_user) //add this
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
編輯用戶端點(diǎn)
要編輯用戶,我們必須首先通過(guò)edit_user
向?qū)崿F(xiàn)塊mongodb_repo.rs
添加方法來(lái)修改文件。
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use mongodb::{
bson::{extjson::de::Error, oid::ObjectId, doc},
results::{ InsertOneResult, UpdateResult}, //modify here
Client, Collection,
};
use crate::models::user_model::User;
pub struct MongoRepo {
col: Collection<User>,
}
impl MongoRepo {
pub async fn init() -> Self {
//init code goes here
}
pub async fn create_user(&self, new_user: User) -> Result<InsertOneResult, Error> {
//create_user code goes here
}
pub async fn get_user(&self, id: &String) -> Result<User, Error> {
//get_user code goes here
}
pub async fn update_user(&self, id: &String, new_user: User) -> Result<UpdateResult, Error> {
let obj_id = ObjectId::parse_str(id).unwrap();
let filter = doc! {"_id": obj_id};
let new_doc = doc! {
"$set":
{
"id": new_user.id,
"name": new_user.name,
"location": new_user.location,
"title": new_user.title
},
};
let updated_doc = self
.col
.update_one(filter, new_doc, None)
.await
.ok()
.expect("Error updating user");
Ok(updated_doc)
}
}
上面的代碼片段執(zhí)行以下操作:
UpdateResult
update_user
方法,該方法接受 self
、id
和new_user
參數(shù)并返回更新的用戶詳細(xì)信息或錯(cuò)誤。在該方法內(nèi)部,我們將 id
轉(zhuǎn)換為ObjectId
,創(chuàng)建一個(gè)filter
變量來(lái)獲取我們想要更新的匹配文檔,并使用doc
宏來(lái)更新文檔字段。然后,我們使用self
引用該MongoRepo
結(jié)構(gòu)體來(lái)訪問(wèn)update_one
集合中的函數(shù),以更新filter
與指定匹配的用戶并處理錯(cuò)誤。最后我們返回了更新后的用戶信息。其次,我們需要user_api.rs
通過(guò)創(chuàng)建一個(gè)處理程序來(lái)進(jìn)行修改,該處理程序使用 中的update_user
方法repository
來(lái)更新用戶。
use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo};
use actix_web::{
post, get, put, //modify here
web::{Data, Json, Path},
HttpResponse,
};
use mongodb::bson::oid::ObjectId; //add this
#[post("/user")]
pub async fn create_user(db: Data<MongoRepo>, new_user: Json<User>) -> HttpResponse {
//create_user code goes here
}
#[get("/user/{id}")]
pub async fn get_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
//get_user code goes here
}
#[put("/user/{id}")]
pub async fn update_user(
db: Data<MongoRepo>,
path: Path<String>,
new_user: Json<User>,
) -> HttpResponse {
let id = path.into_inner();
if id.is_empty() {
return HttpResponse::BadRequest().body("invalid ID");
};
let data = User {
id: Some(ObjectId::parse_str(&id).unwrap()),
name: new_user.name.to_owned(),
location: new_user.location.to_owned(),
title: new_user.title.to_owned(),
};
let update_result = db.update_user(&id, data).await;
match update_result {
Ok(update) => {
if update.matched_count == 1 {
let updated_user_info = db.get_user(&id).await;
return match updated_user_info {
Ok(user) => HttpResponse::Ok().json(user),
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
};
} else {
return HttpResponse::NotFound().body("No user found with specified ID");
}
}
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}
上面的代碼片段執(zhí)行以下操作:
put
和ObjectId
update_user
處理程序,該處理程序接受Mongo
、Repo
、path
和db
的類(lèi)型作為參數(shù)。在處理程序內(nèi)部,我們創(chuàng)建了一個(gè)變量來(lái)獲取用戶的id?,并使用該方法通過(guò)傳入更新的用戶信息來(lái)更新數(shù)據(jù)庫(kù)中的用戶詳細(xì)信息。最后,我們會(huì)驗(yàn)證更新操作是否順利完成,并根據(jù)結(jié)果返回更新后的用戶信息或相應(yīng)的錯(cuò)誤信息(如果更新過(guò)程中出現(xiàn)了任何問(wèn)題)。最后,我們需要修改應(yīng)用程序入口點(diǎn)(main.rs
)以通過(guò)導(dǎo)入處理程序并為其添加新服務(wù)來(lái)包含該處理程序。
mod api;
mod models;
mod repository;
//modify imports below
use actix_web::{web::Data, App, HttpServer};
use api::user_api::{create_user, get_user, update_user}; //import the handler here
use repository::mongodb_repo::MongoRepo;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = MongoRepo::init().await;
let db_data = Data::new(db);
HttpServer::new(move || {
App::new()
.app_data(db_data.clone())
.service(create_user)
.service(get_user)
.service(update_user) //add this
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
刪除用戶端點(diǎn)
要?jiǎng)h除用戶,我們必須首先通過(guò)delete_user
向?qū)崿F(xiàn)塊mongodb_repo.rs
添加方法來(lái)修改文件。
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use mongodb::{
bson::{extjson::de::Error, oid::ObjectId, doc},
results::{ InsertOneResult, UpdateResult, DeleteResult}, //modify here
Client, Collection,
};
use crate::models::user_model::User;
pub struct MongoRepo {
col: Collection<User>,
}
impl MongoRepo {
pub async fn init() -> Self {
//init code goes here
}
pub async fn create_user(&self, new_user: User) -> Result<InsertOneResult, Error> {
//create_user code goes here
}
pub async fn get_user(&self, id: &String) -> Result<User, Error> {
//get_user code goes here
}
pub async fn update_user(&self, id: &String, new_user: User) -> Result<UpdateResult, Error> {
//update_user code goes here
}
pub async fn delete_user(&self, id: &String) -> Result<DeleteResult, Error> {
let obj_id = ObjectId::parse_str(id).unwrap();
let filter = doc! {"_id": obj_id};
let user_detail = self
.col
.delete_one(filter, None)
.await
.ok()
.expect("Error deleting user");
Ok(user_detail)
}
}
上面的代碼片段執(zhí)行以下操作:
DeleteResult
delete_user
方法,該方法接受 self
和id
作為參數(shù)并返回已刪除的用戶詳細(xì)信息或錯(cuò)誤。在該方法內(nèi)部,我們將 轉(zhuǎn)換id
為 ObjectId
并創(chuàng)建一個(gè)filter
變量來(lái)獲取我們要?jiǎng)h除的匹配文檔。然后,我們使用self
引用該MongoRepo
結(jié)構(gòu)體來(lái)訪問(wèn)delete_one
集合中的函數(shù),以刪除filter
與指定匹配的用戶并處理錯(cuò)誤。最后我們返回了刪除的用戶信息。接下來(lái),我們需要在user_api.rs
中創(chuàng)建一個(gè)處理程序,這個(gè)處理程序會(huì)調(diào)用repository
中的某個(gè)方法(我們假設(shè)這個(gè)方法命名為delete_user
)來(lái)刪除指定的用戶。
use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo};
use actix_web::{
post, get, put, delete, //modify here
web::{Data, Json, Path},
HttpResponse,
};
use mongodb::bson::oid::ObjectId; //add this
#[post("/user")]
pub async fn create_user(db: Data<MongoRepo>, new_user: Json<User>) -> HttpResponse {
//create_user code goes here
}
#[get("/user/{id}")]
pub async fn get_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
//get_user code goes here
}
#[put("/user/{id}")]
pub async fn update_user(
db: Data<MongoRepo>,
path: Path<String>,
new_user: Json<User>,
) -> HttpResponse {
//update_user code goes here
}
#[delete("/user/{id}")]
pub async fn delete_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
let id = path.into_inner();
if id.is_empty() {
return HttpResponse::BadRequest().body("invalid ID");
};
let result = db.delete_user(&id).await;
match result {
Ok(res) => {
if res.deleted_count == 1 {
return HttpResponse::Ok().json("User successfully deleted!");
} else {
return HttpResponse::NotFound().json("User with specified ID not found!");
}
}
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}
上面的代碼片段執(zhí)行以下操作:
delete
delete_user
處理程序,該處理程序接受Mongo
、Repo
和 path
的db
類(lèi)型作為參數(shù)。在處理程序內(nèi)部,我們創(chuàng)建了一個(gè)名為id
的變量來(lái)獲取需要?jiǎng)h除的用戶ID。然后,我們調(diào)用了repository
中的delete_user
方法,并將id
作為參數(shù)傳遞進(jìn)去,以刪除指定的用戶。最后,我們根據(jù)刪除操作的結(jié)果返回了相應(yīng)的響應(yīng)或錯(cuò)誤(如果有)。最后,我們需要修改應(yīng)用程序入口點(diǎn)(main.rs
)以通過(guò)導(dǎo)入處理程序并為其添加新服務(wù)來(lái)包含該處理程序。
mod api;
mod models;
mod repository;
//modify imports below
use actix_web::{web::Data, App, HttpServer};
use api::user_api::{create_user, get_user, update_user, delete_user}; //import the handler here
use repository::mongodb_repo::MongoRepo;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = MongoRepo::init().await;
let db_data = Data::new(db);
HttpServer::new(move || {
App::new()
.app_data(db_data.clone())
.service(create_user)
.service(get_user)
.service(update_user)
.service(delete_user) //add this
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
獲取所有用戶端點(diǎn)
要獲取用戶列表,我們必須首先通過(guò)get_all_users
向?qū)崿F(xiàn)塊mongodb_repo.rs
添加方法來(lái)修改文件。
use std::env;
extern crate dotenv;
use dotenv::dotenv;
use mongodb::{
bson::{extjson::de::Error, oid::ObjectId, doc},
results::{ InsertOneResult, UpdateResult, DeleteResult},
Client, Collection,
};
use futures::stream::TryStreamExt; //add this
use crate::models::user_model::User;
pub struct MongoRepo {
col: Collection<User>,
}
impl MongoRepo {
pub async fn init() -> Self {
//init code goes here
}
pub async fn create_user(&self, new_user: User) -> Result<InsertOneResult, Error> {
//create_user code goes here
}
pub async fn get_user(&self, id: &String) -> Result<User, Error> {
//get_user code goes here
}
pub async fn update_user(&self, id: &String, new_user: User) -> Result<UpdateResult, Error> {
//update_user code goes here
}
pub async fn delete_user(&self, id: &String) -> Result<DeleteResult, Error> {
//delete_user code goes here
}
pub async fn get_all_users(&self) -> Result<Vec<User>, Error> {
let mut cursors = self
.col
.find(None, None)
.await
.ok()
.expect("Error getting list of users");
let mut users: Vec<User> = Vec::new();
while let Some(user) = cursors
.try_next()
.await
.ok()
.expect("Error mapping through cursor")
{
users.push(user)
}
Ok(users)
}
}
上面的代碼片段添加了一個(gè)get_all_users
方法,該方法接受 a self
作為參數(shù)并返回用戶列表或錯(cuò)誤。在方法內(nèi)部,我們使用self
引用結(jié)構(gòu)MongoRepo
體從集合中訪問(wèn)find
函數(shù),無(wú)需任何過(guò)濾器,以便它可以匹配數(shù)據(jù)庫(kù)內(nèi)的所有文檔,使用該try_next()
方法循環(huán)遍歷用戶列表以最佳方式返回列表,并處理錯(cuò)誤。
其次,我們需要在user_api.rs
中創(chuàng)建一個(gè)新的處理程序,這個(gè)處理程序會(huì)利用repository
中提供的get_all_users
方法來(lái)獲取用戶列表。
use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo};
use actix_web::{
post, get, put, delete,
web::{Data, Json, Path},
HttpResponse,
};
use mongodb::bson::oid::ObjectId;
#[post("/user")]
pub async fn create_user(db: Data<MongoRepo>, new_user: Json<User>) -> HttpResponse {
//create_user code goes here
}
#[get("/user/{id}")]
pub async fn get_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
//get_user code goes here
}
#[put("/user/{id}")]
pub async fn update_user(
db: Data<MongoRepo>,
path: Path<String>,
new_user: Json<User>,
) -> HttpResponse {
//update_user code goes here
}
#[delete("/user/{id}")]
pub async fn delete_user(db: Data<MongoRepo>, path: Path<String>) -> HttpResponse {
//delet_user code goes here
}
#[get("/users")]
pub async fn get_all_users(db: Data<MongoRepo>) -> HttpResponse {
let users = db.get_all_users().await;
match users {
Ok(users) => HttpResponse::Ok().json(users),
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}
上面的代碼片段執(zhí)行以下操作:
get_all_users
使用該db.delete_user
方法獲取用戶列表的處理程序。然后,我們返回用戶列表或錯(cuò)誤(如果有)。最終,我們需要更新應(yīng)用程序的入口文件main.rs
,通過(guò)導(dǎo)入新的處理程序,并將它們作為新的服務(wù)添加到服務(wù)集合中,以確保它們能夠被正確地路由和處理。
mod api;
mod models;
mod repository;
//modify imports below
use actix_web::{web::Data, App, HttpServer};
use api::user_api::{create_user, get_user, update_user, delete_user, get_all_users}; //import the handler here
use repository::mongodb_repo::MongoRepo;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = MongoRepo::init().await;
let db_data = Data::new(db);
HttpServer::new(move || {
App::new()
.app_data(db_data.clone())
.service(create_user)
.service(get_user)
.service(update_user)
.service(delete_user)
.service(get_all_users)//add this
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
完成后,我們可以通過(guò)在終端中運(yùn)行以下命令來(lái)測(cè)試我們的應(yīng)用程序。
cargo run
這篇文章討論了如何模塊化 Rust 應(yīng)用程序、構(gòu)建 REST API 以及使用 MongoDB 保存我們的數(shù)據(jù)。
原文鏈接:https://dev.to/hackmamba/build-a-rest-api-with-rust-and-mongodb-actix-web-version-ei1
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)