【.NET 8 实战--孢子记账--从单体到微服务】--编写服务端框架

news2024/9/23 7:31:51

框架是一个项目所必须的,是一组预先编写的代码库和工具,提供了一个可以复用的结构,以帮助开发者快速构建应用程。即使项目目前是一个单体应用,我们还是需要先设计框架的,但是我们不可能在项目的初期就编写出一个完美的框架,因此在项目开发中我们有极大的可能对框架改动(新增一些封装、删除一些代码,修改一些代码等)。在这一节我们先简单的来设计一个小框架。

一、安装Nuget包

项目中我们需要对数据库进行操作,视图模型数据转换为数据库模型数据,以及操作Token,因此我们需要安装和它们相关的 nuget 包。

1.1 Pomelo.EntityFrameworkCore.MySql

Pomelo.EntityFrameworkCore.MySql 是一个开源的 EF Core 提供程序,通过它我们可以操作 MySQL 数据库,同时我们还需要安装 Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.ToolsPomelo.EntityFrameworkCore.MySql 依赖于 Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.Tools 是一个工具包,它包含一组命令行工具,帮助我们在 .NET 项目中使用 EF Core 进行常见任务,例如数据库迁移、模型生成和数据库更新等。
要安装它们,只需要包管理器中搜索他们的名字,选择最新版本(对应.NET 8的最新版本)安装即可,当然你也可以在程序包管理控制台中输入命令来安装它们。

Install-Package Pomelo.EntityFrameworkCore.MySql
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools
1.2 AutoMapper

AutoMapper 是一个对象与对象映射工具,用于在 .NET 应用程序中简化对象之间的数据传输,主要功能是将一个对象的属性映射到另一个对象上,我们把它用在视图模型数据转换为数据库模型数据中。在包管理器中搜索AutoMapper安装即可,也可以在程序包管理控制台中输入命令来安装。

Install-Package AutoMapper
1.3 Microsoft.AspNetCore.Authentication.JwtBearer

Microsoft.AspNetCore.Authentication.JwtBearer 是一个ASP.NET Core 中间件组件,它为 JWT 身份验证提供支持。JwtBearer 中间件允许 ASP.NET Core 应用程序验证传入的 JWT 并授权访问保护的资源。在包管理器中搜索Microsoft.AspNetCore.Authentication.JwtBearer安装即可,也可以在程序包管理控制台中输入命令来安装。

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer

二、配置Jwt

打开 appsettings.json 文件,在文件中添加如下内容:

  "JWT": {
    "ValidIssuer": "spore.miaoshu.xyz",
    "ValidAudience": "sporeapi.miaoshu.xyz",
    "IssuerSigningKey": "9$1_zC$<2b4dVS|dQ%c&bD E{Migyy3h{z#@"
  }

ValidIssuer 是在 JWT 身份验证过程中用于验证令牌来源的一项配置,它指定了期望的令牌签发者。在身份验证过程中,JWT 令牌中的 iss 声明需要匹配 ValidIssuer 的值,只有这样令牌才会被认为是有效的。ValidAudience 同样是在 JWT 身份验证过程中用于验证令牌目标的一项配置,它指定了期望的受(令牌的目标用户或服务),JWT 令牌中的 aud 声明需要匹配 ValidAudience 的值。IssuerSigningKey 是在 JWT 身份验证过程中用于验证令牌签名的密钥,用于指定用于签名 JWT 令牌的密钥,确保令牌的完整性和真实性。

appsettings.json 文件配置完后,我们在 Program.cs 文件中加入如下代码:

            ConfigurationManager configurationManager= builder.Configuration;
            // 配置 JWT 验证
            builder.Services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = configurationManager["JWT:ValidIssuer"],
                    ValidAudience = configurationManager["JWT:ValidAudience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configurationManager["JWT:IssuerSigningKey"])),
                    ClockSkew = TimeSpan.Zero 
                };
            });

