ABP 适用性改造 - 精简 ABP CLI 生成的项目结构

时间:2021-03-18 09:02:00 来源:互联网 作者: 神秘的大神 字体:

Overview

不管是公司或者个人都会有不同的开发习惯,通过建立项目模板,既可以使开发人员聚焦于业务功能的开发,也可以在一定程度上统一不同开发人员之间的开发风格。在使用 ABP 框架的过程中,对于 ABP 生成的默认项目模板,类库多,附加功能多,是目前在部门内部推行 ABP 过程中遇到的问题。因此,本篇文章将针对 ABP 默认生成的模板项目进行精简,构建出一个简化版的 ABP 项目模板

模板源码地址:https://github.com/danvic712/ingos-abp-api-template

Step by Step

在精简项目结构之前肯定需要一个由 ABP CLI 生成的默认项目模板供我们进行参考,创建 ABP 项目主要有如下的两种方式进行

第一种,通过使用 ABP CLI 这么一个 dotnet tool 来创建一个基础项目,只需要将 ABP CLI 全局安装到电脑上,就可以通过脚手架来生成所需项目

-- 全局安装 ABP CLI
dotnet tool install -g Volo.Abp.Cli

-- 全局更新 ABP CLI
dotnet tool update -g Volo.Abp.Cli

当安装完成之后,输入 abp help 就可以查看该脚手架提供的功能,例如这里我们需要通过 abp new 命令来创建项目,同时基于不同的需求,在创建项目时附加不同的参数即可

ABP CLI

