淺入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
。
下面我們來建立需要的專案結構,和了解每一個專案的作用。
ApbBase.Domain.Shared
此專案是最底層的模組,且不依賴其他模組,主要用於定義各種列舉(enums
)、全域性常量(constants
)、靜態變數(static)、啟動依賴配置(options)等。還可以在此為程式設定一個標準,限制各個層次的模組都必須符合此標準的要求。
例如 規定API 請求的一般引數,字串長度不得大於 256 個字元,我們可以這樣寫:
public static Whole
{
public const int MaxLength = 256;
}
[StringLength(maximumLength:Whole.MaxLength)]
總之,這個模組用於定義各種全域性的、共享的內容(變數、列舉等),一般不包含服務。
建立過程
在解決方案中新建 .NET Standard
專案,名稱為 ApbBase.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()]
。
ApbBase.Domain
此專案用於定義各種用於傳遞資料的類。例如資料庫實體、用於做引數傳遞的模型類等。
建立過程
我們在解決方案的src
資料夾,新增一個新的專案,名字為 AbpBase.Domain
,然後引用 ApbBase.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)
{
}
}
}
ApbBase.Domain
依賴於 ApbBase.Domain.Shared
。
ApbBase.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)
{
}
}
}
ApbBase.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)
{
}
}
}
這樣,我們的專案將可以支援三種資料庫的使用。
ApbBase.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)
{
}
}
}
ApbBase.HttpApi
此專案用於編寫 API 控制器。
建立過程
建立 一個 .NET Core 控制檯專案,名字為 ApbBase.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
和 ApbBase.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 的介紹,大家可以看文件,這裡就不搬文件的內容了。