NetCoreKevin 框架详细使用教程
1. 框架概述
NetCoreKevin 是一个基于 .NET 8(同时支持 .NET 6)构建的,采用领域驱动设计 (DDD) 和微服务架构思想的综合性 WebApi 开发框架。它集成了大量现代应用开发所需的组件,旨在提供模块化、解耦、可扩展和高性能的企业级开发解决方案。
核心特性支持:
- ✅ DDD 分层架构
- ✅ 微服务组件(服务发现、配置中心、API网关)
- ✅ IdentityServer4 单点登录 (SSO) 与鉴权授权
- ✅ 多缓存模式 (基于
IDistributedCache
) - ✅ 分布式系统(CAP 集成事件、分布式锁)
- ✅ 一库多租户
- ✅ 多种数据库支持 (EF Core)
- ✅ 日志管理 (Log4Net)
- ✅ 实时通信 (SignalR)
- ✅ 任务调度 (Quartz)
- ✅ 文件存储(阿里云 OSS、腾讯云 COS)
- ✅ 短信服务(阿里云、腾讯云)
- ✅ AI 集成 (Semantic Kernel, MCP 协议服务)
- ✅ Docker 容器化部署
2. 环境准备与项目获取
2.1 开发环境要求
- .NET SDK: .NET 8.0 或 .NET 6.0 (根据项目要求)
- IDE: Visual Studio 2022+, VS Code, 或 Rider
- 数据库: SQL Server, MySQL 或其它 EF Core 支持的数据库
- 缓存: Redis
- 消息队列: RabbitMQ 或 Kafka (CAP 依赖)
- (可选) Docker Desktop: 用于容器化部署
2.2 获取源代码
从代码仓库克隆项目:
# 从 GitHub 克隆
git clone https://github.com/junkai-li/NetCoreKevin.git# 或从 Gitee 克隆 (国内推荐)
git clone https://gitee.com/netkevin-li/NetCoreKevin.git
3. 项目结构解析
NetCoreKevin 采用分层架构和模块化设计,核心项目如下表所示:
项目名称 | 功能描述 | 层 |
---|---|---|
App.AuthorizationService | 基于 IdentityServer4 的认证授权中心 | 认证层 |
Kevin.Domain | 领域模型、领域服务、领域事件 | 领域层 |
App.Application | 应用服务,协调领域层与外部 | 应用层 |
App.RepositorieRps | 数据库仓储实现 | 基础设施层 |
Kevin.EntityFrameworkCore | EF Core 工作单元与仓储抽象 | 基础设施层 |
App.WebApi | API 控制器,HTTP API 入口 | 表现层 |
Kevin.Common | 通用工具类、扩展方法、辅助类 | 通用 |
Share | 共享 DTOs、视图模型、枚举等 | 通用 |
Kevin.Cache | 分布式缓存抽象与实现 | 基础设施 |
Kevin.Cap | 基于 CAP 的分布式事务/事件总线 | 基础设施 |
Kevin.SignalR | SignalR 实时通信 | 基础设施 |
Kevin.FileStorage | 云文件存储服务 | 基础设施 |
Kevin.SMS | 短信服务 | 基础设施 |
Kevin.DistributedLock | 分布式锁 | 基础设施 |
App.TaskQuartz | Quartz 定时任务调度 | 后台服务 |
Kevin.AI.SemanticKernel | AI 智能体集成示例 | 应用集成 |
Kevin.AI.MCP.Server | MCP 协议服务示例 | 应用集成 |
4. 初始配置与数据库搭建
4.1 数据库初始化
- 在你的数据库服务器(如 SQL Server)中创建数据库。
- 找到项目中的
InitData
目录,执行其中的 SQL 脚本以初始化数据库结构。 - (可选) 某些模块可能需要执行 EF Core 迁移命令来生成数据库:
dotnet ef database update --project [你的项目路径,如Kevin.EntityFrameworkCore]
4.2 应用程序配置 (appsettings.json)
框架的核心配置集中在 appsettings.json
或其环境特定版本(如 appsettings.Development.json
)中。你需要根据你的环境修改以下关键连接字符串和配置项:
{"ConnectionStrings": {"DefaultConnection": "Server=你的服务器;Database=你的数据库;User Id=用户名;Password=密码;", // 数据库连接字符串"Redis": "你的Redis连接字符串:端口,password=密码", // Redis连接"RabbitMQ": "amqp://用户名:密码@主机名:端口/" // 如果使用RabbitMQ作为CAP的消息队列},"Kevin": {"SMS": { // 短信配置"AliYun": {"AccessKeyId": "你的阿里云AccessKeyId","AccessKeySecret": "你的阿里云AccessKeySecret","SignName": "你的短信签名","TemplateCode": "你的模板CODE"}//, 腾讯云配置...},"FileStorage": { // 文件存储配置"AliYunOss": {"Endpoint": "你的OSS端点","AccessKeyId": "你的AccessKeyId","AccessKeySecret": "你的AccessKeySecret","BucketName": "你的Bucket名称"}//, 腾讯云COS配置...}},// CAP 配置 (如果使用)"Cap": {"Default": {// 使用 RabbitMQ 作为消息队列"Using": [ "DotNetCore.CAP.RabbitMQ" ],"RabbitMQ": {"HostName": "localhost","UserName": "guest","Password": "guest","ExchangeName": "cap.default.exchange"}},"MongoDB": { // 或者使用MongoDB"DatabaseName": "cap","ConnectionString": "mongodb://localhost:27017"}}// 其他配置...
}
重要:切勿将包含敏感信息的 appsettings.json
文件提交到源代码版本控制系统。在生产环境中,请使用环境变量、Azure Key Vault 或其它安全密钥管理服务。
5. 核心模块使用详解
5.1 启动项配置 (Program.cs)
在 App.WebApi
或类似启动项目的 Program.cs
中,你需要注册所需的服务和中间件:
using Kevin.Cors;
using Kevin.Cache;
using Kevin.Cap;
using Kevin.SignalR;
using Kevin.SMS;
using Kevin.FileStorage;
// ... 引入其他需要的Kevin模块var builder = WebApplication.CreateBuilder(args);// 添加服务到容器中
builder.Services.AddControllers();// 1. 配置跨域 (Kevin.Cors)
builder.Services.AddKevinCors(builder.Configuration); // 通常需要在配置中定义Cors策略// 2. 配置缓存 (Kevin.Cache) - 通常依赖Redis连接字符串
builder.Services.AddKevinCache();// 3. 配置CAP分布式事件 (Kevin.Cap) - 依赖数据库连接字符串和消息队列(RabbitMQ)
builder.Services.AddKevinCap(builder.Configuration);// 4. 配置SignalR (Kevin.SignalR)
builder.Services.AddKevinSignalR();// 5. 配置短信服务 (Kevin.SMS) - 依赖配置中的Kevin:SMS节点
builder.Services.AddKevinSMS(builder.Configuration);// 6. 配置文件存储服务 (Kevin.FileStorage) - 依赖配置中的Kevin:FileStorage节点
builder.Services.AddKevinFileStorage(builder.Configuration);// 7. 配置认证授权 (通常已在AuthorizationService中处理,此处需确保API项目正确配置JWT Bearer认证)
builder.Services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>{options.Authority = "https://your-auth-service"; // 认证服务器地址options.RequireHttpsMetadata = false; // 开发环境可false,生产环境应为trueoptions.ApiName = "api1"; // API资源名});// ... 其他服务注册(如EF Core、Swagger等)var app = builder.Build();// 配置HTTP请求管道
app.UseCors("YourCorsPolicyName"); // 启用CORS
app.UseAuthentication(); // 启用认证
app.UseAuthorization(); // 启用授权// 映射SignalR Hub(如果使用)
app.MapHub<YourHub>("/yourHubPath");app.MapControllers();
app.Run();
注意:具体的扩展方法名(如 AddKevinCache()
)可能因框架版本略有不同,请以实际项目中的方法为准。
5.2 领域驱动设计 (DDD) 应用
- 定义领域实体:在
Kevin.Domain
项目中创建继承自Entity
或AggregateRoot
的类。// Kevin.Domain/Entities/Product.cs public class Product : AggregateRoot<Guid> // Guid为主键类型 {public string Name { get; private set; }public decimal Price { get; private set; }// 构造函数、领域方法、领域事件发布...private Product() {} // EF Core 可能需要无参构造函数public Product(string name, decimal price){Id = Guid.NewGuid();Name = name;Price = price;// 发布一个领域事件示例AddDomainEvent(new ProductCreatedEvent(this));} }
- 定义领域事件:在
Kevin.Domain.Events
中定义事件类。// Kevin.Domain/Events/ProductCreatedEvent.cs public class ProductCreatedEvent : DomainEvent {public Product Product { get; }public ProductCreatedEvent(Product product){Product = product;} }
- 定义领域服务:处理复杂的、不属于单个实体的领域逻辑。
- 应用层协调:在
App.Application
项目中,应用服务通过仓储接口获取聚合根,执行业务操作。// App.Application/Services/ProductAppService.cs public class ProductAppService {private readonly IRepository<Product> _productRepository;public ProductAppService(IRepository<Product> productRepository){_productRepository = productRepository;}public async Task CreateProductAsync(string name, decimal price){var product = new Product(name, price);await _productRepository.InsertAsync(product);await _productRepository.UnitOfWork.SaveChangesAsync(); // 提交更改,领域事件可能在SaveChanges前后触发} }
- 事件处理:使用
MediatR
处理领域事件(通常在Kevin.Domain.EventBus
中已集成)。// 在相应的事件处理器中 public class ProductCreatedEventHandler : INotificationHandler<ProductCreatedEvent> {private readonly ILogger<ProductCreatedEventHandler> _logger;public ProductCreatedEventHandler(ILogger<ProductCreatedEventHandler> logger){_logger = logger;}public async Task Handle(ProductCreatedEvent notification, CancellationToken cancellationToken){_logger.LogInformation($"Product created: {notification.Product.Name}");// 执行其他事件处理逻辑,如发送邮件、更新读模型等await Task.CompletedTask;} }
5.3 缓存使用 (Kevin.Cache)
在需要缓存的Service或Controller中注入 IDistributedCache
或框架封装的缓存服务:
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;public class SomeService
{private readonly IDistributedCache _cache;public SomeService(IDistributedCache cache){_cache = cache;}public async Task<SomeData> GetSomeDataAsync(string key){// 尝试从缓存获取var cachedData = await _cache.GetStringAsync(key);if (cachedData != null){return JsonSerializer.Deserialize<SomeData>(cachedData);}// 从数据库或其他来源获取数据var data = await FetchDataFromSource();// 设置缓存选项var cacheOptions = new DistributedCacheEntryOptions{AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10) // 设置绝对过期时间// SlidingExpiration = TimeSpan.FromMinutes(5) // 或设置滑动过期时间};// 将数据序列化后存入缓存await _cache.SetStringAsync(key, JsonSerializer.Serialize(data), cacheOptions);return data;}private async Task<SomeData> FetchDataFromSource(){// 实际的数据获取逻辑return await Task.FromResult(new SomeData());}
}
5.4 分布式事件 (Kevin.Cap)
发布事件:在应用服务中,使用 ICapPublisher
发布集成事件。
// 在App.Application中的某个Service
public class OrderService
{private readonly ICapPublisher _capPublisher;public OrderService(ICapPublisher capPublisher){_capPublisher = capPublisher;}public async Task PlaceOrderAsync(Order order){// 1. 业务逻辑,保存订单到数据库...// await _orderRepository.InsertAsync(order);// 2. 发布一个“订单已创建”的集成事件// CAP确保事件发布和本地数据库事务的一致性await _capPublisher.PublishAsync("Order.Created", new OrderCreatedEvent{OrderId = order.Id,Amount = order.Amount,UserId = order.UserId// ... 其他事件数据});}
}
订阅/消费事件:在其它微服务中创建消费者处理程序来响应事件。
// 在另一个微服务的项目中
public class OrderCreatedEventHandler : ICapSubscribe
{private readonly ILogger<OrderCreatedEventHandler> _logger;public OrderCreatedEventHandler(ILogger<OrderCreatedEventHandler> logger){_logger = logger;}[CapSubscribe("Order.Created")] // 订阅指定的事件名public async Task Handle(OrderCreatedEvent eventData){_logger.LogInformation($"Received order created event for order {eventData.OrderId}");// 处理事件,例如:发送邮件通知、更新积分、库存检查等// await _emailService.SendOrderConfirmationAsync(eventData.UserId, eventData.OrderId);await Task.CompletedTask;}
}
5.5 文件存储 (Kevin.FileStorage)
注入 IFileStorageService
并使用:
public class FileController : ControllerBase
{private readonly IFileStorageService _fileStorageService;public FileController(IFileStorageService fileStorageService){_fileStorageService = fileStorageService;}[HttpPost("upload")]public async Task<IActionResult> UploadFile(IFormFile file){if (file == null || file.Length == 0)return BadRequest("File is empty");using (var stream = file.OpenReadStream()){// 生成唯一文件名或使用原文件名var fileName = $"uploads/{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";// 上传文件到配置的云存储var fileUrl = await _fileStorageService.UploadFileAsync(stream, fileName);return Ok(new { Url = fileUrl });}}[HttpGet("download/{fileName}")]public async Task<IActionResult> DownloadFile(string fileName){// 获取文件流(如果服务支持)// var fileStream = await _fileStorageService.GetFileStreamAsync(fileName);// return File(fileStream, "application/octet-stream", fileName);// 或者直接返回文件的访问URL(通常是云存储的公开或私有URL)var fileUrl = await _fileStorageService.GetFileUrlAsync(fileName);return Redirect(fileUrl); // 或者返回URL让客户端自行下载}
}
5.6 任务调度 (App.TaskQuartz / Quartz)
框架集成了 Quartz,你需要定义作业 (Job) 和触发器 (Trigger)。
- 定义Job:
// 在App.TaskQuartz项目中定义Job [DisallowConcurrentExecution] // 防止并发执行 public class SampleJob : IJob {private readonly ILogger<SampleJob> _logger;public SampleJob(ILogger<SampleJob> logger){_logger = logger;}public async Task Execute(IJobExecutionContext context){_logger.LogInformation($"SampleJob is executing at {DateTime.Now:yyyy-MM-dd HH:mm:ss}");// 执行你的定时任务逻辑await Task.Delay(TimeSpan.FromSeconds(1)); // 模拟工作_logger.LogInformation($"SampleJob completed at {DateTime.Now:yyyy-MM-dd HH:mm:ss}");} }
- 配置并调度Job (通常在Startup或模块初始化中):
// 注册Job和配置调度规则 services.AddQuartz(q => {// 创建一个JobKeyvar jobKey = new JobKey("SampleJob");// 注册Job,并指定其依赖注入的Scopeq.AddJob<SampleJob>(opts => opts.WithIdentity(jobKey));// 为Job创建一个Triggerq.AddTrigger(opts => opts.ForJob(jobKey).WithIdentity("SampleJob-trigger").WithCronSchedule("0/30 * * * * ?")); // 每30秒执行一次 Cron表达式 });// 添加QuartzHostedService services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
6. API 开发与部署
6.1 WebApi 控制器
在 App.WebApi
项目中创建控制器,注入应用服务或领域服务。
[ApiController]
[Route("api/[controller]")]
[ApiVersion("1.0")] // 支持API版本控制
public class ProductsController : ControllerBase
{private readonly ProductAppService _productAppService;public ProductsController(ProductAppService productAppService){_productAppService = productAppService;}[HttpPost][Authorize] // 需要授权public async Task<IActionResult> CreateProduct([FromBody] CreateProductDto createProductDto){if (!ModelState.IsValid)return BadRequest(ModelState);await _productAppService.CreateProductAsync(createProductDto.Name, createProductDto.Price);return Ok(); // 或者返回CreatedAtAction}[HttpGet("{id}")][AllowAnonymous] // 允许匿名访问[CacheDataFilter(Duration = 60)] // 使用缓存特性,缓存60秒public async Task<IActionResult> GetProduct(Guid id){var product = await _productAppService.GetProductByIdAsync(id);if (product == null)return NotFound();return Ok(product);}
}
6.2 Docker 部署
项目支持 Docker 容器化部署。通常每个核心服务(如 App.WebApi
, App.AuthorizationService
)都有自己的 Dockerfile
。
示例 Dockerfile (适用于 .NET 8 WebApi):
# 构建阶段
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["App.WebApi/App.WebApi.csproj", "App.WebApi/"]
COPY ["../Share/Share.csproj", "../Share/"]
# ... 拷贝并恢复其他依赖项目的csproj文件
RUN dotnet restore "App.WebApi/App.WebApi.csproj"
COPY . .
WORKDIR "/src/App.WebApi"
RUN dotnet build "App.WebApi.csproj" -c Release -o /app/build# 发布阶段
FROM build AS publish
RUN dotnet publish "App.WebApi.csproj" -c Release -o /app/publish /p:UseAppHost=false# 最终运行阶段
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=publish /app/publish .
# 设置时区(如果需要)
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
ENTRYPOINT ["dotnet", "App.WebApi.dll"]
使用 docker-compose.yml 编排服务:
version: '3.8'services:webapi:build:context: .dockerfile: App.WebApi/Dockerfileports:- "5000:80"environment:- ASPNETCORE_ENVIRONMENT=Production- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=MyDb;User=sa;Password=YourStrongPassword!;- ConnectionStrings__Redis=redis:6379,password=YourRedisPassworddepends_on:- sqlserver- redis- rabbitmqauthorizationService:build:context: .dockerfile: App.AuthorizationService/Dockerfileports:- "5001:80"environment:- ASPNETCORE_ENVIRONMENT=Production- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=AuthDb;User=sa;Password=YourStrongPassword!;depends_on:- sqlserversqlserver:image: mcr.microsoft.com/mssql/server:2022-latestenvironment:- ACCEPT_EULA=Y- SA_PASSWORD=YourStrongPassword!volumes:- sqldata:/var/opt/mssqlredis:image: redis:alpinecommand: redis-server --requirepass YourRedisPasswordvolumes:- redisdata:/datarabbitmq:image: rabbitmq:3-management-alpineenvironment:- RABBITMQ_DEFAULT_USER=guest- RABBITMQ_DEFAULT_PASS=guestports:- "15672:15672" # Management UI- "5672:5672" # AMQPvolumes:sqldata:redisdata:
运行 docker-compose up -d
启动所有服务。
7. 注意事项与学习建议
- 仔细阅读项目文档和 README: NetCoreKevin 项目的 GitHub 或 Gitee 仓库通常会有更具体的说明和更新。
- 版本兼容性: 注意 .NET 版本以及各 NuGet 包版本间的兼容性问题。
- 数据库迁移: 理解并熟练使用 EF Core 的迁移命令来管理数据库结构变更。
- 配置管理: 熟练掌握
appsettings.json
分层、环境变量以及安全地管理敏感配置。 - 依赖注入: 理解 .NET Core 的 DI 容器,知道如何注册和解析服务。
- 异步编程: 广泛使用
async/await
进行异步操作以提高应用吞吐能力。 - 日志记录: 利用好集成的 Log4Net 或 Microsoft.Extensions.Logging 进行有效的日志记录,以便调试和监控。
- 微服务概念: 如果采用微服务部署,务必理解服务发现、配置中心、API 网关、分布式追踪等概念。
- 调试: 熟练使用 IDE 的调试功能,并学会在 Docker 容器中远程调试。
8. 总结
NetCoreKevin 框架提供了一个功能强大、模块化且高度可定制的起点,用于开发现代化的 .NET 应用程序,特别是基于 DDD 和微服务架构的 WebApi。通过充分利用其集成的各种组件,你可以显著提高开发效率,并构建出结构清晰、易于维护和扩展的系统。
下一步:
- 克隆项目并仔细阅读源码。
- 按照 InitData 中的脚本初始化数据库。
- 配置好
appsettings.json
中的连接字符串和其他设置。 - 从一个简单的 API 端点开始,尝试调试和理解请求的生命周期。
- 逐步探索并使用更多的高级功能,如缓存、分布式事件、文件存储等。
- 参考框架提供的示例代码和文档(如果有的话)来深入理解最佳实践。
祝你使用 NetCoreKevin 框架开发顺利!