淺入ABP(1):搭建基礎結構的 ABP 解決方案
版權護體©作者:痴者工良,微信公眾號轉載文章需要 《NCC開源社區》同意。
源碼地址:https://github.com/whuanle/AbpBaseStruct
本教程結果代碼位置:https://github.com/whuanle/AbpBaseStruct/tree/master/src/1/AbpBase
這里是淺入 ABP 系列的第一章,我們將學習如果搭建一個極簡的 ABP 項目結構,后面我們通過這個結構,一步步來講解、一步步開發和完善。
ABP 系列的第一篇,請各位多多支持~
搭建項目基礎結構
打開 VS 2019,創建一個解決方案,然后刪除解決方案的項目,變成空解決方案。本系列教程將使用 AbpBase 來命名解決方案和項目前綴。
在解決方案中新建一個解決方案文件夾,名字為 src,用來存放項目源碼。

我們將要創建一個類似下圖這樣的層次結構的解決方案,只是沒有 HttpApi.Client ,另外.EntityFrameCore 改成了 .Database。

下面我們來創建需要的項目結構,和了解每一個項目的作用。
AbpBase.Domain.Shared
此項目是最底層的模塊,且不依賴其他模塊,主要用於定義各種枚舉(enums)、全局常量(constants)、靜態變量(static)、啟動依賴配置(options)等。還可以在此為程序設置一個標准,限制各個層次的模塊都必須符合此標准的要求。
例如 規定API 請求的一般參數,字符串長度不得大於 256 個字符,我們可以這樣寫:
public static Whole
{
public const int MaxLength = 256;
}
[StringLength(maximumLength:Whole.MaxLength)]
總之,這個模塊用於定義各種全局的、共享的內容(變量、枚舉等),一般不包含服務。
創建過程
在解決方案中新建 .NET Standard 項目,名稱為 AbpBase.Domain.Shared,然后通過 Nuget 添加 Volo.Abp.Core 包,版本為 3.1.2。

