用NetCore + ReactJS 实现一个前后端分离的网站 (1) 搭建后端项目框架

1. 前言

做了几年的.Net开发,技术虽然在慢慢地进步,但是对.Net的使用还停留在满足工作要求的层面上。
最开始并没有系统地学习过.Net,而是从阅读、修改前人的代码开始,遇到问题上网搜这样的模式一点点积累起来的知识。
后来者们遇到的问题,基本都能解答,但这依然是在我的舒适圈里,并没有涉及到我没接触过、或者不太熟悉的技术。
而这个过程从.NetFramework一直持续到.NetCore时期。
所以,当.NetCore的各种特性扑面而来的时候,只能就事论事地去研究,导致每样都懂一点,但不多,不成体系,心里因此也是惴惴不安,没有底气说可以熟练地使用.NetCore。
所以,特意开了博客,利用一个项目来集成尽可能多的特性,毕竟只有亲自动手去架构一个完整的项目,并且能够表述清楚,才算是掌握了这样技术。


好了,闲话少数,咱们进入正文。

2. 需求

我准备做一个合作写小说的网站,后端用.NetCore来实现API,前端用ReactJS来实现。
用户可以注册、登录、编写大纲、合作写作等等。
一来要先确定后端基础业务逻辑,二来我还没学过ReactJS(笑着哭),所以先做后端。

3. 技术方案

这里首先确定一个基本的技术方案,后期根据功能往里面添加新的模块。

序号 类型
1 开发环境 VS2022
2 .Net版本 6
3 数据库 SqlServer(开发用,生产环境可以适配其他数据库), CodeFirst
4 ORM EFCore

4. 项目框架

我们先创建一个标准的项目框架,如下图所示,有5个工程:API层、实体层、公共层、服务接口层、服务层。

image

先说下我在项目框架上的历程。

  • 一开始接触.Net项目的时候,用的都是传统的三层架构
  1. 数据层:在数据库中用存储过程实现增删改查,使用SqlHelper访问数据库,并将执行结果返回到方法中。
  2. 业务层: 将数据层中的业务组合成展示层需要的复杂逻辑。
  3. 展示层:调用业务层提供的方法实现页面交互。

实际使用中,业务层经常会被忽略掉,成为展示层和数据层之间的传声筒,因为业务逻辑都在存储过程中实现了。

  • 后来用上MVC架构的时候,也只是把controller作为展示层直接调用业务层的方法。
  • 再后来用上EFCore的时候,取消了存储过程的使用,大部分业务逻辑在代码中通过LINQ予以实现,数据库则单纯地作为一个数据存储和查询的地方。
    一开始用的还是挺舒服的,直到后来遇到并发修改数据,以及多对一数据库同步的问题(这个以后再讨论)。
  • 再后来又接触到控制反转依赖注入的概念,老实说一开始挺抗拒的,可以直接调用,为啥要写那么多的接口。
    后来嘛,真香~

接下来我们实际编写代码。

4.1. 创建实体

Novel.cs
namespace NovelTogether.Core.Model
{
    public class Novel
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string SubType { get; set; }
        public string Description { get; set; }
        public int CreatedBy { get; set; }
        public DateTime CreatedTime { get; set; }
        public int? ModifiedBy { get; set; }
        public DateTime? ModifiedTime { get; set; }
        public bool IsDeleted { get; set; }
    }
}

4.2. 创建服务接口

这里只做演示用,后面会抽到IBaseService中,然后让IXXXSerice去继承,而不用写重复的代码。

INovelService.cs
using NovelTogether.Core.Model;

namespace NovelTogether.Core.IService
{
    public interface INovelService
    {
        Task<List<Novel>> SelectAsync();
    }
}

4.3. 创建服务类

NovelService.cs
using NovelTogether.Core.IService;
using NovelTogether.Core.Model;

namespace NovelTogether.Core.Service
{
    public class NovelService: INovelService
    {
        public async Task<List<Novel>> SelectAsync()
        {
            return await Task.FromResult(
                new List<Novel>()
                {
                    new Novel(){ ID = 1, Name = "三国演义", CreatedBy = 1, CreatedTime = DateTime.Now }
                });
        }
    }
}

4.4. 创建API

这里简单地New了服务类,后面会用依赖注入来实现。

NovelController.cs
using Microsoft.AspNetCore.Mvc;
using NovelTogether.Core.IService;
using NovelTogether.Core.Model;
using NovelTogether.Core.Service;

namespace NovelTogether.Core.API.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class NovelController : Controller
    {
        [HttpGet]
        public async Task<List<Novel>> Get()
        {
            INovelService service = new NovelService();
            return await service.SelectAsync();
        }
    }
}

4.5. 测试API

按F5开始执行程序,在Swagger中执行这个方法,得到了在服务层中预设的数据。
image


到这里,一个简单的demo就做完了。目前这还不是一个完整的框架,下一期引入依赖注入来实现控制反转,避免大量的New关键字。

posted @ 2022-11-18 16:58  王一乙  阅读(830)  评论(2编辑  收藏  举报