项目

分层解决方案:结构详解

本文档中提到的一些功能可能在免费版本中不可用。我们使用 * 符号表示该功能在 团队版更高版本 许可证中可用。

本文档解释了 ABP Studio 中分层解决方案模板的解决方案和文件夹结构。

本文档假设您已按照 快速入门:使用 ABP Studio 创建分层 Web 应用程序 指南创建了一个新的分层解决方案。(选择 Entity Framework Core 作为数据库提供程序。)

理解 ABP 解决方案结构

当您创建一个新的分层解决方案时,您将在 解决方案资源管理器 面板中看到类似于下面的树状结构:

分层解决方案在资源管理器中

Acme.Bookstore 是解决方案的主要 ABP Studio 模块。它包含两个文件夹:如上图所示的 srctestsrc 文件夹包含解决方案的源代码,根据 DDD 原则进行结构化,而 test 文件夹则包含单元测试和集成测试。

有关 ABP Studio 解决方案、模块和包术语的全面定义,请参阅 概念 文档。

探索文件夹结构

您可以在解决方案资源管理器中右键单击根项目(本例中为 Acme.Bookstore),然后选择 打开方式 -> 资源管理器 命令,以在文件系统中打开包含解决方案的文件夹:

在资源管理器中打开解决方案

解决方案的根文件夹将类似于以下结构:

解决方案文件夹

  • .abpstudio 文件夹存储您对此解决方案的个人偏好,并从源代码控制(Git 忽略)中排除。它由 ABP Studio 创建和使用。
  • etc 文件夹包含解决方案的附加文件,组织到以下子文件夹中:
    • abp-studio 文件夹保存由 ABP Studio 管理的设置。此文件夹包含在源代码控制中,并在开发人员之间共享。
    • docker 文件夹提供 docker-compose 配置,以便在本地机器上轻松运行解决方案的基础设施依赖项(例如 RabbitMQ、Redis)。
    • helm 文件夹包含用于将解决方案部署到 Kubernetes 的 Helm 图表和相关脚本。*
  • src 文件夹包含解决方案的源代码,根据 DDD 原则进行结构化。它还包含数据库迁移,并且根据您的项目创建选项,可能包含移动和 Web 应用程序项目。
  • test 文件夹包含解决方案的单元测试和集成测试。

理解分层解决方案结构

下图说明了应用程序的层次和项目依赖关系:

分层解决方案层次

.Domain.Shared 项目

此项目包含常量、枚举和其他对象,这些对象实际上是领域层的一部分,但需要被解决方案中的所有层/项目使用。

BookType 枚举和 BookConsts 类(可能包含 Book 实体的一些常量字段,如 MaxNameLength)是此项目的良好候选对象。

  • 此项目不依赖于解决方案中的其他项目。所有其他项目直接或间接依赖于该项目。

.Domain 项目

这是解决方案的领域层。它主要包含实体、聚合根领域服务值对象仓储接口和其他领域对象。

Book 实体、BookManager 领域服务和 IBookRepository 接口是此项目的良好候选对象。

  • 依赖于 .Domain.Shared,因为它使用在该项目中定义的常量、枚举和其他对象。

.Application.Contracts 项目

此项目主要包含应用层的应用服务 接口数据传输对象 (DTO)。它的存在是为了分离应用层的接口和实现。这样,接口项目可以作为合同包共享给客户端。

IBookAppService 接口和 BookCreationDto 类是此项目的良好候选对象。

  • 依赖于 .Domain.Shared,因为它可能在应用服务接口和 DTO 中使用此项目的常量、枚举和其他共享对象。

.Application 项目

此项目包含在 .Application.Contracts 项目中定义的应用服务接口的 实现

BookAppService 类是此项目的良好候选对象。

  • 依赖于 .Application.Contracts 项目,以便能够实现接口并使用 DTO。
  • 依赖于 .Domain 项目,以便能够使用领域对象(实体、仓储接口等)来执行业务逻辑。

.EntityFrameworkCore 项目

这是 EF Core 的集成项目。它定义了 DbContext 并实现在 .Domain 项目中定义的仓储接口。

  • 依赖于 .Domain 项目,以便能够引用实体和仓储接口。

仅当您使用 EF Core 作为数据库提供程序时,此项目才可用。如果您选择其他数据库提供程序,其名称将不同。

.DbMigrator 项目

这是一个控制台应用程序,简化了在开发和生产环境中执行数据库迁移的过程。当您运行此应用程序时,它会:

  • 如有必要,创建数据库。
  • 应用挂起的数据库迁移。
  • 如果需要,种子初始数据。

此项目有自己的 appsettings.json 文件。因此,如果您想更改数据库连接字符串,请记住也要更改此文件。

尤其是种子初始数据在这一点上很重要。ABP 有一个模块化的数据种子基础设施。有关数据种子的更多信息,请参阅其文档

虽然创建数据库和应用迁移似乎只对关系数据库是必要的,但即使您选择了 NoSQL 数据库提供程序(如 MongoDB),此项目也会出现。在这种情况下,它仍然会种子化应用程序所需的初始数据。

  • 依赖于 .EntityFrameworkCore 项目(对于 EF Core),因为它需要访问迁移。
  • 依赖于 .Application.Contracts 项目,以便能够访问权限定义,因为初始数据种子器默认授予管理员角色所有权限。

.HttpApi 项目

此项目用于定义您的 API 控制器。

大多数情况下,您不需要手动定义 API 控制器,因为 ABP 的自动 API 控制器功能会根据您的应用层自动创建它们。但是,如果您需要编写 API 控制器,这是最佳位置。

  • 依赖于 .Application.Contracts 项目,以便能够注入应用服务接口。

