micro_mall_api/README.md
2023-06-02 21:15:33 +08:00

10 KiB
Raw Permalink Blame History

.NET后端开发流程

基于.NET6 + vue3 前后端分离的.net快速开发框架

🍟 概述

  • 本项目适合有一定NetCorevue基础的开发人员
  • 基于**.NET6**实现的通用权限管理平台RBAC模式。整合最新技术高效快速开发前后端分离模式开箱即用。

🍀 后端技术

  • 核心框架:.Net6.0 + Web API + sqlsugar + swagger + signalR + IpRateARWmit + Quartz.net + Redis
  • 定时计划任务Quartz.Net组件支持执行程序集或者http网络请求,备份数据库
  • 安全支持:过滤器(数据权限过滤)、Sql注入、请求伪造
  • 日志管理NLog、登录日志、操作日志、定时任务日志
  • 工具类:验证码、丰富公共功能
  • 接口限流:支持接口限流,避免恶意请求导致服务层压力过大
  • 代码生成:高效率开发,代码生成器可以一键生成所有前后端代码
  • 数据字典:支持数据字典,可以方便对一些状态进行管理
  • 分库分表使用orm sqlsugar可以很轻松的实现分库分库性能优越
  • 多 租 户:支持多租户功能
  • 缓存数据内置内存缓存和Redis

🔧 配置

  1. 用 Vs 打开项目解决方案文件 ARWAdmin.sln

    下载地址:https://visualstudio.microsoft.com/zh-hans/

  2. 连接服务器数据库 navicat

  3. 修改数据库连接配置 ARW.WebApi 目录下的 appsettings.json 配置

{
  "ConnectionStrings": {
		"conn_db": "Data Source=localhost;Initial Catalog=ARWAdmin;User ID=sa;Password=ARWadmin123;Trusted_Connection=SSPI", //当前项目连接数据库,
		"conn_db_type": 1, //选择对应的数据库类型MySql = 0, SqlServer = 1。其他数据库自行添加基础数据
  }

现在尝试启动项目吧 ~

🍻项目结构

├─Infrastructure                ->[基础设施]:提供基础系统工具类。
├─ARW.WebApi               ->[webapi接口]为Vue版或其他三方系统提供接口服务。
├─ARW.Model                		->[实体层类库]:提供项目中的数据库表、数据传输对象;
├─ARW.Common              		->[常用工具]:提供项目中常用方法;
├─ARW.Repository                  ->[仓库层类库]:方便提供有执行存储过程的操作;
├─ARW.Service             		->[服务层类库]提供WebApi接口调用
├─ARW.Tasks               		->[定时任务类库]:提供项目定时任务实现功能;
├─ARW.CodeGenerator               ->[代码生成功能]:包含代码生成的模板、方法、代码生成的下载。

🔍 开发规范

开发时 不管是 哪一个层

都要 按模块 分好文件夹

都要 写好注释!!!!

/// 使用这个注释

🧬 开发流程

1


1、创建模型 (Model层)

1.1 Model (数据交互)

数据交互:与数据库打交道的类,最后接收数据返回到这个类,

然后映射到数据库 ,数据库再把结果返回 详细去了解ORM

这里我们使用的是 SqlSugar 作为 ORM

官方文档:https://www.donet5.com/Home/Doc?typeId=1182

实体常用属性

具体如何写实体类,可以参考实例实体

ARW.Model -> Models -> Business -> Student 或者 Class

  • 需要注意的是:
    • 业务表的前缀是 : tb_
    • 系统表的前缀是 : sys_
    • 记得继承 BusinessBase
    • Id 使用的是 雪花ID
    • **时间(DateTime)**的需要进行转换
    • excel导出 表头特要标记 EpplusTableColumn[ ]

1.2 Dto (数据传输)

只接收指定参数,更加清晰知道传入什么参数

// 接受的参数 是 Dto类型的
// [FromBody] 是 json请求体
public IActionResult AddStudent([FromBody] StudentDto parm)

传统Model层

Dto层更加清晰 知道传入什么值,方便前端对接~

1.3 Vo (数据展示)

展现需要的字段:

定义一个新的类,只展示我们需要的字段

使用 Select() 把实体值 赋值给 新的类就可以了。

var query = _studentRepository
                .Queryable()
                .LeftJoin<Class>((s, c) => s.ClassId == c.ClassId)
                .Where(predicate.ToExpression())
                .Select((s, c) => new StudentVo
                {
                    StudentId = s.StudentId,
                    ClassId = c.ClassId,
                    ClassName = c.ClassName,
                    StudentName = s.StudentName,
                    Sex = s.Sex,
                    Age = s.Age,
                    StudentImg = s.StudentImg,
                    StudentTag = s.StudentTag,
                    StudentService= s.StudentService.ToString(),
                    StudentDescribe = s.StudentDescribe
                });


2、创建接口和实现类 Service层

作用:

1、代码整洁

2、分层好维护

3、可以注册服务不需要实例化

2.1 创建接口

ARW.Service -> Business -> IBusinessService 中 创建接口 (interface)

注意:记得 继承 IBaseService<对应的数据实体类>

  • 命名规范:IxxxService
    • 前缀 I
    • 后缀 Service

Interface(接口)

    public interface IStudentService : IBaseService<Student>
    {
        /// <summary>
        /// 获取学生分页列表
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        PagedInfo<StudentVo> GetStudentList(StudentQueryDto parm);

    }

2.2 创建实现类

ARW.Service -> Business -> BusinessService 中 创建实现类 (Impl)

注意:记得 继承 BaseService<对应的数据实体类>,相对应的接口

添加服务到容器( 特性 ) [AppService(ServiceType = typeof( 相对应的接口 ), ServiceLifetime = LifeTime.Transient)]

[AppService(ServiceType = typeof(IStudentService), ServiceLifetime = LifeTime.Transient)]
public class StudentServiceImpl : BaseService<Student>, IStudentService

实现类要实现 接口所定义的方法

		// 写业务方法

		public PagedInfo<StudentVo> GetStudentList(StudentQueryDto parm)
            {
                //开始拼装查询条件d
                var predicate = Expressionable.Create<Student>();

                //搜索条件查询语法参考Sqlsugar
                predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.StudentName), s => s.StudentName.Contains(parm.StudentName));
                predicate = predicate.AndIF(parm.ClassId != null, s => s.ClassId == parm.ClassId);

                var query = _studentRepository
                    .Queryable()
                    .LeftJoin<Class>((s, c) => s.ClassId == c.ClassId)
                    .Where(predicate.ToExpression())
                    .Select((s, c) => new StudentVo
                    {
                        StudentId = s.StudentId,
                        ClassId = c.ClassId,
                        ClassName = c.ClassName,
                        StudentName = s.StudentName,
                        Sex = s.Sex,
                        Age = s.Age,
                        StudentImg = s.StudentImg,
                        StudentTag = s.StudentTag,
                        StudentService= s.StudentService.ToString(),
                        StudentDescribe = s.StudentDescribe
                    });


                return query.ToPage(parm);
            }

