在上一篇文章《手把手教你用Abp vnext建構API接口服務》中,我們用ABP vnext實作了WebAPI接口服務,但是并非ABP子產品化架構的最佳實踐。我本身也在學習ABP,我認為ABP新手應該從最佳實踐開始學習,可以少走很多彎路,是以寫了這篇最佳實踐來做個總結,同時給其他朋友們提供一點參考。
一、什麼是子產品化架構的最佳實踐
ABP是一個包含許多nuget包的子產品化架構。它提供了一個完整的基礎架構來開發你自己的具有實體、服務、資料庫內建、API、 UI元件等等功能的應用程式子產品。
子產品化架構的最佳實踐就是按功能的劃分建立相應的子產品實作的服務,必要時可以把子產品釋出到nuget,由其他子產品安裝組合成新的服務或單體應用。這樣就可以複用現有的子產品功能,快速的傳遞産品,告别996。
二、子產品化架構的最佳實踐說明
這部分内容全部來自于子產品化架構最佳實踐 & 約定,有興趣的朋友可以去官方文檔檢視。如果已經很熟悉ABP分層了,可以直接閱讀第三部分。
1、解決方案結構:
- 為每個子產品建立一個單獨的解決方案。将解決方案命名為CompanyName.ModuleName。
- 一個子產品做為分層項目開發,因為它有幾個包(項目)是互相關聯的。每個包都有自己的子產品定義檔案,并顯式聲明所依賴的包/子產品的依賴關系。
2、子產品分層和包之間的關系
下面展示了一個分層良好的子產品中的包以及它們之間的依賴關系:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauITNxMTN5ATN3ETLzEDM3ADO0IjMzEDMxAjMwITL1cDO3QzLcBTMwIDMy8CX1cDO3QzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
領域層
将領域層劃分為兩個項目:
- Domain.Shared 包(項目) 命名為CompanyName.ModuleName.Domain.Shared,包含常量,枚舉和其他類型,它不能包含實體、存儲庫、域服務或任何其他業務對象。可以安全地與子產品中的所有層使用。此包也可以與第三方用戶端使用。
- Domain 包(項目) 命名為CompanyName.ModuleName.Domain,包含實體、倉儲接口、領域服務接口及其實作和其他領域對象。Domain 包依賴于 Domain.Shared 包。
應用服務層
将應用服務層劃分為兩個項目:
- Application.Contracts 包(項目) 命名為CompanyName.ModuleName.Application.Contracts,包含應用服務接口和相關的資料傳輸對象(DTO)。 Application contract 包依賴于 Domain.Shared 包。
- Application 包(項目)命名為CompanyName.ModuleName.Application,包含應用服務實作。Application 包依賴于 Domain 包和 Application.Contracts 包。
基礎設施層
- 為每個orm/資料庫內建建立一個獨立的內建包,比如Entity Framework Core 和 MongoDB。例如,建立一個抽象Entity Framework Core內建的CompanyName.ModuleName.EntityFrameworkCore 包。ORM 內建包依賴于 Domain 包。不推薦依賴于orm/資料庫內建包中的其他層.
- 為每個主要的庫建立一個獨立的內建包, 在不影響其他包的情況下可以被另一個庫替換.
HTTP 層
- 建立命名為CompanyName.ModuleName.HttpApi的HTTP API包,為子產品開發REST風格的HTTP API。
- HTTP API 包隻依賴于 Application.Contracts 包。不要依賴 Application 包。
- 為每個應用服務建立一個Controller (通常通過實作其接口)。這些控制器使用應用服務接口來委托操作。它根據需要配置路由,HTTP方法和其他與Web相關的東西。
- 建立一個為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,開始調試賬号注冊和驗證接口。結果如下:
四、子產品化架構的最佳實踐的好處
使用子產品化架構的好處有幾點:
-
可以友善的更換子產品
比如我現在用的資料庫是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
-
單體應用和微服務無縫切換
子產品開發完成後,一般當作微服務來部署;或者把子產品釋出到nuget,在單體應用的各個分層中引入子產品,多個子產品在單體應用中的應用就構成了一個完整系統服務。
-
子產品複用
由于子產品是釋出到nuget的,是以如果有新的項目需要用到相同功能的,可以直接從nuget引入安裝,無需重複開發或者複制代碼。
- 自動API控制器
- 動态 C# API 用戶端
GiHub位址:https://github.com/huangmingji/abp-samples
參考文檔:
- 子產品化:https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics
- 最佳實踐:https://docs.abp.io/zh-Hans/abp/latest/Best-Practices/Index
- 自動API控制器:https://docs.abp.io/zh-Hans/abp/latest/API/Auto-API-Controllers
作者:黃明基 出處:http://www.cnblogs.com/229015504/ 如果你喜歡本文章,歡迎轉載,請保留此段聲明,且在文章頁面明顯位置給出原文連接配接。 如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。歡迎大家掃描右邊二維碼關注公衆号。 |