项目目录结构
在使用 hyperlane 构建生产级 Web 应用时,有效地组织代码库与编写优质代码同样重要。一个结构良好的项目目录使你的代码库更易于导航、测试和维护。本文将探讨 hyperlane 项目的推荐目录结构,并解释每个层的用途。
概览
Hyperlane 遵循分层架构模式,将关注点分离到不同的目录中。推荐的结构如下:
├── application/controller/domain/exception/mapper/middleware/model/repository/service/utils/view
├── bootstrap/application/framework
├── config/application/framework
├── plugin/database/env/logger/mysql/postgresql/process/redis
├── resources/docker/env/sql/static/templates
该结构受领域驱动设计(DDD)原则启发,适用于任何规模的项目 —— 从小型的 API 到大型企业级应用。
应用层
application 目录是你项目的核心。它包含所有业务逻辑,组织在以下几个子目录中:
Controller(控制器)
controller 目录包含你的路由处理程序 —— HTTP 请求的入口点。每个控制器对应一个特定的资源或领域概念。控制器负责接收请求、提取参数、调用适当的服务并返回响应。
在 hyperlane 中,控制器通常使用 #[route] 属性实现为结构体:
#[route("/test/{text}")]
struct Route;
控制器应该保持精简 —— 它们不应包含业务逻辑。相反,它们应将工作委托给服务层。
Domain(领域)
domain 目录保存你的核心业务实体、值对象和领域服务。这些是应用程序的基本构建块,代表你正在建模的业务概念。
Model(模型)
model 目录包含数据传输对象(DTO)、请求/响应模型,以及任何表示流经应用程序的数据形状的数据结构。这些模型用于反序列化请求体和序列化响应数据。
let json_body: T = ctx.get_request().get_body_json::<T>();
Service(服务)
service 目录是你的大部分业务逻辑所在之处。服务编排操作、执行业务规则,并协调应用程序不同部分之间的交互。它们充当控制器层和仓库层之间的桥梁。
Repository(仓库)
repository 目录包含数据访问逻辑 —— 与数据库、缓存或外部 API 交互的代码。仓库抽象了数据存储和检索的细节,为服务层提供干净的接口。
Middleware(中间件)
middleware 目录存放自定义中间件组件。在 hyperlane 中,中间件使用 ServerHook 特性实现:
struct RequestMiddleware;
impl ServerHook for RequestMiddleware {
async fn new(stream: &mut Stream, _: &mut Context) -> Self { Self }
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
ctx.get_mut_response().set_version(HttpVersion::Http1_1).set_status_code(200);
Status::Continue
}
}
server.request_middleware::<RequestMiddleware>();
常见的中间件用例包括身份验证、日志记录、CORS 处理和请求验证。
Exception 和 Mapper
exception 目录包含自定义错误类型和错误处理逻辑。mapper 目录包含在不同数据表示之间转换的函数 —— 例如,将数据库行映射到领域模型。
Utils(工具)
utils 目录用于不属于任何其他类别的共享工具函数和辅助函数。这可能包括字符串操作、日期格式化或加密辅助函数。
View(视图)
view 目录包含模板文件和与视图相关的逻辑,用于渲染 HTML 或其他格式化输出的应用程序。
引导层
bootstrap 目录包含应用程序初始化和启动代码。这是你配置和启动 hyperlane 服务器的地方:
#[tokio::main]
async fn main() {
let mut server: Server = Server::default();
let server_control_hook: ServerControlHook = server.run().await.unwrap_or_default();
server_control_hook.wait().await;
}
bootstrap/application 子目录包含应用程序特定的初始化逻辑,而 bootstrap/framework 包含框架级别的配置。
配置层
config 目录存储所有配置文件和配置加载逻辑。Hyperlane 支持基于 JSON 的配置:
let config_json = r#"{ "address": "0.0.0.0:80", "nodelay": true, "ttl": 64 }"#;
let mut server = Server::default();
server.config_from_json(config_json);
config/application 子目录保存应用程序级别的设置,而 config/framework 保存框架级别的设置,如服务器超时和缓冲区大小。
插件层
plugin 目录包含与外部系统和服务的集成:
- database/ — 数据库连接池和查询构建器
- mysql/ — MySQL 特定的数据库驱动程序和配置
- postgresql/ — PostgreSQL 特定的数据库驱动程序和配置
- redis/ — Redis 缓存集成
- logger/ — 日志框架配置
- env/ — 环境变量管理
- process/ — 进程管理工具
资源层
resources 目录包含非代码资产:
- docker/ — Docker 配置文件和 Dockerfile
- env/ — 环境配置文件
- sql/ — SQL 迁移文件和种子数据
- static/ — 静态资源,如 CSS、JavaScript 和图片
- templates/ — HTML 或文本模板
请求配置
Hyperlane 的 RequestConfig 允许你微调服务器如何处理传入的请求:
let request_config_json = r#"{ "buffer_size": 8192, "max_path_size": 8192, "max_header_count": 100, "max_header_key_size": 8192, "max_header_value_size": 8192, "max_body_size": 2097152, "read_timeout_ms": 6000 }"#;
let request_config = RequestConfig::from_json(request_config_json).unwrap();
这些设置应在 config 层中配置,并在创建服务器时应用。
服务器配置
同样,ServerConfig 控制服务器级别的行为:
let mut config: ServerConfig = ServerConfig::default();
config.set_address("0.0.0.0:80");
config.set_nodelay(Some(true));
config.set_ttl(Some(128));
将所有内容整合在一起
一个典型的 hyperlane 应用程序入口点将所有这些层联系在一起:
#[hyperlane(server: Server)]
#[hyperlane(server_config: ServerConfig)]
#[tokio::main]
async fn main() {
// 加载配置
server.server_config(server_config);
// 注册路由
server.route::<Route>("/test");
// 注册中间件
server.request_middleware::<RequestMiddleware>();
server.response_middleware::<ResponseMiddleware>();
// 启动服务器
let server_control_hook = server.run().await.unwrap_or_default();
server_control_hook.wait().await;
}
最佳实践
- 保持控制器精简 —— 业务逻辑属于服务层,而非控制器。
- 使用仓库模式 —— 通过仓库接口抽象数据访问,以便于测试。
- 将配置与代码分离 —— 对特定于环境的设置使用 JSON 配置文件。
- 利用中间件 —— 身份验证和日志记录等横切关注点应作为中间件实现。
- 遵循单一职责原则 —— 每个模块应有一个明确的用途。
- 使用属性宏 —— 通过 hyperlane 强大的属性宏系统减少样板代码。
总结
Hyperlane 项目的推荐目录结构促进了清晰的关注点分离,使你的代码库更易于理解、测试和维护。通过将代码组织到应用层、引导层、配置层、插件层和资源层中,你创建了一个可以随项目需求扩展的坚实基础。随着你对 hyperlane 的熟悉程度加深,你可以调整此结构以满足你的特定需求,同时保持清洁架构的核心原则。