在上一篇文章《手把手教你用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/huangbenq/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

ABP vnext模块化架构的最佳实践的实现的更多相关文章

  1. Slickflow.NET 开源工作流引擎基础介绍(六)--模块化架构设计和实践

    前言:在集成Slickflow.NET 引擎组件过程中,引擎组件需要将用户,角色等资源数据读取进来,供引擎内部调用:而企业客户都是有自己的组织架构模型,在引入模块化架构设计后,引擎组件的集成性更加友好 ...

  2. 转载:Google 官方应用架构的最佳实践指南 赞👍

    官方给的实践指南,很有实际的指导意义,  特别是对一些小公司,小团队,给了很好的参考意义. 原文地址: https://developer.android.com/topic/libraries/ar ...

  3. Android Jetpack 架构组件最佳实践之“网抑云”APP

    背景 近几年,Android 相关的新技术层出不穷.往往这个技术还没学完,下一个新技术又出来了.很多人都是一脸黑人问号? 不少开发者甚至开始哀嚎:"求求你们别再创造新技术了,我们学不动了!& ...

  4. [Abp vNext微服务实践] - 框架分析

    一.简介 abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了一番研究.我的体验是,vNext的微服务架构确实比较成熟,但是十分难以上手,对于没有微服务开发经验的.n ...

  5. 浅谈Abp vNext的模块化设计

    abp的模块化给我留下深刻的印象,模块化不是什么新概念,大家都习以为常,但是为什么要模块化,模块化的意义或者说目的是什么?也许我们思考得并不深入.难得的是abp不仅完美的阐述了模块化概念,而且把模块化 ...

  6. 基于AWS的云服务架构最佳实践

    ZZ from: http://blog.csdn.net/wireless_com/article/details/43305701 近年来,对于打造高度可扩展的应用程序,软件架构师们挖掘了若干相关 ...

  7. ABP VNext框架基础知识介绍(1)--框架基础类继承关系

    在我较早的时候,就开始研究和介绍ABP框架,ABP框架相对一些其他的框架,它整合了很多.net core的新技术和相关应用场景,虽然最早开始ABP框架是基于.net framework,后来也全部转向 ...

  8. 探索云数据库最佳实践 阿里云开发者大会数据库专场邀你一起Code up!

    盛夏.魔都.科技 三者在一起有什么惊喜? 7月24日,阿里云峰会·上海——开发者大会将在上海世博中心盛大启程,与未来世界的开发者们分享数据库.云原生.开源大数据等领域的技术干货,共同探讨前沿科技趋势, ...

  9. [Abp vNext 源码分析] - 18. 单元测试

    简介 ABP vNext 框架使用 xUnit 作为单元测试组件,官方的所有模块都编写了大量的 单元/集成测试 确保功能正常.由于 ABP vNext 模块化系统的原因,开发人员在建立单元测试项目的时 ...

随机推荐

  1. Spring整合Quartz (cronTrigger和simpleTrigger实现方法)

    Spring整合Quartz (cronTrigger和simpleTrigger实现方法) 之前有记录过一次springboot整合Quartz的文章,由于偶尔一次自己使用spring需要整合Qua ...

  2. Mybatis实例及配置(一)

    创建实体类: package com.test.mybatis.bean; public class Employee { private Integer id; private String las ...

  3. flutter vscode 安卓打包apk文件

    配置 VSCode默认是没有使用密钥签名的,往往我们在正式项目中是需要签名的.那就创建好了...所以需要自己创建并使用密钥签名 步骤一 创建密钥库 执行以下命令: keytool -genkey -v ...

  4. Kubernetes笔记(五):了解Pod(容器组)

    Kubernetes 中, 容器总是以 Pod(容器组)的方式进行调度与运行.因此对 Pod 的理解与掌握是学习 Kubernetes 的基础. 理解 Pod Pod(容器组)是 Kubernetes ...

  5. 2017年PHP程序员未来路在何方(转)

    PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些技术的推 ...

  6. element ui 分页记忆checked

    <el-table :data="tableData" border ref="multipleTableChannel" @selection-chan ...

  7. Java内部类使用场景和作用

    一.Java内部类的分类 Java内部类一般包括四种:成员内部类.局部内部类.匿名内部类和静态内部类 大多数业务需求,不使用内部类都可以解决,那为什么Java还要设计内部类呢. 二.内部类的使用场景 ...

  8. zookeeper(2) 文件系统

    这一节我们主要来看一下zookeeper文件系统的实现. 树结构 为了提高对指定节点的操作,zookeeper使用一个HashMap来存储树结构数据,key为数据路径,value为节点数据. 树节点( ...

  9. linux操作指南-01

    目录 1.1 MBR 1.2 装双系统的坑 1.3 主机硬盘的主要规划 前言:记录下最近在看的鸟哥Liunx私房菜,虽然不是第一次看了..想记录几章开发中用的比较多的部分大致是以下几个章节 第3章 主 ...

  10. SSTI服务器模板注入(以及关于渲染,solt的学习)&&[BJDCTF2020]The mystery of ip 1

    ssti服务器模板注入 ssti:利用公共 Web 框架的服务器端模板作为攻击媒介的攻击方式,该攻击利用了嵌入模板的用户输入方式的弱点.SSTI 攻击可以用来找出 Web 应用程序的内容结构. slo ...