# 健身房管理系统 API 接口设计规范 > 文档编号:GYM-API-SPEC-001 > 版本:v1.0 > 创建日期:2026-03-08 > 最后更新日期:2026-03-08 > 作者:张翔 > 状态:正式发布 ## 文档修订历史 | 版本 | 日期 | 作者 | 修订内容 | | ---- | ---------- | ---- | -------- | | v1.0 | 2026-03-08 | 张翔 | 创建 API 接口设计规范 | ## 参考文档 - RESTful API 最佳实践 - OpenAPI 3.0 规范 - Spring WebFlux 官方文档 - RSocket 规范 --- ## 一、API 设计原则 ### 1.1 RESTful 风格 **资源导向**: - 使用名词表示资源,不使用动词 - 使用 HTTP 方法表示操作 - 使用复数名词表示资源集合 **示例**: ``` ✅ GET /api/v1/members # 获取会员列表 ✅ POST /api/v1/members # 创建会员 ✅ GET /api/v1/members/{id} # 获取单个会员 ✅ PUT /api/v1/members/{id} # 更新会员 ✅ DELETE /api/v1/members/{id} # 删除会员 ❌ GET /api/v1/getMembers ❌ POST /api/v1/createMember ``` ### 1.2 版本控制 **URL 路径版本化**: ``` /api/v1/members /api/v2/members ``` **版本号规则**: - 格式:`v{主版本号}` - 主版本号递增:不兼容的 API 变更 - 向后兼容:在同一版本内添加字段 ### 1.3 响应式 API 设计 **异步非阻塞**: - 使用 Spring WebFlux 实现响应式 API - 返回类型:`Mono`(单个对象)、`Flux`(集合) - 支持 Server-Sent Events (SSE) 实时推送 **示例**: ```java // 单个资源 @GetMapping("/{id}") public Mono getMember(@PathVariable Long id) { return memberService.findById(id); } // 资源集合 @GetMapping public Flux listMembers() { return memberService.findAll(); } // SSE 实时推送 @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux streamMembers() { return memberService.streamAll(); } ``` --- ## 二、API 响应格式 ### 2.1 标准响应结构 **成功响应**: ```json { "code": 200, "message": "success", "data": { "id": 1, "name": "张三", "phone": "138****1234" }, "timestamp": "2026-03-08T10:30:00Z" } ``` **列表响应**: ```json { "code": 200, "message": "success", "data": { "items": [ { "id": 1, "name": "张三" }, { "id": 2, "name": "李四" } ], "pagination": { "page": 1, "size": 20, "total": 100, "totalPages": 5 } }, "timestamp": "2026-03-08T10:30:00Z" } ``` **错误响应**: ```json { "code": 400, "message": "参数验证失败", "errors": [ { "field": "phone", "message": "手机号格式不正确" } ], "timestamp": "2026-03-08T10:30:00Z" } ``` ### 2.2 HTTP 状态码 | 状态码 | 含义 | 使用场景 | |--------|------|----------| | 200 OK | 成功 | GET、PUT、PATCH 成功 | | 201 Created | 已创建 | POST 成功创建资源 | | 204 No Content | 无内容 | DELETE 成功 | | 400 Bad Request | 请求错误 | 参数验证失败 | | 401 Unauthorized | 未授权 | 未登录或 Token 过期 | | 403 Forbidden | 禁止访问 | 权限不足 | | 404 Not Found | 未找到 | 资源不存在 | | 409 Conflict | 冲突 | 资源已存在 | | 422 Unprocessable Entity | 不可处理 | 业务规则验证失败 | | 429 Too Many Requests | 请求过多 | 触发限流 | | 500 Internal Server Error | 服务器错误 | 系统异常 | ### 2.3 数据格式 **日期时间格式**: ``` ISO 8601: 2026-03-08T10:30:00Z 日期:2026-03-08 时间:10:30:00 ``` **数字格式**: ``` 金额:100.00 (DECIMAL) 数量:10 (INTEGER) 比例:0.15 (DECIMAL) ``` **布尔值**: ``` true/false (JSON 原生布尔值) ``` --- ## 三、API 接口分类 ### 3.1 会员管理 API #### 3.1.1 创建会员 ``` POST /api/v1/members ``` **请求体**: ```json { "phone": "13812341234", "name": "张三", "gender": 1, "birthday": "1990-01-01", "fitnessGoal": "增肌" } ``` **响应**: ```json { "code": 201, "message": "创建成功", "data": { "id": 1, "phone": "138****1234", "name": "张三" } } ``` #### 3.1.2 获取会员详情 ``` GET /api/v1/members/{id} ``` **响应**: ```json { "code": 200, "message": "success", "data": { "id": 1, "phone": "138****1234", "name": "张三", "gender": 1, "birthday": "1990-01-01", "fitnessGoal": "增肌", "status": 1, "level": 2 } } ``` #### 3.1.3 会员列表查询 ``` GET /api/v1/members ``` **查询参数**: ``` ?phone=13812341234&status=1&page=1&size=20&sort=createdAt,desc ``` **响应**: ```json { "code": 200, "message": "success", "data": { "items": [...], "pagination": { "page": 1, "size": 20, "total": 100, "totalPages": 5 } } } ``` ### 3.2 预约管理 API #### 3.2.1 创建预约 ``` POST /api/v1/bookings ``` **请求体**: ```json { "slotId": 1, "memberId": 1 } ``` **响应**: ```json { "code": 201, "message": "预约成功", "data": { "id": 1, "bookingNo": "BK202603080001", "status": 1 } } ``` #### 3.2.2 取消预约 ``` DELETE /api/v1/bookings/{id} ``` **响应**: ```json { "code": 204, "message": "取消成功" } ``` ### 3.3 订阅管理 API #### 3.3.1 开通订阅模块 ``` POST /api/v1/subscriptions ``` **请求体**: ```json { "moduleCode": "marketing", "billingCycle": 1, "startDate": "2026-03-08", "endDate": "2026-04-07" } ``` **响应**: ```json { "code": 201, "message": "开通成功", "data": { "id": 1, "subscriptionNo": "SUB202603080001", "moduleCode": "marketing", "status": 1 } } ``` --- ## 四、错误处理 ### 4.1 错误码规范 **错误码结构**: ``` 业务码 (3 位) + 错误类型码 (2 位) + 具体错误码 (2 位) ``` **示例**: ``` MEM0101 - 会员创建失败 MEM0102 - 会员手机号已存在 BOK0201 - 预约失败 BOK0202 - 预约时段已满 SUB0301 - 订阅开通失败 ``` ### 4.2 全局异常处理 **控制器建议**: ```java @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Mono> handleResourceNotFound( ResourceNotFoundException ex) { return Mono.just(ApiResponse.error(404, ex.getMessage())); } @ExceptionHandler(ValidationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Mono> handleValidationException( ValidationException ex) { return Mono.just(ApiResponse.error(400, ex.getMessage(), ex.getErrors())); } @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public Mono> handleException(Exception ex) { log.error("系统异常", ex); return Mono.just(ApiResponse.error(500, "系统繁忙,请稍后重试")); } } ``` ### 4.3 参数验证 **请求体验证**: ```java public class CreateMemberRequest { @NotBlank(message = "手机号不能为空") @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") private String phone; @NotBlank(message = "姓名不能为空") @Size(min = 1, max = 50, message = "姓名长度不能超过 50 个字符") private String name; @NotNull(message = "性别不能为空") @Min(value = 0, message = "性别值无效") @Max(value = 2, message = "性别值无效") private Integer gender; // getters and setters } ``` --- ## 五、安全设计 ### 5.1 认证机制 **JWT Token 认证**: ``` Authorization: Bearer {token} ``` **Token 结构**: ```json { "sub": "user123", "tenantId": 1, "storeId": 1, "roles": ["ADMIN"], "iat": 1709870400, "exp": 1709956800 } ``` ### 5.2 权限控制 **基于角色的访问控制 (RBAC)**: ```java @PreAuthorize("hasRole('ADMIN')") @PostMapping public Mono createMember(@RequestBody CreateMemberRequest request) { return memberService.create(request); } @PreAuthorize("hasAnyRole('ADMIN', 'COACH')") @GetMapping("/{id}") public Mono getMember(@PathVariable Long id) { return memberService.findById(id); } ``` ### 5.3 限流 **令牌桶限流**: ```java @RateLimiter(name = "apiRateLimiter") @GetMapping public Flux listMembers() { return memberService.findAll(); } ``` **配置**: ```yaml resilience4j: ratelimiter: instances: apiRateLimiter: limit-for-period: 100 # 每次允许 100 个请求 limit-refresh-period: 1s # 每秒刷新 timeout-duration: 0 # 不等待 ``` --- ## 六、API 文档 ### 6.1 OpenAPI 规范 **使用 Springdoc OpenAPI**: ```java @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("健身房管理系统 API") .version("v1") .description("健身房管理系统 RESTful API 文档")) .addSecurityItem(new SecurityRequirement().addList("bearerAuth")) .components(new Components() .addSecuritySchemes("bearerAuth", new SecurityScheme() .type(SecurityScheme.Type.HTTP) .scheme("bearer") .bearerFormat("JWT"))); } ``` ### 6.2 API 文档访问 **Swagger UI**: ``` http://localhost:8080/swagger-ui.html ``` **OpenAPI JSON**: ``` http://localhost:8080/v3/api-docs ``` --- ## 七、API 版本迁移 ### 7.1 版本兼容策略 **向后兼容**: - 添加新字段:不影响旧版本 - 添加新接口:不影响旧版本 - 扩展枚举值:不影响旧版本 **不兼容变更**: - 删除字段:需要升级版本 - 修改字段类型:需要升级版本 - 修改业务逻辑:需要升级版本 ### 7.2 版本废弃流程 1. **标记废弃**:在旧版本 API 添加 `@Deprecated` 注解 2. **通知用户**:通过文档、邮件通知升级 3. **过渡期**:至少保留 3 个月 4. **正式下线**:移除旧版本 API --- ## 八、性能优化 ### 8.1 分页优化 **游标分页**: ``` GET /api/v1/members?cursor=eyJpZCI6MTAwfQ==&size=20 ``` **优势**: - 避免深度分页性能问题 - 适合大数据量场景 ### 8.2 字段过滤 **按需返回字段**: ``` GET /api/v1/members?fields=id,name,phone ``` **优势**: - 减少网络传输 - 提升响应速度 ### 8.3 缓存策略 **HTTP 缓存头**: ``` Cache-Control: max-age=3600, public ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" Last-Modified: Wed, 08 Mar 2026 10:30:00 GMT ``` **Redis 缓存**: ```java @Cacheable(value = "members", key = "#id") public Mono findById(Long id) { return memberRepository.findById(id); } ``` --- **文档结束**