Spire 总览
Spire(天擎)是一个基于仓颉语言开发、借鉴 ASP.NET Core 设计哲学的现代化 Web 框架。与仓颉官方团队共同研发,致力于打造轻量级、高性能、可扩展的应用开发体验。
适用场景
- 初次接触 Spire,需要建立四层架构的整体心智模型
- 需要知道各层之间的依赖关系和阅读顺序
- 需要理解框架的设计原则和统一的开发公式
核心问题
Spire 不是一堆模块的集合,而是按四层架构组织的能力体系。核心问题是:
- 每一层解决什么问题 — 基础设施层提供底座能力、宿主层管理应用生命周期、安全层贯穿认证授权、Web 层处理 HTTP 请求
- 层与层之间如何协作 — 上层依赖下层,下层不感知上层;安全层横向贯穿宿主和 Web 两层
- 开发者如何统一接入 — 所有能力收敛到
services.addXxx()+host.useXxx()的注册与使用分离模型
架构全景
四层架构
Spire 采用经典的分层设计。每一层只依赖它下面的一层,上层不知道下层的实现细节。
你的应用(Controllers / MiniAPI / 业务逻辑)
│
▼
Web 层(MVC · MiniAPI · 静态文件 · CORS · OpenAPI · 健康检查)
│
▼
安全与身份(认证 · 授权 · JWT · 认证中心)
│
▼
宿主层(通用主机 · Web 主机 · 中间件管道)
│
▼
基础设施层(DI · 配置 · 选项 · 日志 · HTTP · 缓存 · 序列化 · 对象池 · Mediator)
│
▼
仓颉运行时基础设施层
框架的底座。 九项基础设施各自解决一类通用工程问题——依赖注入组装对象、配置系统管理设置、日志记录运行时信息、HttpClient 发请求、缓存加速读取、序列化转换数据、对象池复用资源、Mediator 收敛横切逻辑。每一项都是一行 services.addXxx() 注册,DI 容器统一管理生命周期和依赖关系。
完整说明见 基础设施总览
宿主层
应用的骨骼。 通用主机提供统一的启动/停止生命周期、环境管理、配置加载;Web 主机在通用主机之上增加 HTTP 监听和中间件管道。中间件管道是请求处理的核心模型——每个请求依次经过一串中间件,每个中间件在 next() 前后都有执行机会。
安全与身份
贯穿多层的横切面。 认证(Authentication)负责"你是谁"——从 JWT 或 Cookie 中解析用户身份,挂到 context.user;授权(Authorization)负责"你能干什么"——根据 endpoint 上的权限标注校验当前用户是否有权访问。认证中心(Identity Server)提供完整的 OAuth 2.0 / OpenID Connect 令牌颁发能力。
Web 层
面向 HTTP 的能力集合。 MVC 提供结构化控制器开发;MiniAPI 提供极简端点注册;静态文件托管 SPA 构建产物;CORS 处理跨域请求;OpenAPI 自动生成 API 文档;健康检查暴露探活端点。所有 Web 能力都通过中间件注册到管道中。
完整说明见 Web 总览
能力矩阵
Spire 的能力分布在四层中,每一项解决一类开发中的常见问题。
| 层级 | 模块 | 一句话概括 | 核心接口/入口 |
|---|---|---|---|
| 基础设施 | 依赖注入 | 统一组装对象,管理生命周期 | services.addXxx() |
| 基础设施 | 配置系统 | 多源叠加,统一读取 | config["section:key"] |
| 基础设施 | 选项模式 | 强类型配置,启动期校验 | IOptions<T> |
| 基础设施 | 日志系统 | 记录与输出解耦 | ILogger |
| 基础设施 | HttpClient | 请求管道与生命周期管理 | IHttpClientFactory |
| 基础设施 | 分布式缓存 | 统一缓存接口,切换后端不改代码 | IDistributedCache |
| 基础设施 | 序列化 | 编译期宏生成,字段改一处 | @Serialization |
| 基础设施 | 对象池 | 高频对象复用,降低 GC 压力 | ObjectPool<T>.get()/put() |
| 基础设施 | Mediator | 请求与处理器解耦,横切逻辑收敛 | IMediator.send() |
| 宿主 | 通用主机 | 启动/停止、环境、配置、DI | Host.createBuilder() |
| 宿主 | Web 主机 | HTTP 监听、中间件管道 | WebHost.createBuilder() |
| 安全 | 认证 | 验 token,解析用户身份 | useAuthentication() |
| 安全 | 授权 | 验权限,放行或拦截 | useAuthorization() |
| 安全 | JWT 令牌 | 颁发和验证 JWT | JwtSecurityTokenHandler |
| 安全 | 认证中心 | OAuth 2.0 / OIDC 令牌服务 | IdentityServer |
| Web | MVC | 结构化控制器开发 | @Route["..."] + mapControllers() |
| Web | MiniAPI | 极简端点注册 | app.mapGet("/hello") { => ... } |
| Web | 静态文件 | SPA 构建产物托管 | useFileServer() |
| Web | CORS | 跨域预检与响应头处理 | useCors("策略名") |
| Web | OpenAPI | 自动生成 API 文档 | mapOpenApi() + useOpenApiUI() |
| Web | 健康检查 | 暴露探活端点 | useHealthChecks("/health") |
框架设计原则
Spire 的架构不是凭空设计的,它遵循四条原则。理解这四条原则,你就理解了几十个模块为什么是这种组织方式。
原则一:注册与使用分离
// 注册阶段(应用启动时):往 DI 容器里放东西
builder.services.addAuthentication().addJwtBearer { ... }
builder.services.addCors { ... }
// 使用阶段(请求处理时):从 DI 容器取东西,搭管道
host.useAuthentication()
host.useCors("default")add* 和 use* 不是随便选的命名——add* 往容器里放服务,use* 把服务插入请求处理管道。启动时集中注册,运行时按需取用。
原则二:中间件洋葱模型
每个请求穿过一串中间件,形成层层包裹的"洋葱":
┌──────────────────────────┐
│ ExceptionHandler │ ← 最外层 try-catch
│ ┌────────────────────┐ │
│ │ Auth │ │ ← 验 token
│ │ ┌──────────────┐ │ │
│ │ │ Controller │ │ │ ← 业务逻辑
│ │ └──────────────┘ │ │
│ └────────────────────┘ │
└──────────────────────────┘每层在 next() 调用前后都有执行机会。认证先解析用户,业务执行完日志再记录耗时——这些横切逻辑不需要 Controller 关心。
原则三:接口隔离,实现可替换
// 业务代码依赖接口,不依赖具体实现
class BlogService {
public init(cache: IDistributedCache) {} // 不是 MemoryDistributedCache
public init(http: IHttpClientFactory) {} // 不是 SocketsHttpHandler
public init(logger: ILogger) {} // 不是 ConsoleLogger
}
// 下面换什么实现,上面零改动
appsettings.json 改 "Cache:Provider": "Redis" → 全系统切换 Redis
services.addHttpMessageHandler<RetryHandler>() → 加一个重试,不碰业务代码原则四:约定优于配置
能按命名规则自动匹配的,不写配置文件;能从一个注解推导的,不手写三行。
// 约定:声明 Request 类型 → Mediator 通过接口自动找到对应 Handler
@Serialization[superType: BlogPost]
public class CreateBlogPostCommand <: IRequest<Unit> {}
// ↑ 只需声明字段;Handler 通过实现 IRequestHandler<CreateBlogPostCommand, Unit> 接口被扫描注册
public class CreateBlogPostCommandHandler <: IRequestHandler<CreateBlogPostCommand, Unit> {
public func handle(request: CreateBlogPostCommand): Unit { ... }
}
// ↑ MediatorBuilder.registerServices() 扫描包中实现了 IRequestHandler 接口的类型并注册到 DI
// Mediator.send() 从 DI 按 IRequestHandler<TRequest, TResponse> 泛型接口解析,不依赖类名约定
// 约定:@Route 注解 → 路由表一行代码扫描全部控制器
@Route["api/[controller]/[action]"]
public class BlogController <: Controller { ... }
// ↑ [controller] = Blog, [action] = getList → /api/Blog/getList无论你在 Spire 的哪一层写代码,都遵循同一条公式:
1. 定义接口/类(IOptions<T> / ILogger / DelegatingHandler / Controller / IRequestHandler)
│
2. 实现接口/继承基类(写业务逻辑) ← 你主要做这一步
│
3. 一行注册到容器(services.addXxx() / host.useXxx())
│
4. Spire 接管生命周期和依赖解析 ← 框架帮你做这些这也是为什么 博客实战项目 虽然有多组控制器、多层架构、复杂的 CQRS 管线,但每个新 Controller 加进来只需要三步:继承基类 → 打注解 → 注册模块。
当前边界
- 已覆盖:四层架构(基础设施、宿主、安全与身份、Web)的全部模块、框架设计原则、统一开发公式、能力矩阵速查
- 未覆盖:各模块的详细 API 文档、高级配置项、第三方生态的具体实现
生态共建
Spire 每一层的核心接口都为扩展预留了设计空间——不是"先有内部实现再对外开放",而是每层都先定接口,内部实现和第三方扩展站在同一条起跑线上。
| 层级 | 核心接口 | 可扩展方向 |
|---|---|---|
| 基础设施 | IDistributedCache | Redis / MongoDB / Memcached 实现 |
| 基础设施 | ILoggerProvider | 文件 / ES / Kafka / 飞书实现 |
| 基础设施 | ConfigurationProvider | Nacos / Apollo / Consul 实现 |
| 基础设施 | DelegatingHandler | 链路追踪 / 熔断 / 签名实现 |
| 基础设施 | IPipelineHandler | 日志 / 事务 / 校验 / 缓存行为实现 |
| 基础设施 | IPooledObjectPolicy<T> | 特定类型的资源复用策略 |
| 安全 | AuthenticationScheme | OAuth / SAML / LDAP 方案实现 |
| Web | IMiddleware | 自定义中间件 |
| Web | JsonConverter<T> | 自定义类型序列化 |
如果你正在为仓颉生态编写类库,请尽量基于 Spire 的接口和选项模式来设计。用户只需一行 services.addXxx(),剩下的由 Spire 接管生命周期、配置绑定和依赖解析。
推荐阅读顺序
| 顺序 | 文档 | 你学到什么 |
|---|---|---|
| 1 | 快速开始 | 5 分钟跑起来 |
| 2 | 基础设施总览 | 理解底座:DI、配置、日志、缓存怎么配合 |
| 3 | 通用主机 | 应用怎么启动、怎么配置环境、怎么优雅关闭 |
| 4 | Web 总览 | HTTP 请求怎么被处理:中间件管道、路由、MVC |
| 5 | 安全总览 | 认证授权怎么打通:JWT、Claim、Token |
| 6 | Blog 实战 | 把这些能力拼成一个完整的项目 |
读完之后,你开新项目时就知道:基础设施放哪、控制器怎么写、认证怎么接、整个项目怎么组织。