浅入ABP(1):搭建基础结构的 ABP 解决方案

简介: 浅入ABP(1):搭建基础结构的 ABP 解决方案

搭建项目基础结构


打开 VS 2019,创建一个解决方案,然后删除解决方案的项目,变成空解决方案。本系列教程将使用 AbpBase 来命名解决方案和项目前缀。


在解决方案中新建一个解决方案文件夹,名字为 src,用来存放项目源码。

微信图片_20220504112317.png

我们将要创建一个类似下图这样的层次结构的解决方案,只是没有 HttpApi.Client ,另外.EntityFrameCore 改成了 .Database

微信图片_20220504112320.png

下面我们来创建需要的项目结构,和了解每一个项目的作用。


AbpBase.Domain.Shared


此项目是最底层的模块,且不依赖其他模块,主要用于定义各种枚举(enums)、全局常量(constants)、静态变量(static)、启动依赖配置(options)等。还可以在此为程序设置一个标准,限制各个层次的模块都必须符合此标准的要求。


例如 规定API 请求的一般参数,字符串长度不得大于 256 个字符,我们可以这样写:

public static Whole
{
  public const int MaxLength = 256;
}
[StringLength(maximumLength:Whole.MaxLength)]


总之,这个模块用于定义各种全局的、共享的内容(变量、枚举等),一般不包含服务。


创建过程

在解决方案中新建 .NET Standard 项目,名称为 AbpBase.Domain.Shared,然后通过 Nuget 添加 Volo.Abp.Core 包,版本为 3.1.2

微信图片_20220504112323.png

然后新建 一个 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()]


AbpBase.Domain


此项目用于定义各种用于传递数据的类。例如数据库实体、用于做参数传递的模型类等。

创建过程

我们在解决方案的src 文件夹,添加一个新的项目,名字为 AbpBase.Domain,然后引用 AbpBase.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)
        {
        }
    }
}


AbpBase.Domain 依赖于 AbpBase.Domain.Shared


AbpBase.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)
        {
        }
    }
}


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)
        {
        }
    }
}

这样,我们的项目将可以支持三种数据库的使用。


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)
        {
        }
    }
}


AbpBase.HttpApi


此项目用于编写 API 控制器。

创建过程

创建 一个 .NET Core 控制台项目,名字为 AbpBase.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.ApplicationAbpBase.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 的介绍,大家可以看文档,这里就不搬文档的内容了。

相关文章
|
26天前
|
Java Maven 数据库
一文教会你如何进行Rest微服务构建 案例工程模块。教会你如何创建父子工程
这篇文章介绍了如何在微服务架构中创建父子工程模块,并通过RESTful服务的方式构建微服务通用案例,包括服务提供者和消费者的基本实现,以及数据库的创建和测试服务的步骤。
一文教会你如何进行Rest微服务构建 案例工程模块。教会你如何创建父子工程
|
2月前
|
开发框架 前端开发 JavaScript
ABP开发框架前后端开发系列---(16)ABP框架升级最新版本的经验总结
ABP开发框架前后端开发系列---(16)ABP框架升级最新版本的经验总结
个人若依框架学习大杂烩
个人若依框架学习大杂烩
142 0
|
开发框架 JSON 前端开发
浅入ABP(2):添加基础集成服务
浅入ABP(2):添加基础集成服务
634 0
浅入ABP(2):添加基础集成服务
|
缓存 .NET 开发框架
【ABP框架系列学习】N层架构(3)
原文:【ABP框架系列学习】N层架构(3) 目录 0.引言 1.DDD分层 2.ABP应用构架模型 客户端应用程序(Client Applications) 表现层(Presentation Layer) 分布式服务层(Distributed Service Layer) 应用层(Application Layer) 领域层 基础设施层 3.使用ABP项目模版快速生成应用程序 0.引言 应用程序的分层是一种广泛接受的技术, 可以降低复杂度和提高代码的可重用性。
1718 0
|
前端开发 JavaScript UED
|
Web App开发
ABP架构学习系列三:手工搭建ABP框架
  由于公司的项目才接触到ABP这个框架,当时就觉得高大上,什么IOC、AOP、ddd各种专业词汇让人激情 澎湃,但在使用过程中碰到了许多坑,可能也许是没有去看源码导致的,但工作确实没有那么多时间让人去慢慢研究。
4004 0
|
Web App开发 前端开发 .NET
【ABP框架系列学习】模块系统(4)
原文:【ABP框架系列学习】模块系统(4) 0.引言 ABP提供了构建模块和通过组合模块以创建应用程序的基础设施。一个模块可以依赖于另外一个模块。通常,程序集可以认为是模块。如果创建多个程序集的应用程序,建议为每个程序集创建模块定义。
1576 0
|
前端开发 JavaScript .NET
【ABP框架系列学习】介绍篇(1)
原文:【ABP框架系列学习】介绍篇(1)   0.引言 该系列博文主要在【官方文档】及【tkbSimplest】ABP框架理论研究系列博文的基础上进行总结的,或许大家会质问,别人都已经翻译过了,这不是多此一举吗?原因如下: 1.【tkbSimplest】的相关博文由于撰写得比较早的,在参照官方文档学习的过程中,发现部分知识未能及时同步(当前V4.0.2版本),如【EntityHistory】、【Multi-Lingual Engities】章节未涉及、【Caching】章节没有Entity Caching等内容。
1899 0