.HttpApi.Client 项目

这是一个定义 C# 客户端代理以使用解决方案的 HTTP API 的项目。您可以将此库共享给第三方客户端,以便他们可以轻松地在其 Dotnet 应用程序中使用您的 HTTP API(对于其他类型的应用程序,他们仍然可以手动使用您的 API,或在自己的平台上使用工具)

大多数情况下,您不需要手动创建 C# 客户端代理,这要归功于 ABP 的动态 C# API 客户端功能。

.HttpApi.Client.ConsoleTestApp 项目是一个控制台应用程序,用于演示客户端代理的使用。

  • 依赖于 .Application.Contracts 项目,以便能够与远程服务共享相同的应用服务接口和 DTO。

如果您不需要为您的 API 创建 C# 客户端代理,可以删除此项目及其依赖项。

.Web 项目

如果您使用 ASP.NET Core MVC UI,此项目包含应用程序的用户界面 (UI)。它包含 Razor 页面、JavaScript 文件、CSS 文件、图像等...

此项目包含主要的 appsettings.json 文件,其中包含应用程序的连接字符串和其他配置。

  • 依赖于 .HttpApi 项目,因为 UI 层需要使用解决方案的 API 和应用服务接口。

如果您检查 .Web.csproj 文件的源代码,您将看到对 .Application.EntityFrameworkCore 项目的引用。

实际上,在编写 UI 层代码时并不需要这些引用,因为 UI 层通常不依赖于 EF Core 或应用层的实现。这些启动模板已为分层部署做好准备,其中 API 层托管在与 UI 层不同的服务器上。

但是,如果您没有选择 --tiered 选项,这些引用将保留在 .Web 项目中,以便能够在单个应用程序端点上托管 Web、API 和应用层。

这使您能够在表示层中使用领域实体和仓储。然而,根据 DDD,这被认为是一种不良实践。

测试项目

解决方案有多个测试项目,每一层对应一个:

  • .Domain.Tests 用于测试领域层。
  • .Application.Tests 用于测试应用层。
  • .EntityFrameworkCore.Tests 用于测试 EF Core 配置和自定义仓储。
  • .Web.Tests 用于测试 UI(如果您使用 ASP.NET Core MVC UI)。
  • .TestBase 是所有测试的基(共享)项目。

此外,.HttpApi.Client.ConsoleTestApp 是一个控制台应用程序(不是自动化测试项目),用于演示从 .NET 应用程序使用 HTTP API。

测试项目已为集成测试做好准备:

  • 它与 ABP 和您的应用程序中的所有服务完全集成。
  • 对于 EF Core,它使用 SQLite 内存数据库。对于 MongoDB,它使用 EphemeralMongo 库。
  • 授权被禁用,因此任何应用服务都可以在测试中轻松使用。

您仍然可以为您的类创建单元测试,这将更难编写(因为您需要准备模拟/伪对象),但运行速度更快(因为它只测试单个类并跳过所有初始化过程)。

如何运行?

您可以打开解决方案运行器面板并启动所有应用程序。默认用户名为 admin,密码为 1q2w3E*

运行解决方案

更多信息,请参阅使用 ASP.NET Core MVC 模板入门

分层结构 *

如果您选择了 ASP.NET Core UI 并指定了 --tiered 选项,创建的解决方案将是一个分层解决方案。分层结构的目的是能够 将 Web 应用程序和 HTTP API 部署到不同的服务器

分层解决方案

  • 浏览器通过执行 HTML、CSS 和 JavaScript 来运行您的 UI。
  • Web 服务器托管静态 UI 文件(CSS、JavaScript、图像等)和动态组件(例如 Razor 页面)。它向 API 服务器执行 HTTP 请求以执行应用程序的业务逻辑。
  • API 服务器托管 HTTP API,然后使用应用程序的应用层和领域层来执行业务逻辑。
  • 最后,数据库服务器托管您的数据库。

除非您确实需要这种四层部署,否则建议采用默认结构,这种结构在开发、部署和维护方面更简单。

解决方案结构如下所示:

分层书店解决方案

与默认结构不同,有两个新项目出现:.AuthServer.HttpApi.Host

.AuthServer 项目

此项目用作其他项目的身份验证服务器。.Web 项目使用 OpenId Connect 身份验证从 AuthServer 获取当前用户的身份和访问令牌。然后使用访问令牌调用 HTTP API 服务器。HTTP API 服务器使用承载令牌身份验证从访问令牌获取声明以授权当前用户。

分层解决方案应用程序

ABP 使用 OpenIddict 模块,该模块使用开源的 OpenIddict-core 库进行应用程序之间的身份验证。有关 OpenIddict 和 OpenID Connect 协议的详细信息,请参阅 OpenIddict 文档

它有自己的 appsettings.json,其中包含数据库连接和其他配置。

.HttpApi.Host 项目

此项目是一个托管解决方案 API 的应用程序。它有自己的 appsettings.json,其中包含数据库连接和其他配置。

.Web 项目

与默认结构一样,此项目包含应用程序的用户界面 (UI)。它包含 Razor 页面、JavaScript 文件、样式文件、图像等...

此项目包含一个 appsettings.json 文件,但这次它没有连接字符串,因为它从不连接到数据库。相反,它主要包含远程 API 服务器和身份验证服务器的端点。

Docker Compose

etc/docker-compose 文件夹中的 docker-compose 配置文件已配置为使用 Docker 运行解决方案。更多信息,请参阅使用 Docker Compose 进行 Docker 部署


在本文档中