应用接口抽象

Zino框架的应用接口抽象由Application trait定义,它包含一个关联类型和两个必须实现的方法:

pub trait Application {
    type Routes;

    fn register(self, routes: Self::Routes) -> Self;
    fn run_with<T: AsyncScheduler + Send + 'static>(self, scheduler: T);
}

其中register用来注册路由,run_with用来加载异步任务并运行应用。 需要注意的是,异步任务的执行涉及到异步运行时的选择, 而zino-core本身并没有限定只能使用特定的运行时1, 所以需要实现者自行在run_with方法的实现中指定。对于同步任务,不涉及到异步运行时的选择, 我们就在Applicationspawn方法中提供了默认实现。

这就是Zino框架的起点!我们只要给其他Web框架实现这个trait,就能把这个框架的功能集成到Zino中,并使应用的启动方式保存一致:

mod router;
mod schedule;

use zino::prelude::*;

fn main() {
    zino::Cluster::boot()
        .register(router::routes())
        .register_debug(router::debug_routes())
        .spawn(schedule::job_scheduler())
        .run_with(schedule::async_job_scheduler())
}

目前我们已经为actix-webaxumdioxus-desktop实现了Application trait, 它们对应的关联类型Routes分别为:

  • actix-web:引入ActixCluster类型,基于ServiceConfig来定义路由。

    pub type RouterConfigure = fn(cfg: &mut actix_web::web::ServiceConfig);
    
    impl Application for ActixCluster {
        type Routes = Vec<RouterConfigure>;
    }
  • axum:引入AxumCluster类型,基于Router来定义路由。

    impl Application for AxumCluster {
        type Routes = Vec<axum::Router>;
    }
  • dioxus-desktop:引入DioxusDesktop<R>类型,基于Routable泛型约束来定义路由。

    impl Application for DioxusDesktop<R>
    where
        R: dioxus_router::routable::Routable,
        <R as FromStr>::Err: Display,
    {
        type Routes = R;
    }

可以看到,在以上框架的Application实现中,我们并没有定义自己的路由类型, 这就使得actix-webaxum中的路由、中间件可以直接在我们的Zino框架中使用。 确保充分理解了这一点,对我们的应用开发至关重要。

1

虽然大部分情况下我们还是会优先选择tokio