浅入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.ContractsAbpBase.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.ContractsAbpBase.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.ApplicationApbBase.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 -> ....

你可以在每个 ModuleConfigureServices 函数中打印控制台信息,然后启动程序进行测试,看看打印顺序。

对于 ABP 的介绍,大家可以看文档,这里就不搬文档的内容了。

浅入ABP(1):搭建基础结构的 ABP 解决方案的更多相关文章

  1. 浅入 ABP 系列(4):事件总线

    浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...

  2. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  3. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

  4. 关于使用ABP框架搭建的项目升级时需要注意的问题汇总

    ABP理论学习总目录 一步一步使用ABP框架搭建正式项目系列教程 ABP之Module-Zero学习目录 本篇目录 说明 升级方法 问题_01:Log4Net导致编译不成功 2015/12/18更新 ...

  5. 浅入深出Vue:环境搭建

    浅入深出Vue:环境搭建 工欲善其事必先利其器,该搭建我们的环境了. 安装NPM 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的NodeJS Windows安装程序 下载下来后,直 ...

  6. NET使用ABP框架搭建项目

    NET使用ABP框架搭建博客项目(一) 有很多学NET开发的小伙伴建项目都比较茫然,我用什么开发?我都使用什么框架?我怎么起名字?种种问题,让一些低等.中等的工程师(甚至是高级工程师)很烦躁. 推荐一 ...

  7. 使用 Abp.Zero 搭建第三方登录模块(一):原理篇

    ​第三方登录是基于用户在第三方平台上(如微信,QQ, 百度)已有的账号来快速完成系统的登录.注册-登录等功能. 微信的鉴权 以微信的鉴权为例: 假如你的网站有一个扫码登录的功能,会弹出一个由微信提供的 ...

  8. 浅入 AutoMapper

    目录 浅入 AutoMapper AutoMapper 基本使用 映射配置 映射检查 性能 Profile 配置 依赖注入 表达式与 DTO 浅入 AutoMapper 在 Nuget 搜索即可安装, ...

  9. 基于DDD的现代ASP.NET开发框架--ABP系列之2、ABP入门教程

    基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boi ...

随机推荐

  1. element-ui 格式化树形数组在table组件中展示(单元格合并)

    最近做的项目涉及到很多单元格合并问题,element-ui组件对于单元格合并的处理虽然很灵活,但是需要事先计算好每个单元格合并的rowspan和colspan,直接在span-method属性中计算实 ...

  2. vue.extend和vue.component的区别

    vue.extend 使用基础 Vue 构造器函数,通过原型继承,(返回)创建一个"子类"(构造器).参数是一个包含组件选项的对象. const Sub = function Vu ...

  3. JavaScript设计模式之策略模式【组合委托】

    前言:语言只是工具,思想才是核心 今天要总结的是 策略模式 策略在开发中的应用非常广泛,所以也是非常常见且使用的设计模式. 在实际开发中,往往在实现一个功能时,有多种解决方案可行. 常见场景: 解压: ...

  4. Jmeter 常用函数(3)- 详解 __RandomString

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 根据指定的字符产生一个随机字符串 语法 ...

  5. Four Fundamental Operations(JS) --结对项目

    一.Github地址:https://github.com/BayardM/Four-Fundamental-Operations (本项目由鲍鱼铭3118004995 和 许铭楷3118005023 ...

  6. 实用的git log用法

    git log可以很方便地查看日志,可以根据自己需要,将日志按照特定格式显示,或者输出某种格式. 最原始的输出样式: $ git log commit ca82a6dff817ec66f4434200 ...

  7. Charles 断点修改Response

    前言: 我们可以通过map功能进行重定向,但如果同一个域名进行的是不同请求与返回.此时map在这里就不适用了. 我们可以通关对某一请求进行断点,在进行修改请求或者返回.这样就可以满足我们的需求了. 一 ...

  8. C# DataTable查询示例

    代码 public void Test() { #region 初始化数据 /* 数据 张三 语文 34.00 张三 数学 58.00 张三 英语 61.00 李四 语文 45.00 李四 数学 87 ...

  9. 基于Nodejs的sequelize操纵数据库

    ## 使用基于ORM架构的sequelize操纵数据库 ### 1.技术背景 ```Sequelize是一个基于promise的关系型数据库ORM框架,*********************技术文 ...

  10. Python Selenium 之数据驱动测试的实现

    数据驱动模式的测试好处相比普通模式的测试就显而易见了吧!使用数据驱动的模式,可以根据业务分解测试数据,只需定义变量,使用外部或者自定义的数据使其参数化,从而避免了使用之前测试脚本中固定的数据.可以将测 ...