3、创建仓储层(Repository层)

ARW.Repository -> Business 中 创建仓储类 (Repository)、

作用:用于超级复杂的业务逻辑,当 接口实现类 都写的很乱时,可以使用这个层

一般走流程需要创建一个,所以参考以下模板创建:

[AppService(ServiceLifetime = LifeTime.Transient)]
public class StudentRepository : BaseRepository<Student>
{
    /*
    * 复杂的业务逻辑代码
    */
}

4、创建控制层 (Controller层)

-- 这里细节比较多,请注意看 --

控制器头部:

  [Verify] // 身份认证
  [Route("business/[controller]")] // 路由
  public class StudentController : BaseController // 继承 BaseController

依赖注入(构造函数注入)

    /// <summary>
    /// 依赖注入
    /// </summary>
    /// <param name="studentService">学生服务</param>
    /// <param name="classService">班级服务</param>
    public StudentController(IStudentService studentService, IClassService classService)
    {
        _studentService = studentService;
        _classService = classService;
    }

方法:

  • 请求参数格式:

**[FromBody]**json请求体

[FromQuery] url 获取参数

**[FromForm(Name = "xxx")] **获取From表单中的参数

  • 抛出异常:

    throw new CustomException(" ")

  • 返回结果:

SUCCESS("消息")

ToResponse(数据,"消息")

// 头部规范:
[HttpPost("addStudent")] // [请求方法("请求路由")]
[ActionPermissionFilter(Permission = "business:student:add")] // 权限标识符
[Log(Title = "学生添加", BusinessType = BusinessType.INSERT)] // 日志
public IActionResult AddStudent([FromBody] StudentDto parm)
{
    // 抛出异常
    if (parm == null)
    {
    	throw new CustomException("请求参数错误");
    }

    // 模型映射Dto层需要把接受的数据 给到 Model层才能和数据库交互
    var modal = parm.Adapt<Student>().ToCreate(HttpContext);

    var response = _studentService.Insertable(modal).ExecuteReturnSnowflakeId();
    return SUCCESS("添加成功!");
}

查询分页(联表)

查询树形

查询单条

添加

修改

删除

导入Excel

导出Excel

下载模板Excel

具体操作方法可参考:

ARW.WebApi -> Business -> StudentController(基础方法) / ProductTypeController(树形)