第二种,则是直接通过官网(https://abp.io/get-started)进行下载,本篇文章中所使用到的项目模板就是使用该方法,直接在官网上下载的模板基础上进行调整的

创建项目

在官网创建项目时需要输入项目的相关信息,因为这里需要改造的是 Web API 项目,所以 UI 框架选择了 Angular,同时,因为默认的 ABP 模板会把 IdentityServer 和 API 项目混在一起,所以这里我会把这两块的功能进行拆分,确定项目类型无误之后,点击现在创建按钮,等待浏览器提示有文件需要下载即可

2.1、运行模板项目

解压下载完成的安装包,如果你和我创建的项目选项相同的话,这里会包含两个文件夹,因为仅针对后端项目进行调整,这里只关注 aspnet-core 文件夹中的内容即可。在改造之前,我们先依据官方文档中的使用说明来进行操作,确保模板是可以正常运行起来之后再进行后续的调整。

模板文件夹结构

2.1.1、调整数据库连接字符串

在 ABP 生成的模板项目中,整个项目的配置文件 appsettings.json 文件存在于三个地方,.DbMigrator.HttpApi.Host.IdentityServer,先不去关注这三个项目的具体作用,首先将这三处配置文件中的数据库连接字符串修改为实际使用的配置信息

"ConnectionStrings": {
    "Default": "Server=localhost;Port=3306;Database=IngosAbpTemplate;Uid=root;Pwd=myPassword;"
},

2.1.2、执行数据库迁移

在调整完数据库连接配置之后,就可以执行数据库的迁移操作,从而实现初始化项目模板中内置的一些数据表结构 or 初始化数据

这里,将 .DbMigrator 设置为启动项目,直接运行,等待程序的运行完成即可。此时,打开你所使用的 DBMS 工具,可以看到模板项目中定义的表已经迁移到了我们指定的数据库中

执行数据库迁移

可以看到,整个模板项目中包含了很多的东西,绝大多数的功能都不会是我们平常在开发业务功能时经常能够使用到的

2.1.3、运行程序

当数据库迁移成功之后就可以正式运行了,在这个模板程序中存在着两个 Web 应用,.HttpApi.Host.IdentityServer,分别对应于 API 接口的宿主以及 IdentityServer 的宿主,因为后续会移除掉 IdentityServer 相关的功能,所以这里就只运行 .HttpApi.Host 这一个站点了

.HttpApi.Host 设置为启动程序,这里并不会进行调试,所以直接通过 Ctrl + F5 运行,项目会自动打开 swagger 页面

Swagger

2.2、精简项目功能

当程序可以运行起来之后,就可以针对模板项目进行精简及改造,这里主要包含两块的内容,精简模板的功能以及简化项目的结构

2.2.1、精简模板功能

首先这里会移除掉 .IdentityServer 这个 Web 项目以及目前使用不到的 test 文件夹,从上面运行的 swagger 页面中就可以看到,初始化的模板中包含了一些业务功能开发中可能用不到的功能,而这些功能则是包含在项目所引用的 ABP 类库中的。因此,对于模板功能的精简则是将引用的一些用不到的 Volo.Abp.* 类库进行去除,仅保留我们所需的部分

这里我移除了下列的程序集引用,重新编译解决方案,不出意外会报很多的错误,因为具体的排错过程会涉及到很多,不太好用文字进行描述,所以这里就跳过了

  • Volo.Abp.Account.*

  • Volo.Abp.Identity.*

  • Volo.Abp.IdentityServer.*

  • Volo.Abp.PermissionManagement.*

  • Volo.Abp.TenantManagement.*

  • Volo.Abp.FeatureManagement.*

  • Volo.Abp.SettingManagement.*

  • Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy

报错信息

这里对于模板项目中的功能基本上都移除了,只保留了 audit 日志、后台任务、邮件通知、对象映射、EF Core 这类的基础服务

总结来说,对于移除功能后导致的编译报错,只需要将相关的类文件、引用直接删除就好,而对于功能移除之后产生的代码问题,就需要具体分析了,这类的问题基本上是初始化数据(DataSeed)的功能,我这边采取的是直接移除相关的功能

至此,当你进行到这一步时,也就可以顺势将 .DbMigrator 这个专门用于数据库迁移的控制台应用进行移除了,而对于迁移的这个功能,在下面的内容中我也将补充到别的类库上

哦对了,在移除上面的功能之后,你还需要在如下的类库中添加对应的 ABP 程序集引用,从而确保程序可以编译通过

  • .Application 引用 Volo.Abp.Ddd.Application
  • .Domain.Shared 引用 Volo.Abp.Validation
  • .HttpApi 引用 Volo.Abp.AspNetCore.Mvc
  • .HttpApi.Client 引用 Volo.Abp.Http.Client

如果不出意外的话,你的应用已经能够编译成功,并且可以再次运行了,从 swagger 也就可以看出,整个模板去掉了绝大多数的功能。当然,如果你觉得这个过程比较麻烦的话,也可以直接使用文章开头所列到的 github 的项目,然后在上面基于你的需求进行调整即可

精简功能

2.3、简化项目结构

让我们再回到最原始的后端模板项目中,整个后端解决方案的项目全局结构如下所示

解决方案结构

因为移除了单元测试的相关类库,从项目依赖关系图中就可以看到,整个解决方案中,包含了三个最顶层的项目,.IdentityServer.HttpApi.Host.DbMigrator,其它类库之间通过相互引用,构建出项目的分层基础

依赖关系

当然,在上面进行模板功能的精简时,已经将 .IdentityServer.DbMigrator 这一块进行了整体的移除

2.3.1、合并 EntityFramework Core 相关功能类库

因为这里选择了 EntityFramework Core(以下简称 EF Core)作为项目的 ORM,如果使用 Code First 模式的话,不可避免的会使用到 migrations 这样一个迁移的操作,在原始的模板中,存在着如下的三个类库与之存在关联

  • .DbMigrator:控制台程序,主要是为了进行数据库的迁移工作(migration)
  • .EntityFrameworkCore:集成 EF Core 到项目中,定义 DbContext 和领域中的数据访问仓储(Repository),在整个项目中提供数据持久化以及数据访问
  • .EntityFrameworkCore.DbMigrations:执行 EF Core 的迁移

可以看到,ABP 作为一个模块化的框架,对于每个类库的使用用途定义的非常清楚,但是,在实际的开发中,对于正式环境数据库的操作基本上都是交由 DBA 来执行的,EF Core 的 migration 更多的是在开发时进行使用。同时,如果真的这样划分的话,至少我遇到的绝大多数开发人员都是会叫的

介于上面已经将 .DbMigrator 进行了移除,因此,这里将对于 EF Core 的相关操作全部合并到 .EntityFrameworkCore 这个类库中

为了方便起见,我们先把 .EntityFrameworkCore.DbMigrations 中的文件全部拷贝一份到 .EntityFrameworkCore 这个类库中,然后直接在解决方案中移除掉原有的类库后再进行调整

PS:这里的 Migrations 文件夹以及 .EntityFrameworkCore.DbMigrations 的模块类就可以直接删除了,毕竟上面我们精简了模板的功能后,绝大多数的表也不复存在了 ,后面在类库合并后也会重新执行数据库迁移的操作

合并 EF Core 相关类库

因为现在会在 .EntityFrameworkCore 上执行 migration 的操作,所以这里需要添加上 EF Core 官方的 Design 组件包

Install-Package Microsoft.EntityFrameworkCore.Design

对于从 .DbMigrations 这个类库,其实是存在引用关系的,当整体删除之后,我们需要在 .HttpApi.Host 上添加对于 .EntityFrameworkCore 这个类库的引用。同时,对于拷贝过来的文件,其实是存在功能重复的问题,所以这里我们需要对这些文件进行合并归纳

首先,则是需要对于 DbContext 这个数据库上下文对象进行合并。从下图中可以看到,两个 DbContext 主要在配置实体映射关系的地方有所差异,因此这里直接将 MigrationsDbContext 这个类中关于 ABP 内置框架的实体映射配置拷贝过去即可,然后就可以直接删除了

合并 DbContext

对于每个 ABP 类库来说,都会存在一个入口的模块类,这里对比后就可以发现,直接将 EntityFrameworkCoreDbMigrationsModule 这个模块类删除即可,然后你需要将 .HttpApi.Host 项目中引用的这个模块类型改为 EntityFrameworkCoreModule

此时,编译解决方案,报错的问题主要是因为引用了已经删除的 DbContext,这里直接替换成现在使用的即可

修复 DbContext 引用错误的问题

这里还有一项需要注意,从上图中的第 27 行可以看到,这里获取的是 .DbMigrator 这个控制台应用中的配置文件,所以这里也需要同步修改成获取 .HttpApi.Host 项目中的配置文件

自此,涉及到 EF Core 相关功能的类库就合并完成了,定位到 .EntityFrameworkCore 这个类库,在控制台中就可以通过 migrations 命令来执行数据库的迁移工作。因为已经执行过一次了,所以直接将原来的库删除即可

-- 1、创建迁移文件
dotnet ef migrations add Initialize

-- 2、应用到数据库中
dotnet ef database update

PS:这里使用的是 EF Core tools 这么一个 dotnet tool,如果控制台提示你找不到命令的话,你需要先安装该工具到你的电脑上

dotnet tool install --global dotnet-ef

等待迁移工作的完成,数据库也重新生成了对应的表,此时再次运行项目,系统运行无误后即可进行后续的操作

迁移完成

2.3.2、合并 API 宿主相关功能

一般来说,我们会在 ASP.NET Core 项目中来定义 Controller,并以此作为整个接口项目的宿主程序,在 ABP 中,涉及到 API 接口的包含了如下的三个类库

  • .HttpApi:定义 API 接口的 controller
  • .HttpApi.Client:用于设置其它 C# 程序调用该 API 的 HTTP 代理
  • .HttpApi.Host:API 接口的宿主程序

这里的 .HttpApi.Client 的类库我们使用不到,所以直接删除即可,对于剩下的两个类库将进行合并,统一至 .HttpApi.Host 这个 ASP.NET Core 项目中

对于这两个类库的合并很简单,直接将 .HttpApi 项目中的类文件直接拷贝到 .HttpApi.Host 中即可,然后将模块类中的配置进行移动,最后直接删除 .HttpApi 类库,并将相关引用删除即可

合并 API 相关功能

至此,整个模板项目的简化也就结束了,在保留 ABP 的设计思想下,基于开发现状,构建了一个相对单一的模板项目,调整后的项目引用关系图如下所示

项目引用关系图

2.4、搭建项目脚手架

当整个调整完成之后,后续再创建一个新的项目时不可能再执行一次这样的操作,因此这里会创建一个 nuget 包进行发布,这样后面就可以直接通过 dotnet cli 命令来直接创建项目来使用

对于搭建项目模板的过程这里就不详细描述了,如果有需要的同学,可以参考博客园中的这一篇文章(打造自己的.NET Core项目模板),在这个过程中我们需要新建两个文件 template.json 以及 Ingos.Abp.Templates.csproj ,调整后的项目文件夹结构如下所示

项目脚手架结构

这里列出来了我目前使用的配置,你可以进行参考,如果你需要添加别的参数的话,可以参考官网文档(dotnet new 自定义模板

{
  "$schema": "http://json.schemastore.org/template",
  "author": "Danvic Wang",
  "classifications": [ "Web/WebAPI" ],
  "name": "Ingos Web API with ABP Framework",
  "identity": "Ingos.Abp.Templates",
  "shortName": "ingos-abp",
  "tags": {
    "language": "C#",
    "type": "project"
  },
  "sourceName": "IngosAbpTemplate",
  "preferNameDirectory": true
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <PackageType>Template</PackageType>
    <PackageVersion>1.0.1</PackageVersion>
    <PackageId>Ingos.Abp.Templates</PackageId>
    <Title>Ingos.Abp.Templates</Title>
    <Authors>Danvic Wang</Authors>
    <Description>Ingos Web API with ABP Framework</Description>
    <PackageTags>dotnet-new;templates;abp;domain-driven-design</PackageTags>

    <TargetFramework>net5.0</TargetFramework>

    <IncludeContentInPack>true</IncludeContentInPack>
    <IncludeBuildOutput>false</IncludeBuildOutput>
    <ContentTargetFolders>content</ContentTargetFolders>
    <NoWarn>$(NoWarn);NU5128</NoWarn>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
    <Copyright>Copyright (c) 2021 Danvic Wang</Copyright>
    <PackageIcon>logo.png</PackageIcon>
    <Product>Ingos.Abp.Templates</Product>
    <Company>Danvic Wang</Company>
    <RepositoryUrl>https://github.com/danvic712/ingos-abp-api-template</RepositoryUrl>
    <PackageProjectUrl>https://github.com/danvic712/ingos-abp-api-template</PackageProjectUrl>
    <RepositoryType>git</RepositoryType>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="templates\**\*" Exclude="templates\.vs\**;templates\**\Logs\**;templates\**\bin\**;templates\**\obj\**;" />
    <Compile Remove="**\*" />
  </ItemGroup>

  <ItemGroup>
    <None Include="resource\images\logo.png">
      <Pack>True</Pack>
      <PackagePath></PackagePath>
    </None>
  </ItemGroup>
</Project>

当配置定义完成之后,定位到 Ingos.Abp.Templates.csproj 所在的路径,执行 dotnet pack -o . 命令即可生成一个包含版本号的 .nupkg 文件,之后就可以将该文件上传到公有 or 私有的 nuget 仓库中供别人进行下载使用

以我这里创建的项目为例,因为我已经上传到 nuget 官方仓库上了,因此,你可以使用如下的命令进行安装

dotnet new -i Ingos.Abp.Templates

安装项目模板

安装完成后就可以通过 dotnet 命令进行项目的创建,在最新版的 VS 中,你也可以直接通过 IDE 来使用该模板进行项目的创建,相对来说也就更方便了,至此整个模板的精简的操作也就结束了,希望可以对你有所帮助

通过 VS 创建项目