## 整体架构图
下面是解决方案整体架构图:
![](https://img.kancloud.cn/a1/7c/a17c242d32b028e6f391f69d4e401711_580x395.png)
如图所示,有六个应用程序和一个数据库,下面提供了更多的信息:
* **身份验证服务器**:此服务用于登录、注册和管理用户帐户。它基于 ABP 的标准**Account**模块,该模块基于该`IdentityServer`库。它是**单点登录**(**SSO**) 服务,这意味着如果您登录/退出到其中一个应用程序,那么您将登录/退出到所有应用程序。那是一个ASP.NET Core Razor Pages 应用程序,它直接连接到数据库。
* **主站**:这是最终用户用来注册和创建活动的平台 ([www.openeventhub.com)](http://www.openeventhub.com/)它是一个使用**Main HTTP API**作为后端的Razor Pages应用程序。
* **管理员后台**:此应用允许管理员管理组织、事件和系统。它使用**Admin HTTP API**进行所有操作,这是一个**Blazor WebAssembly**应用。
* **主站 HTTP API**:主网使用调用的 HTTP API接口。
* **Admin HTTP API**:管理员后台调用的 HTTP API。
* **后台服务**:运行系统后台进程服务和后台作业的**控制台程序。**
* **数据库**:这是一个关系型 **PostgreSQL**数据库,用于存储系统中的所有数据。
由于是分布式系统,所以使用**Redis**作为分布式缓存服务器。
我们先从身份验证流程开始。
## 认证流程
如前所述,**Authentication Server**是一个 SSO 服务,用于对用户和客户端进行身份验证。当用户想要登录时,**主网站**和**管理员后台**使用**OpenID Connect**(**OIDC**) 协议将用户重定向到\*\*身份验证服务器。\*\*下图显示了登录过程:
![](https://img.kancloud.cn/f2/ed/f2ed851331a932337b11b995edd090bf_506x560.png)
它的逻辑顺序是这样的:
* 当用户想要访问主站时 **(1)**,主站将用户重定向到身份验证服务 **(2)**。
* 身份验证服务有一个登录页面,用户可以输入用户名和密码或注册为新用户。登录完成后,用户将重定向回主站,并返回授权码 **(3)** 和 **(4)**。
* 然后,主站使用获得的授权码向服务器执行令牌请求 **(5)**。
* 身份验证服务返回一个标识符(包含一些用户信息,例如用户名、ID、电子邮件等)和一个访问令牌 **(6)**。
* 主站将访问令牌存储在 cookie 中(管理员后台将令牌存储在浏览器的本地存储中),以便在下一个请求中获取。在接下来的请求中,它从 cookie 中获取访问令牌并将其添加到 HTTP 请求头中,同时对Main HTTP API执行 HTTP 请求 **(7)**。
* Main HTTP API 验证访问令牌 **(8)** 并授权请求。
所有这些过程都由 ABP的`Account`和`IdentityServer`模块完成。
## 探索解决方案
[EventHub.NET](http://EventHub.NET) 解决方案由多个项目组成,按应用类型分组,如下图所示:
![](https://img.kancloud.cn/0a/5f/0a5fcaea1df884c36359975db63e96ec_302x470.png)
该解决方案有两个应用层和一个领域层,以及相应的 HTTP API 和**用户界面**(**UI**) 层。两个应用层共享领域层,但它们具有不同的应用程序逻辑,因此它们是分开的。
### common 文件夹
我们先介绍`common`文件夹。该文件夹包含通用库和服务,如下所述:
* `EventHub.Domain`项目是包含实体、领域服务和其他领域对象的领域层。`EventHub.Domain.Shared`项目包含常量和一些其他类,它们是所有层和应用的共享层。
* `EventHub.EntityFrameworkCore`项目包含`DbContext`、映射、数据库迁移、存储库实现以及与 EF Core 相关的其他代码。
* `EventHub.DbMigrator`项目是一个控制台应用,用于数据库迁移并初始化数据(例如管理员用户/角色及其权限),支持开发和生产环境。
* `EventHub.BackgroundServices`项目是另一个控制台应用,用于运行后台作业。
### www 文件夹
`www`文件夹包含主站项目:
* `EventHub.Application`包括应用服务的实现,`EventHub.Application.Contracts`包括应用服务接口和DTO。
* `EventHub.HttpApi`包含 UI(Web)层使用的 API 控制器,该控制器是应用服务的简单包装器。
* `EventHub.HttpApi.Host`托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离(重用`EventHub.HttpApi`)。
* `EventHub.HttpApi.Client`一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。
* `EventHub.Web`是应用程序的 UI 层。这是一个典型的 Razor Pages 应用。它没有数据库连接,调用**Main HTTP API**进行操作。
* `EventHub.Web.Theme`自定义主题。ABP 有一个主题系统,您可以使用它来构建自己的主题并在其他应用中重用它们。`EventHub.Web`项目使用此主题。主题系统将在*第 4 部分*,*用户界面和 API 开发*中介绍。
### admin 文件夹
`admin`文件夹包含管理员后台,由维护系统的用户使用,这里有更详细的解释:
* `EventHub.Admin.Application`项目是管理员后台的应用层,包含应用服务的实现,`EventHub.Admin.Application.Contracts`包含与UI层共享的应用服务接口和DTO。
* `EventHub.Admin.HttpApi`包含 UI(Web)层使用的 API 控制器。
* `EventHub.Admin.HttpApi.Host`项目托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离。
* `EventHub.Admin.HttpApi.Client`项目是一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。
* `EventHub.Admin.Web`项目是应用程序的 UI 层。这是一个在浏览器中运行并对服务器执行 HTTP API 调用的Blazor WebAssembly应用。
### account 文件夹
`account`文件夹包含单个项目`EventHub.IdentityServer`,其他应用程序使用该项目对用户进行身份验证。
我们已经简要地介绍了解决方案中的所有项目,下面介绍项目之间的依赖关系。
## 项目依赖关系
在接下来的部分中,我将展示每个项目的依赖关系图,以便您了解代码库的组织方式。我们从基本应用程序**主站开始。**
### Main Application(主站)
请记住,**主站**是互联网**终端用户**使用应用程序:[www.openeventhub.com](http://www.openeventhub.com/)。下图显示了项目依赖关系,从应用程序的根项目`Web`开始:
![](images/screenshot_1650540632152.png)
该`Web`项目依赖于`Web.Theme`,它实现了 EventHub 的 UI 主题。`Web.Theme`是一个单独的项目,因为它同时被**Authentication Server**复用。
项目`Web`也依赖于`HttpApi`项目。我们可以在Web项目的客户端 (JavaScript) 中调用这些 API,当您通过`HttpApi.Client`调用 HTTP API 时,请求将重定向到 **Main HTTP API** (后端)。
>[success] 请注意,`HttpApi`和`HttpApi.Client` 都引用了`Application.Contacts`项目。
`HttpApi`引用`.Contracts`接口层,而`HttpApi.Client`使用 ABP 的动态 C# 代理实现了这些接口,并通过执行HTTP远程调用**Main HTTP API**。
### Main HTTP API(主站API)
**主站**使用**Main HTTP API**作为后端 API。它包含应用领域逻辑。下图显示了根项目`HttpApi.Host`及其直接或间接依赖项:
![](https://img.kancloud.cn/fe/1e/fe1eec341c709c8724137f5246f7a719_589x256.png)
* 通过引用(添加依赖)`HttpApi`项目(包括 API 控制器),客户端可以响应 HTTP API 调用;
* HTTP API 控制器使用`Application.Contracts`项目中定义的服务接口,而这些接口由`Application`项目实现,这就是为什么我们需要在`HttpApi.Host`项目中引用`Application`项目,而`Application`往下依赖的是`Domain`层,通过它来执行业务逻辑。
* `HttpApi.Host`项目还引用了该`EntityFrameworkCore`项目,因为我们在运行时需要一个数据层。该`EntityFrameworkCore`项目将实体映射到数据库中的表,并实现了`Domain`项目中定义的存储库接口。
请注意,`Application.Contracts`项目,以及`Domain.Shared`项目由客户端程序**Main Website**共享(以及`Domain.Shared`项目是间接被共享),因此它们可以依赖相同的应用程序接口进行通信。
我们现在已经了解了**主站**应用程序,下一部分介绍管理员后台:
### Admin Application(管理员站)
管理员后台站点的前端采用的是Blazor WebAssembly技术,它有一组不同的 API、UI 页面、授权规则、缓存要求等。它有不同的应用层和 HTTP API 层,共享相同的领域层,使用相同的领域逻辑和相同的数据库。
如下图所示:
![](https://img.kancloud.cn/40/f1/40f1d8087660111764283c8570e70477_404x259.png)
此图很简单。`Admin.Web`项目(即 Blazor WebAssembly )引用`Admin.HttpApi.Client`项目,因为它需要调用远程 HTTP API。而项目`Admin.HttpApi.Client`依赖于`Admin.Application.Contracts`项目(内部依赖于`Domain.Shared`项目),目的是要使用其中定义的应用服务接口。
### Admin HTTP API(管理员站 API)
管理员站点调用**Admin HTTP API**。它运行着管理员后台的应用逻辑。下图显示了根项目`Admin.HttpApi.Host`及其直接和间接依赖项:
![](https://img.kancloud.cn/21/c9/21c9ca6813e2647f3322db488a2cde0c_595x256.png)
该图与**Main HTTP API**非常相似。区别在于他们具有不同的 HTTP API 和应用层。但是使用相同的**领域**和数据库集成 (`EntityFrameworkCore`) 层。
### 认证服务器
**Authentication Server**的根项目是`IdentityServer`,依赖关系如下:
![](https://img.kancloud.cn/0b/a7/0ba779c6d95996000032b4f40a9375da_416x259.png)
`IdentityServer`项目和主站一样,也引用`Web.Theme`,它还引用了`EntityFrameworkCore`项目。通过引用`EntityFrameworkCore`项目,也间接引用了`Domain`和`Domain.Shared`项目。
### 后台服务
`BackgroundServices`项目具有下图所示的依赖项:
![](https://img.kancloud.cn/99/0a/990a77f0a8807539ea564629d240b407_389x235.png)
`BackgroundServices`项目引用`EntityFrameworkCore`,以便操作数据库,它还可以使用**领域**对象(实体、域服务)来执行后台任务。
我们已经介绍完了解决方案中的所有项目。现在,我们准备在本地开发环境中运行它们。
- 前言
- 第一部分
- 第1章 现代软件开发和 ABP 框架
- 企业级 Web 开发的挑战
- ABP框架的能力清单
- 第2章 ABP框架入门
- 安装 ABP CLI
- 创建新解决方案
- 运行解决方案
- 探索预构建模块
- 第3章 逐步开发开发ABP应用
- 创建解决方案
- 定义领域对象
- EFCore和数据库映射
- 定义应用服务
- 测试产品
- 产品列表
- 创建产品
- 编辑产品
- 删除产品
- 第4章 探索 EventHub解决方案
- 应用介绍
- 架构探索
- 方案运行
- 第二部分
- 第5章 探索ABP基础架构
- 了解模块化
- 使用依赖注入系统
- 配置应用程序
- 实现选项模式
- 日志系统
- 第6章 数据访问基础架构
- 定义实体
- 定义仓储库
- EF Core集成
- 了解 UoW
- 第7章 探索横切关注点
- 认证授权
- 用户验证
- 异常处理
- 第8章 体验 ABP 的功能和服务
- 获取当前用户
- 使用数据过滤
- 控制审计日志
- 缓存数据
- 本地化用户界面
- 第三部分
- 第9章 理解领域驱动设计
- 介绍 DDD
- 构建基于 DDD 的 解决方案
- 处理多个应用程序
- 了解执行流程
- DDD的通用原则
- 第10章 领域层 Domain
- 领域事件案例分析
- 聚合和实体的设计原则和实践
- 实现领域服务
- 落地存储库
- 构建规约(Specification)
- 领域事件
- 第11章 应用层 Application
- 落地应用服务
- 设计 DTO
- 理解各层的职责
- 第四部分
- 第12章 MVC/Razor 页面
- 主题系统
- 绑定和压缩
- 导航菜单
- Bootstrap标签助手
- 创建表单并验证
- 使用模态窗口
- 使用JS API
- 调用HTTP API
- 第13章 Blazor WebAssembly UI
- 什么是Blazor
- ABP Blazor UI
- 验证用户身份
- 理解主题系统
- 使用菜单
- 使用基本服务
- 使用UI服务
- 消费HTTP API
- 使用全局脚本和样式
- 第14章 HTTP API 和实时服务
- 构建HTTP API
- 使用HTTP API
- 使用SignalR
- 第五部分
- 第15章 落地模块化
- 理解模块化
- 构建支付模块
- 安装模块
- 第16章 实现多租户
- 理解多租户
- 多租户基础设施
- 使用功能系统
- 何时使用多租户
- 第17章 构建自动化测试
- 了解ABP测试基础设施
- 构建单元测试
- 构建集成测试