今天就要打疫苗了 然後我現在還沒睡 掰了
明天沒看到我的文就代表真的掰了 QQ
好 今天準備的內容比較多一點
主要是前天看到學長在幫學校弄一個圖書館的登入系統
我想說能不能用 Rust Rocket Rebuild 出一個
當然 可能有部份內容不一樣 因為我根本沒看過他的 Code 想必各位讀者也不會看過
今天的 Code 頗多的
明天不太知道要講啥 我去問學長他還有什麼功能了 如果有問到應該就是繼續這個東東吧
那這篇的內容是使用 Rocket + Serde + SQLx + Chrono
閱讀前請先回去看之前的 SQLX教學配置環境 就是創造 .db檔之類的
以下是 Cargo.toml 檔
[dependencies]
chrono = "0.4.19"
rocket = { version = "0.5.0-rc.1", features = ["json"] }
serde = "1.0.130"
sqlx = { version = "0.5.7", features = [ "runtime-tokio-rustls", "sqlite" ] }
tokio = { version = "1.12.0", features = ["full"] }
anyhow = "1.0"
futures = "0.3"
然後我現在才發現 toml 會有顏色顯示
那這邊的部份會需要兩個 Struct
#[derive(Serialize, Deserialize)]
pub struct User {
username: String,
student_id: String,
pos: i32,
}
#[derive(Serialize, Deserialize)]
pub struct Input {
username: String,
student_id: String,
pos: i32,
time: String,
}
上面是 POST 資料進去我們的後端所用的 Struct
而下面是回傳以及使用資料庫的 Struct
那直接看我們 POST 的 Code
#[post("/get_in", format = "json", data = "<user>")]
async fn inside(user: Json<User>) -> Status {
let username = user.username.clone();
let student_id = user.student_id.clone();
let pos = user.pos.clone();
let time= Local::now().to_string();
sql::add_data(Input {
username,
student_id,
pos,
time,
}).await;
Status::Accepted
}
那可以看到說就跟昨天的內容很像
也就是引入內容然後 clone
其實也可以在傳入那邊去 clone 這樣會比較簡潔
而 time 那邊我使用 chrono 裡面的函數,具體用法我沒有到很清楚,我只會一些用法
要注意的地方是 因為有使用 await 所以函數要加 async
那麼切到 SQL 的部份
pub async fn add_data(data: Input) -> anyhow::Result<()> {
let pool = SqlitePool::connect(&env::var("DATABASE_URL")?).await?;
let mut conn = pool.acquire().await?;
let add = sqlx::query!(
r#"INSERT INTO student (name, student_id, pos, time) VALUES ($1, $2, $3, $4)"#, data.username, data.student_id, data.pos, data.time)
.execute(&mut conn).await?;
Ok(())
}
可以看到說跟之前講 SQLX 的時候有些差別
就是不會傳入 pool 也就是 SqlitePool
最後回傳 OK
#[get("/all_data")]
async fn search() -> Json<Vec<Input>>{
let result = sql::list_data().await;
Json(result.unwrap())
}
這邊可以看到十分的簡短
所以我們直接切到 SQL 的部份
pub async fn list_data() -> anyhow::Result<(Vec<crate::Input>)> {
let pool = SqlitePool::connect(&env::var("DATABASE_URL")?).await?;
let result = sqlx::query!(r#"
SELECT name, student_id, pos, time
FROM student
ORDER BY name
"#).fetch_all(&pool).await?;
let mut ret: Vec<crate::Input> = Vec::new();
for i in result {
ret.push(
crate::Input {
username: i.name.unwrap().clone(),
student_id: i.student_id.clone(),
pos: i.pos.parse::<i32>().unwrap().clone(),
time: i.time.clone(),
}
);
}
Ok(ret)
}
那這邊這個 SQL 用法是照官方文檔寫的 實際上也可行
下面的部份就是去將資料塞到我們最後要回傳的 Code
而上面是 Result 的部份
所以也可以看到上面 search 的函數中最後回傳是有 unwrap 的
至於下面 pos 這邊我記得好像有講過 總之就是一個能夠弄成 atoi 的方法
那既然解釋完 Code 就來看最後成品吧!
傳入資料是這兩筆
傳入後會看到後端
左邊是後端 右邊是 POST 內容
最後可以看到資料
今天先這樣 明天打 BNT 怕