然后新建 一個 AbpBaseDomainSharedModule.cs 文件,其內容如下:
using System;
using Volo.Abp.Modularity;
namespace AbpBase.Domain.Shared
{
[DependsOn()]
public class AbpBaseDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
在 ABP 項目中,每一個模塊(項目) 都要創建一個繼承 AbpModule 的 類,用於聲明此模塊的結構、依賴注入等。
[DependsOn] 是依賴注入標記,代表要為模塊注入什么服務,因為 .Domain.Shared 不依賴任何模塊,因此現在先留空,寫成 [DependsOn()] 。
AbpBase.Domain
此項目用於定義各種用於傳遞數據的類。例如數據庫實體、用於做參數傳遞的模型類等。
創建過程
我們在解決方案的src 文件夾,添加一個新的項目,名字為 AbpBase.Domain,然后引用 AbpBase.Domain.Shared 項目。
在項目中創建一個 AbpBaseDomainModule.cs 文件,其內容如下:
using AbpBase.Domain.Shared;
using Volo.Abp.Modularity;
namespace AbpBase.Domain
{
[DependsOn(
typeof(AbpBaseDomainSharedModule)
)]
public class AbpBaseDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
AbpBase.Domain 依賴於 AbpBase.Domain.Shared 。
AbpBase.Application.Contracts
主要用於定義接口、抽象和 DTO 對象。這個模塊用於定義各種服務,但是不提供實現。
創建過程
在解決方案的 src 文件夾,新建一個 AbpBase.Application.Contracts 項目,然后添加 AbpBase.Domain 項目引用。
在項目里新建一個 AbpBaseApplicationContractsModule 文件,其內容如下:
using AbpBase.Domain;
using Volo.Abp.Modularity;
namespace AbpBase.Application.Contracts
{
[DependsOn(
typeof(AbpBaseDomainModule)
)]
public class AbpBaseApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
AbpBase.Database
此模塊用於配置和定義 EFCore、Freesql 等 ORM,還有倉儲等,主要是處理數據庫相關的代碼。
創建過程
在解決方案 的 src 目錄新建一個 AbpBase.Database 項目,然后添加 AbpBase.Domain 項目引用。
在項目中新建一個 AbpBaseDatabaseModule 文件,其內容如下:
using AbpBase.Domain;
using Volo.Abp.Modularity;
namespace AbpBase.Database
{
[DependsOn(
typeof(AbpBaseDomainModule)
)]
public class AbpBaseDatabaseModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
ABP 里面默認集成了 EFCore ,所以我們可以直接拿來使用,這里我們先不處理數據庫相關的東西,但是先提前配好依賴注入。
在 Nuget 管理器中,添加下面四個包,版本都是 3.1.2 :
Volo.Abp.EntityFrameworkCore
Volo.Abp.EntityFrameworkCore.MySQL
Volo.Abp.EntityFrameworkCore.Sqlite
Volo.Abp.EntityFrameworkCore.SqlServer
然后將 AbpBaseDatabaseModule.cs 文件的內容修改成如下內容:
using AbpBase.Domain;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Modularity;
namespace AbpBase.Database
{
[DependsOn(
typeof(AbpBaseDomainModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqliteModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpEntityFrameworkCoreMySQLModule)
)]
public class AbpBaseDatabaseModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
這樣,我們的項目將可以支持三種數據庫的使用。
AbpBase.Application
此用於實現接口、編寫各種服務。
創建過程
在解決方案的 src 文件夾,新建一個 AbpBase.Application 項目,然后添加 AbpBase.Application.Contracts 、 AbpBase.Database 項目引用。
在項目里創建一個 AbpBaseApplicationModule.cs 文件,其文件內容如下:
using AbpBase.Application.Contracts;
using AbpBase.Database;
using AbpBase.Domain;
using Volo.Abp.Modularity;
namespace AbpBase.Application
{
[DependsOn(
typeof(AbpBaseDomainModule),
typeof(AbpBaseApplicationContractsModule),
typeof(AbpBaseDatabaseModule)
)]
public class AbpBaseApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
}
}
AbpBase.HttpApi
此項目用於編寫 API 控制器。
創建過程
創建 一個 .NET Core 控制台項目,名字為 AbpBase.HttpApi,通過 Nuget 添加 Volo.Abp.AspNetCore.Mvc 包,版本為 3.1.2。
然后添加 AbpBase.Application.Contracts 和 AbpBase.Application 兩個項目引用。
在項目里面創建一個 AbpBaseHttpApiModule.cs 文件,其內容如下:
using AbpBase.Application;
using AbpBase.Application.Contracts;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace AbpBase.HttpApi
{
[DependsOn(
typeof(AbpAspNetCoreMvcModule),
typeof(AbpBaseApplicationModule),
typeof(AbpBaseApplicationContractsModule)
)]
public class AbpBaseHttpApiModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options
.ConventionalControllers
.Create(typeof(AbpBaseHttpApiModule).Assembly, opts =>
{
opts.RootPath = "api/1.0";
});
});
}
}
}
上面,模塊的 ConfigureServices 函數里面,創建了 API 服務。
AbpBase.Web
此模塊是最上層的模塊,用於提供 UI 與用戶交互、權限控制、提供啟動配置信息、控制程序運行等。
創建過程
在解決方案的 src 文件夾,新建一個 AbpBase.Web 項目,項目為 ASP.NET Core 程序,並且創建模板為“空”。
通過 Nuget 管理器添加 Volo.Abp.Autofac,版本為 3.1.2,然后添加 AbpBase.Application 和 AbpBase.HttpApi 項目引用。
在項目里面創建 AbpBaseWebModule.cs 文件,其內容如下:
using AbpBase.Application;
using AbpBase.HttpApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace AbpBase.Web
{
[DependsOn(
typeof(AbpBaseApplicationModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpBaseHttpApiModule)
)]
public class AbpBaseWebModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
}
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseConfiguredEndpoints();
}
}
}
在 Program.cs文件中 ,加上 .UseAutofac()
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseAutofac();
將 Startup.cs 的內容 改為:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace AbpBase.Web
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AbpBaseWebModule>();
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
}
}
完成上面的步驟后,你將得到一個可以啟動的、具有基礎結構的 ABP(WEB) 應用,你可以添加一個 API 來進行測試訪問。
在 AbpBase.HttpApi 項目中,創建一個 COntrollers 目錄,再添加一個 API 控制器,其內容如下:
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
namespace AbpBase.Web.Controllers
{
[ApiController]
public class TestController : AbpController
{
[HttpGet("/T")]
public string MyWebApi()
{
return "應用啟動成功!";
}
}
}
然后啟動程序,訪問 https://localhost:5001/T,可以發現頁面顯示了字符串,則測試成功。
當然,這只是一個非常簡單的結構,我們還需要添加項目跨域、授權驗證、依賴注入、swagger 、數據庫訪問等一系列的服務,后面我們將通過從易到難、逐步求精的方法來學習 ABP 框架和架設一個完整的實踐項目!
下面介紹一下上面模塊中出現的一些代碼結構。
關於ABP和代碼解疑
完成上面的步驟后,相信你應該對 ABP 項目有了大致的認識,下面我們來介紹一下 ABP 中的一些概念以及前面出現到的一些代碼解析。
模塊
我們看一下 ABP 官網中關於 ABP 的介紹:
ABP 框架提供的設計旨在支持構建完全模塊化的應用程序和系統
前面我們建立了 7 個項目,相信大家已經體驗到了模塊化開發的過程。
ABP 模塊化,就是將每個項目作為一個模塊,然后每個模塊中需要定義一個繼承 AbpModule 的類,最終集成到上層模塊中。
[DependsOn]
一個模塊要使用另一個模塊時,通過 [DependsOn] 特性來引用需要的模塊。
配置服務和管道
繼承 AbpModule 的類型,可以使用 ConfigureServices 來配置服務,如依賴注入、數據庫配置、跨域等,OnApplicationInitialization 則用來配置中間件管道。
當然,這兩個函數都可以不寫,直接寫個空的 Module:
[DependsOn(
typeof(AbpBaseDomainSharedModule)
)]
public class AbpBaseDomainModule : AbpModule
{
}
模塊如何關聯
首先,每個模塊都需要定義一個類來繼承 AbpModule ,然后一個模塊要使用另一個模塊,則通過 [DependsOn] 來聲明引用。
在本教程的解決方案結構中, AbpBase.Web 是最上層的項目,他依賴了三個模塊:
[DependsOn(
typeof(AbpBaseApplicationModule),
typeof(AbpBaseHttpApiModule),
typeof(AbpAspNetCoreMvcModule)
)]
而 AbpBaseApplicationModule 模塊又使用了其他模塊,這就形成了一個引用鏈,讀者可以看看文章開頭的圖片。
引用鏈形成后,程序啟動時,會順着這個鏈,從最底層的模塊開始初始化。這個初始化鏈會依次調用模塊的 ConfigureServices 函數,為程序逐漸配置服務。
Domain.Shared -> Domain -> Application.Contras -> ....
你可以在每個 Module 的 ConfigureServices 函數中打印控制台信息,然后啟動程序進行測試,看看打印順序。
對於 ABP 的介紹,大家可以看文檔,這里就不搬文檔的內容了。
