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 数据库初始化

  1. 在你的数据库服务器(如 SQL Server)中创建数据库。
  2. 找到项目中的 InitData 目录,执行其中的 SQL 脚本以初始化数据库结构。
  3. (可选) 某些模块可能需要执行 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) 应用

  1. 定义领域实体:在 Kevin.Domain 项目中创建继承自 EntityAggregateRoot 的类。
    // 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));
        }
    }
    
  2. 定义领域事件:在 Kevin.Domain.Events 中定义事件类。
    // Kevin.Domain/Events/ProductCreatedEvent.cs
    public class ProductCreatedEvent : DomainEvent
    {
        public Product Product { get; }
        public ProductCreatedEvent(Product product)
        {
            Product = product;
        }
    }
    
  3. 定义领域服务:处理复杂的、不属于单个实体的领域逻辑。
  4. 应用层协调:在 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前后触发
        }
    }
    
  5. 事件处理:使用 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)。

  1. 定义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}");
        }
    }
    
  2. 配置并调度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。通过充分利用其集成的各种组件,你可以显著提高开发效率,并构建出结构清晰、易于维护和扩展的系统。

下一步

  1. 克隆项目并仔细阅读源码。
  2. 按照 InitData 中的脚本初始化数据库
  3. 配置好 appsettings.json 中的连接字符串和其他设置。
  4. 从一个简单的 API 端点开始,尝试调试和理解请求的生命周期。
  5. 逐步探索并使用更多的高级功能,如缓存、分布式事件、文件存储等。
  6. 参考框架提供的示例代码和文档(如果有的话)来深入理解最佳实践。

祝你使用 NetCoreKevin 框架开发顺利!

posted @ 2025-09-03 14:14  .BOM  阅读(2)  评论(0)    收藏  举报