• ABP vnext模块化架构的最佳实践的实现


    在上一篇文章《手把手教你用Abp vnext构建API接口服务》中,我们用ABP vnext实现了WebAPI接口服务,但是并非ABP模块化架构的最佳实践。我本身也在学习ABP,我认为ABP新手应该从最佳实践开始学习,可以少走很多弯路,所以写了这篇最佳实践来做个总结,同时给其他朋友们提供一点参考。

    一、什么是模块化架构的最佳实践

    ABP是一个包含许多nuget包的模块化框架。它提供了一个完整的基础架构来开发你自己的具有实体、服务、数据库集成、API、 UI组件等等功能的应用程序模块。
    模块化架构的最佳实践就是按功能的划分创建相应的模块实现的服务,必要时可以把模块发布到nuget,由其他模块安装组合成新的服务或单体应用。这样就可以复用现有的模块功能,快速的交付产品,告别996。

    二、模块化架构的最佳实践说明

    这部分内容全部来自于模块化架构最佳实践 & 约定,有兴趣的朋友可以去官方文档查看。如果已经很熟悉ABP分层了,可以直接阅读第三部分。

    1、解决方案结构:
    1. 为每个模块创建一个单独的解决方案。将解决方案命名为CompanyName.ModuleName。
    2. 一个模块做为分层项目开发,因为它有几个包(项目)是相互关联的。每个包都有自己的模块定义文件,并显式声明所依赖的包/模块的依赖关系。
    2、模块分层和包之间的关系
    下面展示了一个分层良好的模块中的包以及它们之间的依赖关系:

    领域层

    将领域层划分为两个项目:

    1. Domain.Shared 包(项目) 命名为CompanyName.ModuleName.Domain.Shared,包含常量,枚举和其他类型,它不能包含实体、存储库、域服务或任何其他业务对象。可以安全地与模块中的所有层使用。此包也可以与第三方客户端使用。
    2. Domain 包(项目) 命名为CompanyName.ModuleName.Domain,包含实体、仓储接口、领域服务接口及其实现和其他领域对象。Domain 包依赖于 Domain.Shared 包。
    应用服务层

    将应用服务层划分为两个项目:

    1. Application.Contracts 包(项目) 命名为CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO)。 Application contract 包依赖于 Domain.Shared 包。
    2. Application 包(项目)命名为CompanyName.ModuleName.Application,包含应用服务实现。Application 包依赖于 Domain 包和 Application.Contracts 包。
    基础设施层
    1. 为每个orm/数据库集成创建一个独立的集成包,比如Entity Framework Core 和 MongoDB。例如,创建一个抽象Entity Framework Core集成的CompanyName.ModuleName.EntityFrameworkCore 包。ORM 集成包依赖于 Domain 包。不推荐依赖于orm/数据库集成包中的其他层.
    2. 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
    HTTP 层
    1. 创建命名为CompanyName.ModuleName.HttpApi的HTTP API包,为模块开发REST风格的HTTP API。
      • HTTP API 包只依赖于 Application.Contracts 包。不要依赖 Application 包。
      • 为每个应用服务创建一个Controller (通常通过实现其接口)。这些控制器使用应用服务接口来委托操作。它根据需要配置路由,HTTP方法和其他与Web相关的东西。
    2. 创建一个为HTTP API包提供客户端服务的HTTP API Client包,它的命名为Companyname.ModuleName.HttpApi.Client。这些客户端服务将应用服务接口实现远程端点的客户端。
      • HTTP API Client包仅依赖于 Application.Contracts包。
      • 推荐使用ABP框架提供的动态代理HTTP C#客户端的功能。
    Web 层

    创建命名为CompanyName.ModuleName.Web的Web包。 包含页面、视图、脚本、样式、图像和其他UI组件。Web包仅依赖于HttpApi包。

    三、实现模块化架构的最佳实践

    开发环境:Mac Visual Studio Code
    SDK:dotnet core 3.1
    数据库:PostgreSQL

    创建项目文件夹,然后进入改文件夹的命令目录执行以下命令创建项目

    在上一篇文章中引入的是Volo.Abp.Identity的包,现在改用Volo.Abp.DDD的包,更简洁。

    /**创建解决方案**/
    dotnet new sln
    /**创建模块分层**/
    dotnet new classlib -o src/Lemon.Account.Domain.Shared
    dotnet new classlib -o src/Lemon.Account.Domain
    dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore
    dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.DbMigrations
    dotnet new classlib -o src/Lemon.Account.Application.Contracts
    dotnet new classlib -o src/Lemon.Account.Application
    dotnet new classlib -o src/Lemon.Account.HttpApi
    dotnet new classlib -o src/Lemon.Account.HttpApi.Client
    dotnet new web -o src/Lemon.Account.Host
    
    /**加入解决方案**/
    dotnet sln Lemon.Account.sln add src/Lemon.Account.Domain.Shared
    dotnet sln Lemon.Account.sln add src/Lemon.Account.Domain
    dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore
    dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.DbMigrations
    dotnet sln Lemon.Account.sln add src/Lemon.Account.Application.Contracts
    dotnet sln Lemon.Account.sln add src/Lemon.Account.Application
    dotnet sln Lemon.Account.sln add src/Lemon.Account.HttpApi
    dotnet sln Lemon.Account.sln add src/Lemon.Account.HttpApi.Client
    dotnet sln Lemon.Account.sln add src/Lemon.Account.Host
    
    /**分层间互相引用**/
    dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj reference src/Lemon.Account.Domain.Shared/Lemon.Account.Domain.Shared.csproj
    dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
    dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj reference src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj
    dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj reference src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj
    dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
    dotnet add src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj reference src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.Application/Lemon.Account.Application.csproj
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj
    
    /**添加nuget依赖包**/
    dotnet add src/Lemon.Account.Domain.Shared/Lemon.Account.Domain.Shared.csproj package Volo.Abp.Validation
    dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj package Volo.Abp.Ddd.Domain
    dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj package Lemon.Common
    
    dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj package Volo.Abp.EntityFrameworkCore
    dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj package Volo.Abp.EntityFrameworkCore.PostgreSql
    
    dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Volo.Abp.EntityFrameworkCore
    dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Volo.Abp.EntityFrameworkCore.PostgreSql
    dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Microsoft.EntityFrameworkCore.Design
    
    dotnet add src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj package IdentityModel
    dotnet add src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj package Volo.Abp.Ddd.Application.Contracts
    
    dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj package Volo.Abp.Ddd.Application
    dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj package Volo.Abp.AutoMapper
    
    dotnet add src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj package Volo.Abp.AspNetCore.Mvc
    
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.AspNetCore.Mvc
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Swashbuckle.AspNetCore
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Microsoft.AspNetCore.DataProtection.StackExchangeRedis
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Microsoft.Extensions.Caching.StackExchangeRedis
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.AspNetCore
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Settings.Configuration
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Sinks.Async
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Sinks.File
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.AspNetCore.Serilog
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.Autofac
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package IdentityServer4.AccessTokenValidation
    dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj
    
    
    实现领域层

    在Domain创建实体类及其约束关联,具体代码请看UserData类,此处不再详细说明。

    实现基础设施层

    在EntityFrameworkCore创建AccountDbContext类和LemonAccountDbContextModelCreatingExtensions类。请特别关注LemonAccountDbContextModelCreatingExtensions类,主要是用来定义实体在数据库表中的字段属性。

    实现应用服务层
    实现httpapi
    用swagger调试接口

    进入Host目录,执行命令

    dotnet watch run
    


    服务启动成功,在浏览器打开链接http://localhost:5000/swagger/index.html,开始调试账号注册和验证接口。结果如下:



    四、模块化架构的最佳实践的好处

    使用模块化架构的好处有几点:

    1. 可以方便的更换模块
      比如我现在用的数据库是PostgreSQL,如果想要更换成MySQL,只要以EntityFrameworkCore层为基础,新增一个MySQL连接库,就可以在不改变业务逻辑的前提下快速的切换数据库。
    dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.MySQL
    dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations
    dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.MySQL
    dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations
    
    dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
    dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations.csproj reference src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj
    
    dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj package Volo.Abp.EntityFrameworkCore.MySQL
    
    dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations.csproj package Microsoft.EntityFrameworkCore.Design
    

    最后再修改ConnectionStrings default为mysql的连接,修改LemonAccountHostModule的依赖项LemonAccountEntityFrameworkCoreDbMigrationsModule为MySQL

    1. 单体应用和微服务无缝切换
      模块开发完成后,一般当作微服务来部署;或者把模块发布到nuget,在单体应用的各个分层中引入模块,多个模块在单体应用中的应用就构成了一个完整系统服务。

    2. 模块复用
      由于模块是发布到nuget的,所以如果有新的项目需要用到相同功能的,可以直接从nuget引入安装,无需重复开发或者复制代码。

    3. 自动API控制器

    4. 动态 C# API 客户端

    GiHub地址:https://github.com/huangmingji/abp-samples

    参考文档:

    1. 模块化:https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics
    2. 最佳实践:https://docs.abp.io/zh-Hans/abp/latest/Best-Practices/Index
    3. 自动API控制器:https://docs.abp.io/zh-Hans/abp/latest/API/Auto-API-Controllers
    作者:黄明基
    出处:http://www.cnblogs.com/229015504/
    如果你喜欢本文章,欢迎转载,请保留此段声明,且在文章页面明显位置给出原文连接。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。欢迎大家扫描右边二维码关注公众号。
  • 相关阅读:
    Android的LinearLayout中orientation默认值为什么是HORIZONTAL
    Android中HttpURLConnection对象是怎么生成的
    记一个擦除硬盘数据,防止已删除文件被恢复的程序
    添加一个Android框架层的系统服务与实现服务的回调
    在 Activity 中实现 getContentView 操作
    (01)明明配置了log4j.properties为什么还是不打印日志
    (05)pom.xml文件报错web.xml is missing and <failOnMissingWebXml> is set to true
    (04)maven中的几个常用插件
    (03)开发环境eclipse、myEclipse本地tomcat调试发布maven项目遇到的糟心事
    (04)Storm与Kafka结合使用简单案例
  • 原文地址:https://www.cnblogs.com/huangmingji/p/13812191.html
Copyright © 2020-2023  润新知