在上面的代码中,有两个很关键的地方,一个是 AddAuthentication 方法,一个是 AddJwtBearer 方法。
AddAuthentication 方法用于添加和配置身份验证服务,其中 DefaultAuthenticateSchemeDefaultChallengeScheme 指定了 JWT 身份验证的默认身份验证方案为JwtBearerDefaults.AuthenticationScheme
AddJwtBearer 方法用于配置 JWT Bearer 身份验证,TokenValidationParameters 类用于设置令牌验证参数,确保令牌的有效性和安全性。在这个代码段中我们告诉 JWT Bearer 需要验证令牌的签发者(ValidateIssuer),并指定了令牌的签发者(ValidIssuer)。同时也告知 JWT Bearer 需要验证令牌的受众(ValidateAudience),以及指定了令牌的受众(ValidAudience)。通过 ValidateLifetime 设置需要验证令牌的有效期,也通过 ValidateIssuerSigningKey 设置了示需要验证令牌的签名,这时JWT 的签名将使用 IssuerSigningKey 进行验证,确保令牌没有被篡改。ClockSkew 设置为 TimeSpan.Zero,表示不允许任何时间偏移。

Tip:Jwt 在这里就不详细讲解了,需要来学习的可以关注我写的关于Jwt的文章。

三、配置AutoMapper

Program.cs 中加入代码 builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly()); 就完成了 AutoMapper 的配置。AutoMapper 会在程序启动时去扫描当前程序集中所有继承了 Profile 的类,然后加载他们。

Tip:AutoMapper 在这里就不详细讲解了,需要来学习的可以关注我写的关于AutoMapper的文章。

四、配置数据库

首先我们需要创建数据库上下文类SporeAccountingDBContext,类代码如下:

using Microsoft.EntityFrameworkCore;
using SporeAccounting.Models;

namespace SporeAccounting;

/// <summary>
/// 数据库连接上下文
/// </summary>
public class SporeAccountingDBContext : DbContext
{
    IConfiguration _dbConfig;
    public SporeAccountingDBContext(IConfiguration dbConfig)
    {
        _dbConfig = dbConfig;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var serverVersion = ServerVersion.AutoDetect(_dbConfig.GetConnectionString("MySQLConnection"));
        optionsBuilder.UseMySql(_dbConfig.GetConnectionString("MySQLConnection"), serverVersion);
        optionsBuilder.UseLoggerFactory(LoggerFactory.Create(builder =>
        {
            //控制台打印SQL语句
            builder.AddConsole();
        }));

    }
}

在上面代码中,SporeAccountingDBContext 类继承了 DbContext,并且重写了 OnConfiguring 方法,在这个方法中我们读取了 appsettings.json 文件中的数据库连接字符串,同时配置了在控制台打印 EF Core 生成的代码。
接下来,我们配置数据库连接字符串,在 ***appsettings.json *** 文件中输入如下内容:

  "ConnectionStrings": {
    "MySQLConnection": "server=47.95.36.237;port=3306;database=SporeAccounting;user=root;pwd=123asdasd;"
  }

到此,数据库的配置就完成了。

Tip:EF Core 在这里就不详细讲解了,需要来学习的可以关注我写的关于EF Core 的文章。

五、配置 Swagger

Swagger 是一个用于生成和展示 API 文档的工具,可以帮助你为 API 生成交互式文档,方便我们测试和调试。在 Program.cs 文件中输入如下内容:

builder.Services.AddSwaggerGen(s =>
{
    //添加安全定义
    s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "请输入token,格式为 Bearer XXXXX(注意中间必须有空格)",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
    //添加安全要求
    s.AddSecurityRequirement(new OpenApiSecurityRequirement {
        {
            new OpenApiSecurityScheme{
                Reference =new OpenApiReference{
                    Type = ReferenceType.SecurityScheme,
                    Id ="Bearer"
                }
            },new string[]{ }
        }
    });
});

在这段代码中,我们为 Swagger 开启了 Token 验证功能,并设置了 BearerFormat 为JWT。然后我们邮件项目属性,打开属性设置页面,找到输出选项卡,勾选生成包含API文档的文件即可。
在这里插入图片描述

六、添加通用类

最后,我们要添加四个通用类:PageRequestViewModelPageResponseViewModelBaseModelResponseData。它们的作用是:

  1. PageRequestViewModel:分页查询请求基类
using System.ComponentModel.DataAnnotations;

namespace SporeAccounting.BaseModels.ViewModel.Request;

