動態

詳情 返回 返回

Zino開發框架快速入門 - 動態 詳情

Zino致力於打造基於Rust語言的新一代組裝式應用開發框架,提供一站式跨平台多端解決方案,可用於後端API開發、桌面應用開發等。我們奉行『約定優於配置』的原則,提供開箱即用的功能模塊,極大提升開發效率;並通過應用接口抽象與actix-webaxumdioxusntex等框架集成,打通社區生態。

本文將以zino倉庫下的examples/axum-app為例,詳細講解怎麼使用zino框架快速開發一個後端API服務。首先是使用cargo new axum-app --bin新建一個項目,然後在Cargo.toml中添加以下依賴:
圖片
這裏我們都使用線上的版本,對於ORM選用MySQL(如果是PostgreSQL就換成orm-postgres)。進而我們在src目錄創建controllermodelrouter三個模塊(此時mod.rs中都還是空文件),在main.rs中添加以下代碼:
圖片
注意logs目錄是應用運行時自動生成的。運行cargo run(需要nightly工具鏈),此時已經能正常啓動了,在終端裏你應該能看到類似於以下的輸出:
圖片
如果不指定配置文件的話,默認運行端口就是6080。當然,目前我們還沒手動註冊任何路由,你唯一能看到的就是框架默認註冊的OpenAPI文檔頁面:
圖片
下一步我們來添加配置文件。在項目目錄下添加config目錄(注意不是src目錄下,因為配置文件不屬於源代碼),併為開發環境dev和生產環境prod創建兩個配置文件:
圖片
這裏我們新添加了一個debug服務器標籤,綁定端口6070(如果存在debug標籤,調試用的API文檔路由就會註冊到這個對應的端口)。在數據庫配置部分,我們指定了數據表創建時的namespace前綴。對於MySQL連接的配置,密碼可以先寫成明文,實際運行之後終端裏會提示你改成框架加密之後的。需要注意的是,zino框架的ORM是惰性連接的,也就是説只有在需要查詢的時候才會去連接。對於配置文件的加載,可以通過cargo run -- --env=prod來指定,也可以設置環境變量ZINO_APP_ENV。如果不指定,運行cargo run時默認為dev,運行cargo run --release時默認為prod。 下面我們在model目錄下定義兩個模型:UserTag。這個寫法都是模式化的,我們只以Tag模型為例:

use serde::{Deserialize, Serialize};
use zino::prelude::*;
use zino_derive::{ModelAccessor, ModelHooks, Schema};

#[derive(Debug, Clone, Default, Serialize, Deserialize, Schema, ModelAccessor, ModelHooks)]
#[serde(default)]
pub struct Tag {
    // Basic fields.
    #[schema(primary_key, auto_increment, readonly)]
    id: i64,
    #[schema(not_null, index_type = "text")]
    name: String,
    #[schema(default_value = "Active", index_type = "hash")]
    status: String,
    #[schema(index_type = "text")]
    description: String,

    // Info fields.
    #[schema(not_null)]
    category: String,
    #[schema(reference = "Tag")]
    parent_id: Option<i64>,

    // Revisions.
    #[schema(readonly, default_value = "now", index_type = "btree")]
    created_at: DateTime,
    #[schema(default_value = "now", index_type = "btree")]
    updated_at: DateTime,
    version: u64,
}

impl Model for Tag {
    fn read_map(&mut self, data: &Map) -> Validation {
        let mut validation = Validation::new();
        if let Some(result) = data.parse_i64("id") {
            match result {
                Ok(id) => self.id = id,
                Err(err) => validation.record_fail("id", err),
            }
        }
        if let Some(name) = data.parse_string("name") {
            self.name = name.into_owned();
        }
        if let Some(category) = data.parse_string("category") {
            self.category = category.into_owned();
        }
        if let Some(result) = data.parse_i64("parent_id") {
            match result {
                Ok(parent_id) => self.parent_id = Some(parent_id),
                Err(err) => validation.record_fail("parent_id", err),
            }
        }
        validation
    }
}

雖然代碼略有點長,但思路其實挺簡單:就是定義一個結構體,通過自動推導或手動實現這7個trait:Default, Serialize, Deserialize, Schema, ModelAccessor, ModelHooks, Model。實際上,大部分情況下我們往往都只需要手動實現Model,這個決定了怎麼從前端傳過來的數據來構造模型。當然,Model這個trait也是可以自動推導的,只是目前還沒那麼完善。模型裏的字段是和數據表對應的,如果數據表不存在則會自動創建,如果新增字段也會自動添加(當然,數據表裏的字段可以比模型裏的多)。一旦定義好模型,原則上我們可以不用寫任何controller就能直接得到增刪改查之類的接口,這是通過DefaultController來實現的:
圖片
使用起來也很簡單,直接在router/mod.rs裏引用就行:
圖片
當然,具體路由的pathmethod還是要自己指定的,這裏用到的就是axum框架標準的路由寫法,你也可以選擇自行實現一部分controller。如果你還需要一些中間件,也是按照axum框架的標準寫法,在這裏加載。 最後把這個路由註冊到main()函數裏就行了:

fn main() {
    zino::Cluster::boot()
        .register(router::routes())
        .run(Vec::new())
}

這樣你就已經生成了14個API接口!至於API文檔,我們是和實現分離的,需要寫到獨立的文件裏,這個放到以後再講。

Add a new 評論

Some HTML is okay.