NetCoreKevin-DDD-微服务-WebApi-AI智能体、AISemanticKernel集成、MCP协议服务、SignalR、Quartz-框架详细使用教程
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,生产环境应为true
options.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 => { // 创建一个JobKey var jobKey = new JobKey("SampleJob"); // 注册Job,并指定其依赖注入的Scope q.AddJob<SampleJob>(opts => opts.WithIdentity(jobKey)); // 为Job创建一个Trigger q.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/Dockerfile
ports:
- "5000:80"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=MyDb;User=sa;Password=YourStrongPassword!;
- ConnectionStrings__Redis=redis:6379,password=YourRedisPassword
depends_on:
- sqlserver
- redis
- rabbitmq
authorizationService:
build:
context: .
dockerfile: App.AuthorizationService/Dockerfile
ports:
- "5001:80"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=AuthDb;User=sa;Password=YourStrongPassword!;
depends_on:
- sqlserver
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=YourStrongPassword!
volumes:
- sqldata:/var/opt/mssql
redis:
image: redis:alpine
command: redis-server --requirepass YourRedisPassword
volumes:
- redisdata:/data
rabbitmq:
image: rabbitmq:3-management-alpine
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
ports:
- "15672:15672" # Management UI
- "5672:5672" # AMQP
volumes:
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 框架开发顺利!