/// <summary>
/// 分页查询请求基类
/// </summary>
public class PageRequestViewModel
{
    /// <summary>
    /// 请求的页码
    /// </summary>
    [Range(1, int.MaxValue,ErrorMessage = $"{nameof(PageNumber)}不能小于1大于2147483647")]
    [Required(ErrorMessage = $"{nameof(PageNumber)}不能为空")]
    public int PageNumber { get; set; } = 1;

    /// <summary>
    /// 每页大小
    /// </summary>
    [Range(1, 50, ErrorMessage = $"{nameof(PageSize)}不能小于1大于50")]
    [Required(ErrorMessage = $"{nameof(PageSize)}不能为空")]
    public int PageSize { get; set; } = 20;

}
  1. PageResponseViewModel:分页查询响应基类
namespace SporeAccounting.BaseModels.ViewModel.Response;

/// <summary>
/// 分页查询响应基类
/// </summary>
public class PageResponseViewModel<T>
{
    /// <summary>
    /// 总页数
    /// </summary>
    public int PageCount { get; set; } = 0;
    /// <summary>
    /// 总行数
    /// </summary>
    public int RowCount { get; set; }= 0;
    /// <summary>
    /// 返回的数据集合
    /// </summary>
    public List<T> Data { get; set; }=new List<T>();
}
  1. BaseModel:数据库映射类基类
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace SporeAccounting.BaseModels;

/// <summary>
/// 数据库映射类基类
/// </summary>
public class BaseModel
{
    /// <summary>
    /// 表数据唯一值
    /// </summary>
    [Key]
    [Column(TypeName = "nvarchar(36)")]
    [Required]
    public string Id { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    [Required]
    [Column(TypeName = "datetime")]
    public DateTime CreateDateTime { get; set; }= DateTime.Now;
    /// <summary>
    /// 创建用户
    /// </summary>
    [Required]
    [Column(TypeName = "nvarchar(36)")]
    public string CreateUserId { get; set; }
    /// <summary>
    /// 修改时间
    /// </summary>
    [Required]
    [Column(TypeName = "datetime")]
    public DateTime UpdateDateTime { get; set; } = DateTime.Now;
    /// <summary>
    /// 修改用户
    /// </summary>
    [Required]
    [Column(TypeName = "nvarchar(36)")]
    public string UpdateUserId { get; set; }
    /// <summary>
    /// 删除时间
    /// </summary>
    [Column(TypeName = "datetime")]
    public DateTime DeleteDateTime { get; set; } = DateTime.Now;
    /// <summary>
    /// 删除用户
    /// </summary>
    [Column(TypeName = "nvarchar(36)")]
    public string DeleteUserId { get; set; }
    /// <summary>
    /// 是否删除(物理删除)
    /// </summary>
    [Required]
    [Column(TypeName = "bool")]
    public bool IsDeleted { get; set; }=false;
}
  1. ResponseData:返回给客户端的响应封装
using System.Net;

namespace SporeAccounting.BaseModels;

/// <summary>
/// 返回给客户端的响应封装
/// </summary>
public class ResponseData<T>
{
    /// <summary>
    /// 返回给客户端的响应封装
    /// </summary>
    /// <param name="statusCode">http 状态码</param>
    /// <param name="errorMessage">错误信息</param>
    /// <param name="data">返回数据</param>
    public ResponseData(HttpStatusCode statusCode, string errorMessage, T data)
    {
        StatusCode = statusCode;
        ErrorMessage = errorMessage;
        Data = data;
    }

    /// <summary>
    /// 响应的Code
    /// </summary>
    public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.OK;
    /// <summary>
    /// 错误信息
    /// </summary>
    public string ErrorMessage { get; set; }
    /// <summary>
    /// 数据
    /// </summary>
    public T Data { get; set; }
}

七、封装视图模型验证信息返回值

打开 Program.cs 文件,输入如下代码:

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = actionContext =>
    {
        //获取验证失败的模型字段 
        var errors = actionContext.ModelState
            .Where(s => s.Value != null && s.Value.ValidationState == ModelValidationState.Invalid)
            .SelectMany(s => s.Value!.Errors.ToList())
            .Select(e => e.ErrorMessage)
            .ToList();

        // 统一返回格式
        var result = new ResponseData<string>(HttpStatusCode.BadRequest, string.Join("\r\n", errors.ToArray()), "");
        return new BadRequestObjectResult(result);
    };
});

