2. [Rust] rocket+diesel+mysql學(xué)習(xí)

rocket已經(jīng)內(nèi)置了ORM归露,如果你不使用diesel捞烟,那么其實不需要安裝diesel产阱。

ORM
  • rocket運行版本是nightly,所以我們需要安裝nightly版本惕虑,第一次執(zhí)行該命令會進(jìn)行下載最新版本nightly
rustup default nightly 
  • 或者你已經(jīng)安裝了nightly版本,CMD進(jìn)入項目根目錄運行這個命令庇忌,來指定當(dāng)前項目是nightl版本來運行
rustup override set nightly
  • Cargo.toml
[package]
name = "untitled"
version = "0.1.0"
authors = ["korykim <korykim@vip.qq.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rocket = "0.4.5"
diesel = { version = "1.4.5", features = ["mysql"]}
dotenv = "0.15.0"

r2d2-diesel = "1.0"
r2d2 = "0.8"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
custom_derive ="0.1.7"
[dependencies.rocket_contrib]
version = "*"
default-features = false
features = ["json"]

# Powerful date and time functionality
chrono = { version = "0.4.15", features = ["serde"] }
# For connecting with the MySQL database
diesel = { version = "1.4.2", features = ["chrono"] }
  • Rocket.toml
[development]
address = "localhost"
port = 9000
limits = { forms = 32768 }

[production]
address = "0.0.0.0"
port = 8000
#workers = [number of cpus * 2]
keep_alive = 5
log = "critical"
#secret_key = [randomly generated at launch]
limits = { forms = 32768 }
  • 在項目目錄中創(chuàng)建.env文件义屏,diesel通過讀取.env內(nèi)容來獲取連接數(shù)據(jù)庫的連接信息靠汁。
    .env
  • diesel setup
  • 創(chuàng)建users表 diesel migration generate users,執(zhí)行命令會在項目目錄中生成migrations文檔闽铐。
  • up.sql里添加內(nèi)容如下
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `first_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

up.sql
  • diesel遷移數(shù)據(jù)庫 diesel migration run
  • 可以看到數(shù)據(jù)表生成成功了蝶怔!


    數(shù)據(jù)表

    數(shù)據(jù)表內(nèi)容
  • 同時會自動生成schema文件


    schema
  • 創(chuàng)建db.rs
use diesel::mysql::MysqlConnection;
use r2d2;
use r2d2_diesel::ConnectionManager;
use rocket::http::Status;
use rocket::request::{self, FromRequest};
use rocket::{Outcome, Request, State};
use std::ops::Deref;

pub type Pool = r2d2::Pool<ConnectionManager<MysqlConnection>>;

pub fn init_pool(db_url: String) -> Pool {
    let manager = ConnectionManager::<MysqlConnection>::new(db_url);
    r2d2::Pool::new(manager).expect("db pool failure")
}

pub struct Conn(pub r2d2::PooledConnection<ConnectionManager<MysqlConnection>>);

impl<'a, 'r> FromRequest<'a, 'r> for Conn {
    type Error = ();

    fn from_request(request: &'a Request<'r>) -> request::Outcome<Conn, ()> {
        let pool = request.guard::<State<Pool>>()?;
        match pool.get() {
            Ok(conn) => Outcome::Success(Conn(conn)),
            Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
        }
    }
}

impl Deref for Conn {
    type Target = MysqlConnection;

    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
  • models.rs
use diesel;
use diesel::mysql::MysqlConnection;
use diesel::prelude::*;
use super::schema::users;
use super::schema::users::dsl::users as all_users;

// this is to get users from the database
#[derive(Serialize, Deserialize, Queryable)]
pub struct User {
    pub id: i32,
    pub username: String,
    pub password: String,
    pub first_name: String,
}

// decode request data
#[derive(Deserialize)]
pub struct UserData {
    pub username: String
}

// this is to insert users to database
#[derive(Serialize, Deserialize, Insertable)]
#[table_name = "users"]
pub struct NewUser {
    pub username: String,
    pub password: String,
    pub first_name: String,
}


impl User {
    pub fn get_all_users(conn: &MysqlConnection) -> Vec<User> {
        all_users
            .order(users::id.desc())
            .load::<User>(conn)
            .expect("error!")
    }

    pub fn insert_user(user: NewUser, conn: &MysqlConnection) -> bool {
        diesel::insert_into(users::table)
            .values(&user)
            .execute(conn)
            .is_ok()
    }


    pub fn get_user_by_username(user: UserData, conn: &MysqlConnection) -> Vec<User> {
        all_users
            .filter(users::username.eq(user.username))
            .load::<User>(conn)
            .expect("error!")
    }


    pub fn update_by_username(user: String, first_name: String, conn: &MysqlConnection) -> usize {
        let updated_row = diesel::update(all_users.filter(users::username.eq(user)))
            .set(users::first_name.eq(first_name))
            .execute(conn)
            .unwrap();
        format!("{}", updated_row).parse().unwrap()
    }

    pub fn update_all(user: User, conn: &MysqlConnection) -> Vec<User> {
        diesel::update(all_users.filter(users::id.eq(user.id)))
            .set((
                users::username.eq(user.username),
                users::password.eq(user.password),
                users::first_name.eq(user.first_name)
            ))
            .execute(conn)
            .expect("update error!");

        all_users
            .filter(users::id.eq(user.id))
            .load::<User>(conn)
            .expect("find error!")
    }

    pub fn delete_by_name(user: String, conn: &MysqlConnection) -> bool {
        diesel::delete(all_users.filter(users::username.eq(user)))
            .execute(conn)
            .is_ok()
    }
}
  • routes.rs
use super::db::Conn as DbConn;
use rocket_contrib::json::Json;
use super::models::{User, NewUser};
use serde_json::Value;
use crate::models::UserData;



#[get("/all")]
pub fn get_all(conn: DbConn) -> Json<Value> {
    Json(json!({
        "status": 200,
        "result": User::get_all_users(&conn),
    }))
}

#[get("/delete/<username>")]
pub fn delete_user(conn: DbConn, username: String) -> Json<Value> {
    let status = User::delete_by_name(username, &conn);

    Json(json!({
        "status": 200,
        "result": status,
    }))
}


#[get("/updateName/<username>/<first_name>")]
pub fn update_first_name(conn: DbConn, username: String, first_name: String) -> Json<Value> {
    let code = User::update_by_username(username, first_name, &conn);
    let message;
    if code as i32 == 1 {
        message = String::from("更新成功!")
    } else {
        message =  String::from("更新失敗!")
    }
    Json(json!({
        "status": 200,
        "code":code,
        "message": message,
    }))
}

#[post("/updateAll",format="application/json",data="<update_user>")]
pub fn updateall(conn: DbConn, update_user: Json<User>)->Json<Value>{
    Json(json!({
        "status": User::update_all(update_user.into_inner(), &conn),
        "result": "ok",
    }))
}

#[post("/newUser", format = "application/json", data = "<new_user>")]
pub fn new_user(conn: DbConn, new_user: Json<NewUser>) -> Json<Value> {
    Json(json!({
        "status": User::insert_user(new_user.into_inner(), &conn),
        "result": User::get_all_users(&conn).first(),
    }))
}

#[post("/getUser", format = "application/json", data = "<user_data>")]
pub fn find_user(conn: DbConn, user_data: Json<UserData>) -> Json<Value> {
    Json(json!({
        "status": 200,
        "result": User::get_user_by_username(user_data.into_inner(), &conn),
    }))
}
  • main.rs
#![feature(plugin, const_fn, decl_macro, proc_macro_hygiene)]
#![allow(proc_macro_derive_resolution_fallback, unused_attributes)]

#[macro_use]
extern crate diesel;
extern crate dotenv;
extern crate r2d2;
extern crate r2d2_diesel;
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

use dotenv::dotenv;
use std::env;
use routes::*;
use std::process::Command;

mod db;
mod models;
mod routes;
mod schema;

fn rocket() -> rocket::Rocket {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("set DATABASE_URL");

    let pool = db::init_pool(database_url);
    rocket::ignite()
        .manage(pool)
        .mount(
            "/api/v1/",
            routes![get_all,new_user,find_user,delete_user,update_first_name,updateall],
        )
}

fn main() {
    let _output = if cfg!(target_os = "windows") {
        Command::new("cmd")
            .args(&["/C", "cd ui && npm start"])
            .spawn()
            .expect("Failed to start UI Application")
    } else {
        Command::new("sh")
            .arg("-c")
            .arg("cd ui && npm start")
            .spawn()
            .expect("Failed to start UI Application")
    };
    rocket().launch();
}
添加用戶

查詢用戶

獲取全部

更新全部

更新 first_name
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兄墅,隨后出現(xiàn)的幾起案子踢星,更是在濱河造成了極大的恐慌,老刑警劉巖隙咸,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沐悦,死亡現(xiàn)場離奇詭異,居然都是意外死亡五督,警方通過查閱死者的電腦和手機(jī)藏否,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來充包,“玉大人副签,你說我怎么就攤上這事』” “怎么了淆储?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長愈捅。 經(jīng)常有香客問我遏考,道長,這世上最難降的妖魔是什么蓝谨? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任灌具,我火速辦了婚禮,結(jié)果婚禮上譬巫,老公的妹妹穿的比我還像新娘咖楣。我一直安慰自己,他們只是感情好芦昔,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布诱贿。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珠十。 梳的紋絲不亂的頭發(fā)上料扰,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音焙蹭,去河邊找鬼晒杈。 笑死,一個胖子當(dāng)著我的面吹牛孔厉,可吹牛的內(nèi)容都是我干的拯钻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼撰豺,長吁一口氣:“原來是場噩夢啊……” “哼粪般!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起污桦,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤亩歹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寡润,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捆憎,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年梭纹,在試婚紗的時候發(fā)現(xiàn)自己被綠了躲惰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡变抽,死狀恐怖础拨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绍载,我是刑警寧澤诡宗,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站击儡,受9級特大地震影響塔沃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜阳谍,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一蛀柴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧矫夯,春花似錦鸽疾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冒窍。三九已至,卻和暖如春豺鼻,著一層夾襖步出監(jiān)牢的瞬間综液,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工儒飒, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留意乓,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓约素,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笆凌。 傳聞我的和親對象是個殘疾皇子圣猎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345