rocket已經(jīng)內(nèi)置了ORM归露,如果你不使用diesel捞烟,那么其實不需要安裝diesel产阱。
- rocket內(nèi)置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ù)庫的連接信息靠汁。
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;
- diesel遷移數(shù)據(jù)庫
diesel migration run
-
可以看到數(shù)據(jù)表生成成功了蝶怔!
-
同時會自動生成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();
}