在上面代码中,我们获取了验证失败的模型的字段的错误信息,并通过刚才我们定义的 ResponseData 类重新封装了一下,返回给了客户端。

七、总结

本文详细讲解了如何配置 ASP.NET Core 应用中的几个关键组件。首先,介绍了安装和配置 NuGet 包,包括数据库操作、对象映射、JWT 身份验证。接着,展示了如何在 appsettings.json 中配置 JWT 验证,并在 Program.cs 中设置相关服务。随后,讲解了如何配置 AutoMapper、数据库上下文、以及数据库连接。最后,介绍了如何配置 Swagger 生成 API 文档,并封装视图模型验证信息的返回值。通过这些配置,能帮助开发者快速构建和维护高效的应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1964390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言例题(图形打印,逆序输出,交换数组,平均值)

一.X形图形 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜线和正斜线的长度。针对每行输入&#xff0c;输出用“*”组成的X形图案。 代码展示 #include <stdio.h> int main() {int i0;int j…

鸿蒙对接极光推送时候报错1000900010,厂商token获取失败

在AppGallery Connect上配置项目的调试证书&#xff0c;然后手动导入&#xff0c;不要用IDE的自动构建证书&#xff1a; https://developer.huawei.com/consumer/cn/service/josp/agc/index.html#/

大模型简介以及该如何学习的路线

人人都看得懂的大模型简介 大模型就像一座庞大的图书馆&#xff0c;里面有非常多的书籍。但与普通图书馆不同的是&#xff0c;这座图书馆中的每本书都是关于不同事物的描述和知识。而这些书籍中的每一页都代表了这个事物的一些特征或细节。现在&#xff0c;想象一下&#xff0c…

KVM高级功能部署

kvm虚拟机迁移 静态迁移(拷贝) 关闭虚拟机 拷贝 磁盘镜像 .xml配置文件 操作方便 动态迁移 动态迁移分为基于共享存储的动态迁移和基于数据块的动态迁移 基于共享存储的动态迁移 利用共享存储,存磁盘镜像,存配置文件速度快不用关虚拟机 基于数据块…

OCCT使用指南:Foundation Classes

1、介绍 本手册解释了如何使用Open CASCADE Technology (OCCT) Foundation Classes。它提供了关于基础类的基础文档。有关基础类及其应用的高级信息&#xff0c;请参阅我们的电子学习和培训产品。 基础类提供各种通用服务&#xff0c;如自动动态内存管理&#xff08;通过句柄操…

抖店到家外卖重新布局,本地生活服务商创业机遇再现

自抖音平台去年推出团购、外卖、小时达等即时零售业务以来&#xff0c;这一举措不仅重塑了本地生活服务领域的竞争格局&#xff0c;也为众多拥有线下门店的商家开辟了全新的增长路径。众多商家敏锐捕捉到了这一市场机遇&#xff0c;纷纷入驻短视频平台&#xff0c;利用平台的强…

c基础 函数

函数 1.函数基本用法 1.1定义和三要素 函数是一个完成特定功能的代码模块&#xff0c;其程序代码独立&#xff0c;通常要求有返回值&#xff0c;也可以是空值。 三要素&#xff1a;功能 参数 返回值 参数&#xff1a;参数就是在函数声明时和函数调用时定义的变量。它用于传递…

钟氏崛起的奥秘:归隐与清议

话题的主角是钟皓&#xff0c;东汉后期人&#xff0c;颍川钟氏的第十代。他官做的不大&#xff0c;最高职务是一个小县的县长&#xff08;俸禄400石&#xff09;&#xff0c;远远没有父、祖辈高&#xff0c;父亲做到了光禄大夫、太守&#xff08;2000石&#xff09;。然而&…

【数据结构与算法】详解计数排序:小范围整数排序的最佳选择

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​ 目录 一、引言 二、计数排序的基本原理 三、实现步骤 1. 确定数据范围 2. 初始化计数数组…

JavaScript基础——JavaScript调用的三种方式

JavaScript简介 JavaScript的作用 JavaScript的使用方式 内嵌JS 引入外部js文件 编写函数 JavaScript简介 JavaScript&#xff08;简称“JS”&#xff09;是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。它是Web开发中最常用的脚本语言之一&#x…

