ABP vnext模块化架构的最佳实践的实现
在上一篇文章《手把手教你用Abp vnext構(gòu)建API接口服務(wù)》中,我們用ABP vnext實(shí)現(xiàn)了WebAPI接口服務(wù),但是并非ABP模塊化架構(gòu)的最佳實(shí)踐。我本身也在學(xué)習(xí)ABP,我認(rèn)為ABP新手應(yīng)該從最佳實(shí)踐開(kāi)始學(xué)習(xí),可以少走很多彎路,所以寫(xiě)了這篇最佳實(shí)踐來(lái)做個(gè)總結(jié),同時(shí)給其他朋友們提供一點(diǎn)參考。
一、什么是模塊化架構(gòu)的最佳實(shí)踐
ABP是一個(gè)包含許多nuget包的模塊化框架。它提供了一個(gè)完整的基礎(chǔ)架構(gòu)來(lái)開(kāi)發(fā)你自己的具有實(shí)體、服務(wù)、數(shù)據(jù)庫(kù)集成、API、 UI組件等等功能的應(yīng)用程序模塊。
模塊化架構(gòu)的最佳實(shí)踐就是按功能的劃分創(chuàng)建相應(yīng)的模塊實(shí)現(xiàn)的服務(wù),必要時(shí)可以把模塊發(fā)布到nuget,由其他模塊安裝組合成新的服務(wù)或單體應(yīng)用。這樣就可以復(fù)用現(xiàn)有的模塊功能,快速的交付產(chǎn)品,告別996。
二、模塊化架構(gòu)的最佳實(shí)踐說(shuō)明
這部分內(nèi)容全部來(lái)自于模塊化架構(gòu)最佳實(shí)踐 & 約定,有興趣的朋友可以去官方文檔查看。如果已經(jīng)很熟悉ABP分層了,可以直接閱讀第三部分。
1、解決方案結(jié)構(gòu):
為每個(gè)模塊創(chuàng)建一個(gè)單獨(dú)的解決方案。將解決方案命名為CompanyName.ModuleName。
一個(gè)模塊做為分層項(xiàng)目開(kāi)發(fā),因?yàn)樗袔讉€(gè)包(項(xiàng)目)是相互關(guān)聯(lián)的。每個(gè)包都有自己的模塊定義文件,并顯式聲明所依賴的包/模塊的依賴關(guān)系。
2、模塊分層和包之間的關(guān)系
下面展示了一個(gè)分層良好的模塊中的包以及它們之間的依賴關(guān)系:
領(lǐng)域?qū)?/h6>
將領(lǐng)域?qū)觿澐譃閮蓚€(gè)項(xiàng)目:
Domain.Shared 包(項(xiàng)目) 命名為CompanyName.ModuleName.Domain.Shared,包含常量,枚舉和其他類型,它不能包含實(shí)體、存儲(chǔ)庫(kù)、域服務(wù)或任何其他業(yè)務(wù)對(duì)象。可以安全地與模塊中的所有層使用。此包也可以與第三方客戶端使用。
Domain 包(項(xiàng)目) 命名為CompanyName.ModuleName.Domain,包含實(shí)體、倉(cāng)儲(chǔ)接口、領(lǐng)域服務(wù)接口及其實(shí)現(xiàn)和其他領(lǐng)域?qū)ο蟆omain 包依賴于 Domain.Shared 包。
應(yīng)用服務(wù)層
將應(yīng)用服務(wù)層劃分為兩個(gè)項(xiàng)目:
Application.Contracts 包(項(xiàng)目) 命名為CompanyName.ModuleName.Application.Contracts,包含應(yīng)用服務(wù)接口和相關(guān)的數(shù)據(jù)傳輸對(duì)象(DTO)。Application contract 包依賴于 Domain.Shared 包。
Application 包(項(xiàng)目)命名為CompanyName.ModuleName.Application,包含應(yīng)用服務(wù)實(shí)現(xiàn)。Application 包依賴于 Domain 包和 Application.Contracts 包。
基礎(chǔ)設(shè)施層
為每個(gè)orm/數(shù)據(jù)庫(kù)集成創(chuàng)建一個(gè)獨(dú)立的集成包,比如Entity Framework Core 和 MongoDB。例如,創(chuàng)建一個(gè)抽象Entity Framework Core集成的CompanyName.ModuleName.EntityFrameworkCore 包。ORM 集成包依賴于 Domain 包。不推薦依賴于orm/數(shù)據(jù)庫(kù)集成包中的其他層.
為每個(gè)主要的庫(kù)創(chuàng)建一個(gè)獨(dú)立的集成包, 在不影響其他包的情況下可以被另一個(gè)庫(kù)替換.
HTTP 層
創(chuàng)建命名為CompanyName.ModuleName.HttpApi的HTTP API包,為模塊開(kāi)發(fā)REST風(fēng)格的HTTP API。
HTTP API 包只依賴于 Application.Contracts 包。不要依賴 Application 包。
為每個(gè)應(yīng)用服務(wù)創(chuàng)建一個(gè)Controller (通常通過(guò)實(shí)現(xiàn)其接口)。這些控制器使用應(yīng)用服務(wù)接口來(lái)委托操作。它根據(jù)需要配置路由,HTTP方法和其他與Web相關(guān)的東西。
創(chuàng)建一個(gè)為HTTP API包提供客戶端服務(wù)的HTTP API Client包,它的命名為Companyname.ModuleName.HttpApi.Client。這些客戶端服務(wù)將應(yīng)用服務(wù)接口實(shí)現(xiàn)遠(yuǎn)程端點(diǎn)的客戶端。
HTTP API Client包僅依賴于 Application.Contracts包。
推薦使用ABP框架提供的動(dòng)態(tài)代理HTTP C#客戶端的功能。
Web 層
創(chuàng)建命名為CompanyName.ModuleName.Web的Web包。包含頁(yè)面、視圖、腳本、樣式、圖像和其他UI組件。Web包僅依賴于HttpApi包。
三、實(shí)現(xiàn)模塊化架構(gòu)的最佳實(shí)踐
開(kāi)發(fā)環(huán)境:Mac Visual Studio Code
SDK:dotnet core 3.1
數(shù)據(jù)庫(kù):PostgreSQL創(chuàng)建項(xiàng)目文件夾,然后進(jìn)入改文件夾的命令目錄執(zhí)行以下命令創(chuàng)建項(xiàng)目
在上一篇文章中引入的是Volo.Abp.Identity的包,現(xiàn)在改用Volo.Abp.DDD的包,更簡(jiǎn)潔。
/**創(chuàng)建解決方案**/ dotnet new sln /**創(chuàng)建模塊分層**/ 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.Commondotnet 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.PostgreSqldotnet 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.Designdotnet 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.Contractsdotnet 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.AutoMapperdotnet add src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj package Volo.Abp.AspNetCore.Mvcdotnet 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實(shí)現(xiàn)領(lǐng)域?qū)?/h6>
在Domain創(chuàng)建實(shí)體類及其約束關(guān)聯(lián),具體代碼請(qǐng)看UserData類,此處不再詳細(xì)說(shuō)明。
實(shí)現(xiàn)基礎(chǔ)設(shè)施層
在EntityFrameworkCore創(chuàng)建AccountDbContext類和LemonAccountDbContextModelCreatingExtensions類。請(qǐng)?zhí)貏e關(guān)注LemonAccountDbContextModelCreatingExtensions類,主要是用來(lái)定義實(shí)體在數(shù)據(jù)庫(kù)表中的字段屬性。
實(shí)現(xiàn)應(yīng)用服務(wù)層
實(shí)現(xiàn)httpapi
用swagger調(diào)試接口
進(jìn)入Host目錄,執(zhí)行命令
dotnet watch run
服務(wù)啟動(dòng)成功,在瀏覽器打開(kāi)鏈接http://localhost:5000/swagger/index.html,開(kāi)始調(diào)試賬號(hào)注冊(cè)和驗(yàn)證接口。結(jié)果如下:四、模塊化架構(gòu)的最佳實(shí)踐的好處
使用模塊化架構(gòu)的好處有幾點(diǎn):
可以方便的更換模塊
比如我現(xiàn)在用的數(shù)據(jù)庫(kù)是PostgreSQL,如果想要更換成MySQL,只要以EntityFrameworkCore層為基礎(chǔ),新增一個(gè)MySQL連接庫(kù),就可以在不改變業(yè)務(wù)邏輯的前提下快速的切換數(shù)據(jù)庫(kù)。 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.DbMigrationsdotnet 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.csprojdotnet add src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj package Volo.Abp.EntityFrameworkCore.MySQLdotnet add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations.csproj package Microsoft.EntityFrameworkCore.Design
單體應(yīng)用和微服務(wù)無(wú)縫切換
模塊開(kāi)發(fā)完成后,一般當(dāng)作微服務(wù)來(lái)部署;或者把模塊發(fā)布到nuget,在單體應(yīng)用的各個(gè)分層中引入模塊,多個(gè)模塊在單體應(yīng)用中的應(yīng)用就構(gòu)成了一個(gè)完整系統(tǒng)服務(wù)。模塊復(fù)用
由于模塊是發(fā)布到nuget的,所以如果有新的項(xiàng)目需要用到相同功能的,可以直接從nuget引入安裝,無(wú)需重復(fù)開(kāi)發(fā)或者復(fù)制代碼。自動(dòng)API控制器
動(dòng)態(tài) C# API 客戶端
模塊化:https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics
最佳實(shí)踐:https://docs.abp.io/zh-Hans/abp/latest/Best-Practices/Index
自動(dòng)API控制器:https://docs.abp.io/zh-Hans/abp/latest/API/Auto-API-Controllers
最后再修改ConnectionStrings default為mysql的連接,修改LemonAccountHostModule的依賴項(xiàng)LemonAccountEntityFrameworkCoreDbMigrationsModule為MySQL
GiHub地址:https://github.com/huangbenq/abp-samples
參考文檔:
總結(jié)
以上是生活随笔為你收集整理的ABP vnext模块化架构的最佳实践的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Exceptionless服务端本地化部
- 下一篇: 全球知名跨境电商,.Net软件工程师招聘