可复用的模式提炼
模式 1:#[inject] + #[handler(inject)]
#[inject]
pub struct LoginHandler {
auth: Arc<dyn IAuthService>,
}
#[handler(inject)]
#[async_trait]
impl IRequestHandler<LoginRequest, AuthResponse> for LoginHandler { ... }
**复用场景**:任何需要 DI 的 HTTP 端点。
模式 2:接口在 contracts,实现在 handlers
// contracts/blog.rs — 契约
pub trait IBlogService: Send + Sync {
fn list_all_posts(&self) -> Result<Vec<BlogPostSummary>, String>;
}
pub struct ListBlogPostsRequest;
#[get("/api/blog")]
impl IRequest<Vec<BlogPostSummary>> for ListBlogPostsRequest {}
// handlers/blog.rs — 实现
#[inject]
pub struct BlogService {
paths: Arc<AppPaths>,
}
impl IBlogService for BlogService { ... }
#[inject]
pub struct ListBlogPostsHandler {
blog: Arc<dyn IBlogService>,
}
**复用场景**:文档、博客、订单、通知等可替换业务模块。换存储实现时 Handler 与契约无需改动。
模式 3:IHostedService 初始化
#[inject]
pub struct DbInitService {
ctx: Arc<Mutex<DbContext>>,
docs: Arc<dyn IDocumentService>,
paths: Arc<AppPaths>,
}
**复用场景**:迁移、索引构建、资源同步——不在 `main()` 写初始化逻辑。
模式 4:薄 Handler + 厚 Service 实现
async fn handle(&self, req: GetDocIndexRequest) -> Result<DocIndex> {
self.docs.index(&req.work).map_err(|e| Error::NotFound(e))
}
Service 实现不感知 HTTP;Handler 只做参数传递与 `Error` 映射。
模式 5:组合根最小化
.register(common::bootstrap::configure) // 仅 AppPaths + DbContext
业务代码通过 `#[inject]` 在 handlers 自注册,开发时聚焦 `contracts` / `handlers` / `domain`。
模式 6:DTO 在 contracts,实体在 domain
// contracts/blog.rs
#[derive(Serialize)]
pub struct BlogPostSummary { pub slug: String, pub title: String }
// domain/comment.rs — 仅持久化实体
pub struct BlogCommentEntity { ... }
// handlers/blog_service.rs — 映射
fn to_summary(meta: &BlogPostMeta) -> BlogPostSummary { ... }
contracts 不引用 domain;domain 可通过 `use crate::contracts::…` 复用枚举。
从 Docbit 到新项目的检查清单
- [ ] `contracts` / `handlers` / `domain` 三层,无 `services/` 目录 - [ ] `I…Service` trait 在 `contracts/`,实现在 `handlers/` - [ ] `contracts` 仅依赖框架,不引用 `domain` - [ ] Handler 注入 `Arc<dyn I…Service>`,不用具体类型 - [ ] `bootstrap::configure` 只注册 DbContext、路径等基础设施 - [ ] 初始化放在 `IHostedService` - [ ] `main.rs` 仅 Host 配置 - [ ] `appsettings.json` 配置框架运行时参数 - [ ] 认证端点使用 `#[authorize]`
小结
面向接口 + 自动注册让业务开发**自动化、聚焦契约、组合根简洁**——这是 rust-webx 业务应用模板的核心价值。
下一章:[迁移指南](../16-migration/INDEX.md)