高清无水印,录屏软件对比盘点

现在生活中不论是想要记录赛事精彩瞬间、制作教学视频&#xff0c;都可以用录屏大师这样的录屏软件来实现。今天我就介绍几款备受好评的录屏工具。 1.福昕录屏大师 链接直达&#xff1a;https://www.foxitsoftware.cn/REC/ 这个软件就是一个专业的录屏工具。它可以控制屏幕…

UltraEdit v27文本代码程序编辑器免费版下载安装教程(亲测可用)

前言 UltraEdit 是一套功能强大的文本编辑器&#xff0c;可以编辑文本、十六进制、ASCII 码&#xff0c;完全可以取代记事本&#xff08;如果电脑配置足够强大&#xff09;&#xff0c;内建英文单字检查、C 及 VB 指令突显&#xff0c;可同时编辑多个文件&#xff0c;而且即使…

OrangePi AI Pro 固件升级 —— 让主频从 1.0 GHz 到 1.6 GHz 的巨大升级

前言 OrangePi AI Pro 最近发布了Ascend310B-firmware 固件包&#xff0c;据说升级之后可以将 CPU 主频从 1.0 GHz 提升至 1.6 GHz&#xff0c;据群主大大说&#xff0c;算力也从原本的 8T 提升到了 12T&#xff0c;这波开发板的成长让我非常的 Amazing 啊&#xff01;下面就来…

【学习日记】U-Boot 环境变量与 U-Boot 命令概述

本文记录了在学习 i.MX6ULL 的 U-Boot 代码时关于环境变量和 U-Boot 命令的一些关键点。 1 环境变量的定义 在 U-Boot 中&#xff0c;使用 #define 和反斜杠 \ 来定义多行字符串。 反斜杠 \&#xff1a; 反斜杠用于指示宏定义在下一行继续。这意味着所有的行将被视为一个连续的…

mqtt协议详解(0)初步认识mqtt

文章目录 1. 介绍2. 主要特性3. 架构1. 介绍 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种构建在TCP/IP协议之上的轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境,例如IOT。 MQTT 协议于 1…

JVM:栈上的数据存储

文章目录 一、Java虚拟机中的基本数据类型 一、Java虚拟机中的基本数据类型 在Java中有8大基本数据类型&#xff1a; 这里的内存占用&#xff0c;指的是堆上或者数组中内存分配的空间大小&#xff0c;栈上的实现更加复杂。 Java中的8大数据类型在虚拟机中的实现&#xff1a;…

【error】ModuleNotFoundError: No module named ‘mmcv.cnn.weight_init‘

from&#xff1a; oduleNotFoundError: No module named ‘mmcv.cnn.weight_init‘_modulenotfounderror: no module named mmcv.cnn-CSDN博客https://blog.csdn.net/qq_36679208/article/details/107815137?spm1001.2101.3001.6650.1&utm_mediumdistribute.pc_relevant.…

java基础 之 集合与栈的使用(二)

文章目录 List 和 Set的比较Set接口对于set的无序该怎么理解&#xff1f;&#xff08;一&#xff09;实现类&#xff1a;HashSet&#xff08;二&#xff09;实现类&#xff1a;LinkedHashSet【代码部分】HashSet 和 LinkedHashSet浅谈HashSet 和 LinkedHashSet的打印结果 &…

MYSQL-初级-事务篇

目录 概述为什么有事务&#xff1f; 事务操作事务的四大特性&#xff08;AICD&#xff09;原子性&#xff08;Atomicity&#xff09;一致性&#xff08;Consistency&#xff09;隔离性&#xff08;Isolation&#xff09;持久性&#xff08;Durability&#xff09; 并发事务问题…

为虚幻引擎C++项目设置VS开发环境

为虚幻引擎C项目设置VS开发环境 虚幻引擎&#xff08;简称UE&#xff09; 能与 Visual Studio&#xff08;简称VS&#xff09; 完美结合&#xff0c;使你能够快速、简单地改写项目代码&#xff0c;并能即刻查看编译结果。设置Visual Studio以使用虚幻引擎能提高开发者对虚幻引…