关于 backend-api-design
backend-api-design 是供开发者按既定约定实现后端 API 的速查技能,涵盖 URL 模式、分层职责、响应处理、分页、错误处理和常见实现陷阱。
主要功能
- 01URL 与 HTTP 方法约定
- 02Controller、Manager 和 Repository 职责
- 03基于 Either 的错误与事务处理
- 04响应模型和分页指南
- 05Micronaut 实现注意事项
适用场景
- 01设计资源操作接口
- 02划分 API 与数据访问职责
- 03实现分页列表响应
- 04检查代码中的常见陷阱
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ c0x12c/ ai-toolkit --skill backend-api-design安装后在 Claude Code 中输入/backend-api-design确认已加载。
附带文件code-patterns.md
详细介绍
后端 API 设计——快速参考
URL 模式
GET /api/v1/employees # List (plural)
GET /api/v1/employee # Get one (?id=xxx)
POST /api/v1/employee # Create
POST /api/v1/employee/update # Update (?id=xxx)
POST /api/v1/employee/delete # Soft delete (?id=xxx)
POST /api/v1/employee/restore # Restore (?id=xxx)
POST /api/v1/sync/employees # Action
硬性规则
- 禁止使用路径参数——始终使用
@QueryValue,绝不使用@PathVariable - 单个资源使用单数形式——使用
/employee,而非/employees/{id} - 集合使用复数形式——使用
/employees - 操作使用动词子路径——
/delete、/restore、/sync
分层架构
Controller → thin, just delegates
↓
Manager → business logic, transactions, Either returns
↓
Repository → data access only, no business logic
Controller:精简封装
- 使用默认值解析查询参数
- 委托给 manager
- 使用
.throwOrValue()解包 Either - 不包含业务逻辑,也不访问 repository
Manager:业务逻辑
- 返回
Either<ClientException, T> - 使用
transaction(db.primary) { }封装数据库操作 - 协调多个 repository
- 验证业务规则
Repository:数据访问
- 返回实体或 null
- 读取使用
db.replica,写入使用db.primary - 始终检查
deletedAt.isNull()
代码快速参考
核心 controller 委托模式:
@Get("/employee")
suspend fun getEmployee(@QueryValue id: UUID): EmployeeResponse {
return employeeManager.findById(id).throwOrValue()
}
- 响应模型——在
module-client/response/{domain}/中使用companion object { fun from(entity) } - 分页——基于 offset;manager 返回包含
items、total、page、limit、hasMore的EmployeeListResponse - 错误——manager 返回
ClientError.NOT_FOUND.asException().left(),绝不抛出异常 - Factory bean——使用包含
@Singleton方法的@Factory类,将 repos 和 db 连接到 manager
完整的 controller、响应模型、分页、错误处理和 factory bean 模板,请参阅 code-patterns.md。
易错点
- 多词
@QueryValue参数必须显式指定 snake_case 名称。 前端 axios 拦截器发送project_id,但 Micronaut 会匹配参数的字面名称。应写为@QueryValue("project_id") projectId: UUID,而不是单独使用@QueryValue projectId: UUID。 - 不要使用
@Put、@Delete或@Patch。 这是 RPC 风格——所有变更操作都使用@Post。只有读取操作使用@Get。 - Controller 注入 repository 是一种代码异味。 如果你在 controller 中看到
private val fooRepository: FooRepository,请将它移到 manager 中。 - 使用
andWhere {},而不是第二个.where {}。 再次调用.where {}会替换第一个条件。使用.andWhere {}链接条件。 - 别忘了
@ExecuteOn(TaskExecutors.IO)。 缺少它时,挂起函数可能会卡住,或在错误的线程池上运行。每个 controller 都需要它。
评论
支持 Markdown