项目

ABP 应用程序模块模板

本文档解释了如何基于 模块开发最佳实践与约定 创建一个可复用的 应用程序模块

请注意,本教程中创建的应用程序模块不是一个可执行的应用程序。要查看模块的实际运行,您需要将其安装到一个可执行的应用程序中。

建议查阅 模块化单体应用程序开发教程 以了解如何创建应用程序模块,将其安装到可执行的 Web 应用程序中,以及运行和测试应用程序。该教程使用的是标准模块模板,而本文档解释的是DDD模块模板。

如何开始?

您可以使用 ABP CLIABP Studio 通过此启动模板创建一个新项目。本指南将使用 ABP Studio。

首先,如果您尚未安装 ABP Studio,请先进行安装。您可以按照 安装指南 进行操作。

创建新的空解决方案

打开 ABP Studio,在欢迎页面点击 New solution 按钮,或点击顶部菜单项 文件 > 新建解决方案。点击 empty solution 链接以选择空解决方案模板。

新建解决方案

输入解决方案名称,选择解决方案文件夹,然后点击 Create 按钮。

解决方案属性

  • Acme.IssueManagement 是解决方案名称,格式如 您的公司.您的产品。您可以使用一级、两级或三级命名。

要理解解决方案、模块和包这些术语,请参阅 ABP Studio 概念 文档。

创建新的 DDD 模块

创建新解决方案后,屏幕左侧的解决方案资源管理器将显示为空。右键单击解决方案的根节点,并从上下文菜单中选择 添加 > 新建模块 > DDD 模块

新建模块

创建新模块 对话框将会打开。输入模块名称,然后点击 Next 按钮。

创建新模块

现在,您可以选择用户界面选项,或者留空以创建没有用户界面的模块。一个模块可以支持多种用户界面,例如 MVC、Blazor、Angular 等,或者完全不支持。点击 Next 按钮以指定数据库提供程序。

选择用户界面

选择您想在模块中使用的数据库提供程序。您可以选择 EntityFrameworkCoreMongoDB,或两者都选。与用户界面选项不同,您必须至少选择一个数据库提供程序。点击 Next 按钮查看附加选项。

选择数据库提供程序

您可以通过取消勾选 Include Tests 选项来排除模块中的测试项目。点击 Create 按钮创建模块。

附加选项

解决方案结构

根据您指定的选项,您将获得略有不同的解决方案结构。如果您未指定任何选项,您将获得如下所示的解决方案:

issuemanagement-module-solution

项目按 srctest 文件夹组织:

  • src 文件夹包含实际的模块,该模块基于 DDD 原则分层。
  • test 文件夹包含单元测试和集成测试。

下图展示了模块的层次结构和项目依赖关系:

layered-project-dependencies-module

以下各部分将解释相关的项目及其依赖关系。

.Domain.Shared 项目

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

IssueType 枚举和一个 IssueConsts 类(可能包含 Issue 实体的一些常量字段,如 MaxTitleLength)就是此项目的理想候选。

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

.Domain 项目

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

Issue 实体、IssueManager 领域服务和 IIssueRepository 接口是此项目的理想候选。

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

.Application.Contracts 项目

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

IIssueAppService 接口和 IssueCreationDto 类是此项目的理想候选。

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

.Application 项目

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

IssueAppService 类是此项目的理想候选。

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

.EntityFrameworkCore 项目

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

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

如果您的模块不希望支持 EF Core,可以删除此项目。

.MongoDB 项目

这是 MongoDB 的集成项目。

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

如果您的模块不希望支持 MongoDB,可以删除此项目。

测试项目

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

  • .Domain.Tests 用于测试领域层。
  • .Application.Tests 用于测试应用层。
  • .EntityFrameworkCore.Tests 用于测试 EF Core 配置和自定义仓储。
  • .MongoDB.Tests 用于测试 MongoDB 配置和自定义仓储。
  • .TestBase 是所有测试的基(共享)项目。

测试项目是为集成测试准备的;

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

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

领域层和应用层测试使用的是 EF Core。如果您移除了 EF Core 集成,或者希望使用 MongoDB 测试这些层,您需要手动更改项目引用和模块依赖关系。

宿主应用程序

解决方案没有用于运行模块的宿主应用程序。但是,您可以创建一个 单层分层 的应用程序,并将创建的模块 导入 到宿主应用程序中。

您也可以查阅 模块化单体应用程序开发教程 以学习如何创建应用程序模块,将其安装到可执行的 Web 应用程序中,以及运行和测试应用程序。

Angular UI

如果您选择了 Angular UI,解决方案内部将有一个名为 angular 的文件夹。这是 Angular 客户端代码所在的位置。当您在 IDE 中打开该文件夹时,文件夹结构如下所示:

ABP Angular 模块项目的文件夹结构

  • angular/projects/issue-management 文件夹包含 Angular 模块项目。
  • angular/projects/dev-app 文件夹包含一个运行您模块的开发应用程序。

服务器端结构与上述解决方案描述类似。在您创建 宿主 应用程序后,API 和 Angular 演示应用程序将使用它。

如何运行 Angular 开发应用

对于模块开发,您需要启动并运行 dev-app 项目。以下是我们如何启动开发服务器的方法。

首先,我们需要安装依赖项:

  1. 在根文件夹(即 angular)中打开您的终端。
  2. 运行 yarnnpm install

依赖项将被安装,其中一些是作为 NPM 包发布的 ABP 模块。要查看所有 ABP 包,您可以在 angular 文件夹中运行以下命令:

yarn list --pattern abp

npm 中没有等效的命令。

您将开发的模块依赖于这些 ABP 包中的两个:@abp/ng.core@abp/ng.theme.shared。其余的 ABP 模块包含在 package.json 中是因为 dev-app 项目。

一旦所有依赖项安装完毕,按照以下步骤启动您的开发应用:

  1. 确保 宿主 应用程序项目已启动并运行。
  2. 更改 angular/projects/dev-app/src/environments 文件夹中的 environment.ts 文件,以匹配您的 宿主 应用程序 URL。
  3. 在根文件夹(即 angular)中打开您的终端。
  4. 运行 yarn startnpm start

ABP Angular 模块 dev-app 项目

问题管理页面初始为空。您可以在 angular/projects/issue-management/src/lib/issue-management.component.ts 路径下的 IssueManagementComponent 中更改内容,并观察视图的相应变化。

现在,让我们仔细看看您项目中的一些关键元素。

主组件

位于 angular/projects/issue-management/src/lib/issue-management.routes.ts 路径下的 IssueManagementComponent 是您模块项目的主组件。其中有几点值得注意:

  • IssueManagementComponent 在最新迁移中被声明为独立组件。
  • ISSUE_MANAGEMENT_ROUTES 被配置为惰性加载。

配置模块

angular/projects/issue-management/config/src/providers/route.provider.ts 路径下有一个配置模块。此模块的静态 provideIssueManagement 方法应该在路由级别被调用。因此,您可以假设会发生以下情况:

export const appConfig: ApplicationConfig = {
  providers: [
    // ...
    provideIssueManagement(),
    // ...
  ],
};

您可以使用此静态方法来配置使用您模块项目的应用程序。此类配置的示例已经实现,并且 ISSUE_MANAGEMENT_ROUTE_PROVIDERS 令牌在此处提供。该方法可以接受选项,从而实现进一步配置的可能性。

测试 Angular UI

请参阅 测试文档

在本文档中