# Design Document ## Overview 本设计文档描述 HoneyBox 抽奖系统 .NET 8 Web API 项目基础架构的技术实现方案。采用四层架构设计,使用 Autofac 进行依赖注入,Mapster 进行对象映射,Serilog 进行日志记录,Redis 进行分布式缓存。 ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ HoneyBox.Api │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Controllers │ │ Filters │ │ Middlewares │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────────┐ │ HoneyBox.Core │ │ HoneyBox.Model │ │ ┌─────────────────┐ │ │ ┌─────────────────────┐ │ │ │ Services │ │ │ │ Entities │ │ │ ├─────────────────┤ │ │ ├─────────────────────┤ │ │ │ Interfaces │ │ │ │ Models │ │ │ ├─────────────────┤ │ │ ├─────────────────────┤ │ │ │ Mappings │ │ │ │ Data │ │ │ └─────────────────┘ │ │ ├─────────────────────┤ │ └─────────────────────────┘ │ │ Base │ │ │ │ └─────────────────────┘ │ ▼ └─────────────────────────────┘ ┌─────────────────────────┐ │ HoneyBox.Infrastructure │ │ ┌─────────────────┐ │ │ │ Cache │ │ │ ├─────────────────┤ │ │ │ External │ │ │ ├─────────────────┤ │ │ │ Modules │ │ │ └─────────────────┘ │ └─────────────────────────┘ ``` ### 依赖关系 ``` Api → Core, Model Core → Model, Infrastructure Infrastructure → 无依赖 Model → 无依赖 ``` ## Components and Interfaces ### HoneyBox.Model 组件 #### ApiResponse 基类 ```csharp // Base/ApiResponse.cs public class ApiResponse { public int Code { get; set; } public string Msg { get; set; } = string.Empty; public static ApiResponse Success(string msg = "success"); public static ApiResponse Fail(string msg, int code = -1); } public class ApiResponse : ApiResponse { public T? Data { get; set; } public static ApiResponse Success(T data, string msg = "success"); public new static ApiResponse Fail(string msg, int code = -1); } ``` #### HoneyBoxDbContext ```csharp // Data/HoneyBoxDbContext.cs public partial class HoneyBoxDbContext : DbContext { public HoneyBoxDbContext(DbContextOptions options); public virtual DbSet Users { get; set; } public virtual DbSet Goods { get; set; } public virtual DbSet Orders { get; set; } // ... 其他 DbSet } ``` ### HoneyBox.Infrastructure 组件 #### ICacheService 接口 ```csharp // Cache/ICacheService.cs public interface ICacheService { Task GetAsync(string key); Task SetAsync(string key, T value, TimeSpan? expiry = null); Task RemoveAsync(string key); Task ExistsAsync(string key); Task IsConnectedAsync(); } ``` #### RedisCacheService 实现 ```csharp // Cache/RedisCacheService.cs public class RedisCacheService : ICacheService { private readonly IDatabase _database; private readonly ConnectionMultiplexer _connection; public RedisCacheService(IConfiguration configuration); public Task GetAsync(string key); public Task SetAsync(string key, T value, TimeSpan? expiry = null); public Task RemoveAsync(string key); public Task ExistsAsync(string key); public Task IsConnectedAsync(); } ``` #### Autofac 模块 ```csharp // Modules/ServiceModule.cs public class ServiceModule : Module { protected override void Load(ContainerBuilder builder); } // Modules/InfrastructureModule.cs public class InfrastructureModule : Module { protected override void Load(ContainerBuilder builder); } ``` ### HoneyBox.Core 组件 #### MappingConfig ```csharp // Mappings/MappingConfig.cs public static class MappingConfig { public static void Configure(); } ``` ### HoneyBox.Api 组件 #### GlobalExceptionFilter ```csharp // Filters/GlobalExceptionFilter.cs public class GlobalExceptionFilter : IExceptionFilter { public GlobalExceptionFilter(ILogger logger); public void OnException(ExceptionContext context); } ``` #### HealthController ```csharp // Controllers/HealthController.cs [ApiController] [Route("api/[controller]")] public class HealthController : ControllerBase { public HealthController(HoneyBoxDbContext dbContext, ICacheService cacheService); [HttpGet] public Task> GetHealth(); } ``` ## Data Models ### 健康检查响应模型 ```csharp public class HealthCheckData { public string Status { get; set; } = string.Empty; public string Database { get; set; } = string.Empty; public string Redis { get; set; } = string.Empty; public DateTime Timestamp { get; set; } } ``` ### 统一响应格式 所有 API 接口返回格式: ```json { "code": 0, "msg": "success", "data": { ... } } ``` ## Correctness Properties *A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* 由于本阶段主要是基础架构搭建,大部分验收标准是结构性检查(文件是否存在、配置是否正确),属于示例测试而非属性测试。以下是可以进行属性测试的场景: ### Property 1: ApiResponse 格式一致性 *For any* API 响应,返回的 JSON 结构 SHALL 始终包含 code、msg 字段,当有数据时包含 data 字段 **Validates: Requirements 6.4** ### Property 2: 缓存读写一致性 *For any* 缓存键值对,写入后立即读取 SHALL 返回相同的值 **Validates: Requirements 3.5** ## Error Handling ### 全局异常处理策略 1. 所有未捕获异常由 GlobalExceptionFilter 统一处理 2. 异常信息记录到日志(Serilog) 3. 返回统一格式的错误响应:`{ "code": 500, "msg": "服务器内部错误" }` 4. 开发环境可返回详细错误信息,生产环境隐藏敏感信息 ### 连接失败处理 1. 数据库连接失败:健康检查返回 Database: "Disconnected" 2. Redis 连接失败:健康检查返回 Redis: "Disconnected",但不影响应用启动 ## Testing Strategy ### 验证方式 由于本阶段是基础架构搭建,主要通过以下方式验证: 1. **编译验证**:`dotnet build` 确保项目能正常编译 2. **运行验证**:启动应用,访问 Swagger 文档 3. **健康检查验证**:调用 `/api/health` 接口验证数据库和 Redis 连接 4. **日志验证**:检查控制台和日志文件输出 ### 手动测试清单 - [ ] 解决方案能正常编译 - [ ] 应用能正常启动 - [ ] Swagger 文档可访问 (http://localhost:5000/swagger) - [ ] 健康检查接口返回正确格式 - [ ] 日志输出到控制台 - [ ] 日志输出到文件 (logs/log-*.txt)